// ============================================================
// LSPD · Ticketsystem (öffentlich, LSMD-Pattern)
// ============================================================

const { useState, useEffect, useCallback } = React;

const IC_AUTH_ERRORS = {
  no_character: 'Kein IC-Charakter zu deiner Discord-ID gefunden. Bitte zuerst einen Charakter anlegen.',
  api_not_configured: 'Charakter-API ist nicht konfiguriert.',
  api_unauthorized: 'Charakter-API: Zugriff verweigert.',
  rate_limit: 'Zu viele Anfragen · bitte kurz warten und erneut anmelden.',
  api_error: 'Charakter-API vorübergehend nicht erreichbar.',
};

const IC_LOCKED_HINT = 'Automatisch übernommen · nicht änderbar';
const IC_LOCKED_INPUT_CLS = 'w-full h-10 rounded-md border border-line/60 px-3 text-sm opacity-70 cursor-not-allowed lspd-input';
const TICKET_RETURN = '/ticket';

function icFormFromApplicant(applicant) {
  const locked = applicant?.ic_locked;
  if (!locked) return {};
  return {
    vorname: locked.vorname || '',
    nachname: locked.nachname || '',
    telefon: locked.telefon || '',
  };
}

function fieldVisible(field, form) {
  if (!field.showIf) return true;
  return String(form[field.showIf.field] || '').toLowerCase() === String(field.showIf.value).toLowerCase();
}

function TicketDynamicField({ field, value, onChange, form, locked }) {
  if (!fieldVisible(field, form)) return null;
  const set = (v) => onChange(field.key, v);

  if (locked && (field.type === 'text' || field.type === 'date')) {
    return (
      <Field label={field.label} required={field.required} hint={IC_LOCKED_HINT}>
        <input type="text" className={IC_LOCKED_INPUT_CLS} value={value || ''} readOnly tabIndex={-1} />
      </Field>
    );
  }
  if (field.type === 'textarea') {
    return (
      <Field label={field.label} required={field.required} hint={field.minLength ? `min. ${field.minLength} Zeichen` : ''}>
        <TextArea rows={field.rows || 5} value={value || ''} onChange={e => set(e.target.value)} />
      </Field>
    );
  }
  if (field.type === 'yesno') {
    return (
      <Field label={field.label} required={field.required}>
        <div className="flex gap-2">
          {[['ja', 'Ja'], ['nein', 'Nein']].map(([k, l]) => (
            <button key={k} type="button" onClick={() => set(k)}
              className={`px-4 h-9 rounded-md text-sm font-semibold border ${String(value).toLowerCase() === k ? 'border-accent bg-[var(--c-accent-soft)] text-accent' : 'border-line text-muted'}`}>
              {l}
            </button>
          ))}
        </div>
      </Field>
    );
  }
  return (
    <Field label={field.label} required={field.required}>
      <TextInput value={value || ''} onChange={e => set(e.target.value)} />
    </Field>
  );
}

function IcTicketPublicPage({ go, alarm, onAlarm }) {
  const [applicant, setApplicant] = useState(null);
  const [authLoading, setAuthLoading] = useState(true);
  const [categories, setCategories] = useState([]);
  const [tab, setTab] = useState('new');
  const [step, setStep] = useState('pick');
  const [catId, setCatId] = useState('');
  const [form, setForm] = useState({});
  const [myTickets, setMyTickets] = useState([]);
  const [myScope, setMyScope] = useState('active');
  const [myLoading, setMyLoading] = useState(false);
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState('');

  const cat = categories.find(c => c.id === catId);
  const isAnon = catId === 'beschwerde' && String(form.anonym || '').toLowerCase() === 'ja';
  const needsDiscord = catId !== 'beschwerde' || !isAnon;

  const refreshMy = useCallback(async (scope = myScope) => {
    if (!applicant?.discord_id) return;
    setMyLoading(true);
    try {
      const d = await window.LSPD.icMyTickets(scope === 'closed');
      setMyTickets(d.tickets || []);
    } catch {
      setMyTickets([]);
    } finally {
      setMyLoading(false);
    }
  }, [applicant?.discord_id, myScope]);

  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const authErr = params.get('error');
    if (authErr && IC_AUTH_ERRORS[authErr]) {
      setErr(IC_AUTH_ERRORS[authErr]);
      window.history.replaceState({}, '', window.location.pathname);
    }
    Promise.all([
      window.LSPD.icTicketCategories(),
      window.LSPD.loadApplicant().catch(() => ({ loggedIn: false })),
    ]).then(async ([catData, a]) => {
      setCategories(catData.categories || []);
      if (a?.loggedIn && a.applicant) {
        setApplicant(a.applicant);
        const d = await window.LSPD.icMyTickets(false);
        setMyTickets(d.tickets || []);
      }
    }).catch((e) => {
      console.error('[Tickets]', e);
      setErr('Ticketsystem konnte nicht geladen werden.');
    }).finally(() => setAuthLoading(false));
  }, []);

  useEffect(() => {
    if (tab === 'mine' && applicant?.discord_id) refreshMy();
  }, [tab, applicant?.discord_id, refreshMy]);

  const goNewTicket = () => {
    setTab('new');
    setStep('pick');
    setCatId('');
    setErr('');
  };

  const goMyTickets = () => {
    setTab('mine');
    setStep('pick');
    setCatId('');
    setErr('');
  };

  const pickCategory = (id) => {
    const c = categories.find(x => x.id === id);
    if (!c) return;
    setTab('new');
    setCatId(id);
    setErr('');
    if (id !== 'beschwerde' && !applicant) {
      setStep('auth');
      return;
    }
    setForm({ ...icFormFromApplicant(applicant) });
    setStep('form');
  };

  const submit = async () => {
    if (!cat) return;
    if (needsDiscord && !applicant) {
      setErr('Bitte zuerst mit Discord verifizieren.');
      setStep('auth');
      return;
    }
    setBusy(true);
    setErr('');
    try {
      const d = await window.LSPD.icCreateTicket(catId, form);
      if (isAnon) {
        setStep('done');
        setTab('new');
        setForm({});
        setCatId('');
      } else {
        setMyTickets(prev => [d.ticket, ...prev.filter(t => t.id !== d.ticket.id)]);
        setTab('mine');
        setStep('pick');
        setForm({});
        setCatId('');
      }
    } catch (e) {
      setErr(e.message || 'Ticket konnte nicht erstellt werden.');
    } finally {
      setBusy(false);
    }
  };

  if (authLoading) {
    return (
      <div className="min-h-screen dotgrid grid place-items-center relative z-[2]">
        <p className="text-muted text-sm">Lädt …</p>
      </div>
    );
  }

  return (
    <div className="min-h-screen dotgrid relative z-[2]">
      <NavBar go={go} page="tickets" alarm={alarm} onAlarm={onAlarm} />
      <div className="mx-auto max-w-3xl px-5 py-14">
        <button onClick={() => go('home')} className="text-sm text-muted hover:text-ink flex items-center gap-1.5 mb-6">
          <Icon name="ArrowLeft" size={16} /> Startseite
        </button>
        <Label>Ticketsystem</Label>
        <h1 className="text-3xl font-black tracking-tight mt-1">Anliegen &amp; Beschwerden</h1>
        <p className="text-muted mt-2 text-sm">Anzeigen, Dokumente und Beschwerden ans LSPD · Bearbeitung durch zuständige Beamte</p>

        {err && (step === 'pick' || step === 'form' || step === 'auth') && tab === 'new' && (
          <p className="mt-4 text-sm text-danger rounded-lg border border-danger/30 bg-danger/10 px-4 py-3">{err}</p>
        )}

        {applicant && (
          <div className="mt-4 flex items-center gap-3 rounded-lg border border-line p-3 bg-card/40">
            {applicant.avatar ? <img src={applicant.avatar} alt="" className="h-10 w-10 rounded-full object-cover" /> : <Avatar name={applicant.display_name} size={40} />}
            <div className="flex-1 min-w-0">
              <div className="font-bold text-sm truncate">{applicant.display_name}</div>
              <div className="text-xs text-muted">@{applicant.username}</div>
            </div>
            <button type="button" className="text-xs text-muted hover:text-ink" onClick={() => window.LSPD.logoutApplicant(TICKET_RETURN)}>Abmelden</button>
          </div>
        )}

        {step !== 'done' && (
          <div className="mt-6 flex gap-1 border-b border-line">
            {[['new', 'Neues Ticket'], ['mine', 'Meine Tickets']].map(([id, label]) => (
              <button key={id} type="button" onClick={id === 'new' ? goNewTicket : goMyTickets}
                className={`relative px-4 h-10 text-sm font-semibold ${tab === id ? 'text-ink' : 'text-muted hover:text-ink'}`}>
                {label}
                {tab === id && <span className="absolute bottom-0 left-0 right-0 h-0.5 bg-accent rounded-t" />}
              </button>
            ))}
          </div>
        )}

        {tab === 'new' && step === 'pick' && (
          <div className="mt-6 grid sm:grid-cols-2 gap-3">
            {categories.map(c => (
              <button key={c.id} type="button" onClick={() => pickCategory(c.id)}
                className="text-left rounded-lg border border-line p-4 hover:border-accent/50 transition-colors bg-card/30">
                <div className="font-bold flex items-center gap-2 flex-wrap">
                  {c.label}
                  {c.allowAnonymous && (
                    <span className="text-[9px] uppercase font-bold text-muted border border-line px-1.5 py-0.5 rounded">Anonym möglich</span>
                  )}
                </div>
                <div className="text-xs text-muted mt-1">{c.description}</div>
              </button>
            ))}
            {categories.length === 0 && (
              <Card className="sm:col-span-2 p-8 text-center text-sm text-muted">Keine Kategorien verfügbar.</Card>
            )}
          </div>
        )}

        {tab === 'new' && step === 'auth' && (
          <Card className="mt-8 p-8 text-center">
            <Icon name="MessageCircle" size={32} className="text-discord mx-auto" />
            <h3 className="mt-4 font-bold">Discord-Verifizierung erforderlich</h3>
            <p className="text-sm text-muted mt-2 max-w-md mx-auto">
              Melde dich mit Discord an, um dieses Ticket einzureichen.
            </p>
            <div className="mt-6 flex flex-wrap justify-center gap-2">
              <Btn variant="ghost" onClick={goNewTicket}>← Zurück</Btn>
              <Btn variant="discord" icon="MessageCircle" onClick={() => window.LSPD.loginApplicant(TICKET_RETURN)}>
                Mit Discord verifizieren
              </Btn>
            </div>
          </Card>
        )}

        {tab === 'new' && step === 'form' && cat && (
          <Card className="mt-6 p-6">
            <button type="button" className="text-sm text-muted mb-4 hover:text-ink" onClick={goNewTicket}>← Kategorie wählen</button>
            <h2 className="text-xl font-bold mb-4">{cat.label}</h2>
            {isAnon && (
              <p className="text-sm text-muted mb-4 rounded-md border border-line bg-bg/40 px-3 py-2">
                Anonyme Meldung — persönliche Angaben werden nicht gespeichert.
              </p>
            )}
            {needsDiscord && !applicant && (
              <p className="text-sm text-danger mb-4">Discord-Verifizierung erforderlich, bevor du absenden kannst.</p>
            )}
            <div className="grid sm:grid-cols-2 gap-4">
              {cat.fields.map(f => {
                const locked = !!(f.locked && applicant?.ic_locked && !isAnon);
                return (
                  <div key={f.key} className={f.type === 'textarea' ? 'sm:col-span-2' : ''}>
                    <TicketDynamicField field={f} value={form[f.key]} form={form} locked={locked}
                      onChange={(k, v) => setForm(s => ({ ...s, [k]: v }))} />
                  </div>
                );
              })}
            </div>
            {err && <p className="text-sm text-danger mt-3">{err}</p>}
            <div className="mt-6 flex justify-end gap-2">
              <Btn variant="ghost" onClick={goNewTicket}>Abbrechen</Btn>
              {needsDiscord && !applicant ? (
                <Btn variant="discord" icon="MessageCircle" onClick={() => setStep('auth')}>Mit Discord verifizieren</Btn>
              ) : (
                <Btn icon="Send" onClick={submit} disabled={busy}>
                  {busy ? 'Wird gesendet …' : (isAnon ? 'Anonym absenden' : 'Ticket einreichen')}
                </Btn>
              )}
            </div>
          </Card>
        )}

        {tab === 'new' && step === 'done' && (
          <Card className="mt-8 p-10 text-center">
            <Icon name="CheckCircle" size={40} className="text-success mx-auto" />
            <h3 className="mt-4 text-2xl font-bold">Anonym übermittelt</h3>
            <p className="text-sm text-muted mt-2 max-w-md mx-auto">
              Deine Beschwerde wurde an das LSPD weitergeleitet.
            </p>
            <Btn className="mt-6" onClick={() => { goNewTicket(); setForm({}); }}>Weiteres Anliegen</Btn>
          </Card>
        )}

        {tab === 'mine' && step === 'pick' && (
          <>
            {!applicant ? (
              <Card className="mt-6 p-8 text-center">
                <Icon name="MessageCircle" size={32} className="text-discord mx-auto" />
                <h3 className="mt-4 font-bold">Mit Discord anmelden</h3>
                <p className="text-sm text-muted mt-2 max-w-md mx-auto">
                  Um deine Tickets zu sehen, verifiziere dich mit Discord.
                </p>
                <Btn className="mt-6" variant="discord" icon="MessageCircle" onClick={() => window.LSPD.loginApplicant(TICKET_RETURN)}>
                  Mit Discord verifizieren
                </Btn>
              </Card>
            ) : (
              <>
                <div className="mt-6 flex gap-1 border-b border-line">
                  {[['active', 'Aktiv'], ['closed', 'Geschlossen']].map(([id, label]) => (
                    <button key={id} type="button" onClick={() => { setMyScope(id); refreshMy(id); }}
                      className={`relative px-4 h-9 text-sm font-semibold ${myScope === id ? 'text-ink' : 'text-muted'}`}>
                      {label}
                      {myScope === id && <span className="absolute bottom-0 left-0 right-0 h-0.5 bg-accent rounded-t" />}
                    </button>
                  ))}
                </div>
                {myLoading ? (
                  <p className="mt-8 text-sm text-muted text-center">Tickets werden geladen …</p>
                ) : myTickets.length === 0 ? (
                  <Card className="mt-4 p-10 text-center">
                    <Icon name={myScope === 'closed' ? 'Archive' : 'Inbox'} size={36} className="text-muted mx-auto opacity-60" />
                    <h3 className="mt-4 font-bold">{myScope === 'closed' ? 'Keine geschlossenen Tickets' : 'Noch keine Tickets'}</h3>
                    <p className="text-sm text-muted mt-2 max-w-sm mx-auto">
                      {myScope === 'closed'
                        ? 'Abgeschlossene Anliegen erscheinen hier.'
                        : 'Wähle unter „Neues Ticket“ eine Kategorie und reiche dein Anliegen ein.'}
                    </p>
                    {myScope === 'active' && (
                      <Btn className="mt-6" variant="outline" onClick={goNewTicket}>Neues Ticket erstellen</Btn>
                    )}
                  </Card>
                ) : (
                  <Card className="mt-4 p-4">
                    <h3 className="font-bold text-sm mb-3">{myScope === 'closed' ? 'Geschlossene Tickets' : 'Deine aktuellen Tickets'}</h3>
                    <div className="flex flex-col gap-1">
                      {myTickets.map(t => (
                        <div key={t.id} className="flex flex-wrap items-center justify-between gap-2 px-3 py-3 rounded-md border border-line/60 bg-bg/30">
                          <div>
                            <div className="font-semibold text-sm">{t.ticketNumber} · {t.betreff || t.categoryLabel}</div>
                            <div className="text-[11px] text-muted">{t.categoryLabel}</div>
                          </div>
                          <span className="text-[10px] font-bold uppercase px-2 py-0.5 rounded"
                            style={{ color: t.statusColor, background: `${t.statusColor}22` }}>{t.statusLabel}</span>
                        </div>
                      ))}
                    </div>
                  </Card>
                )}
              </>
            )}
          </>
        )}
      </div>
      <Footer go={go} />
    </div>
  );
}

Object.assign(window, { IcTicketPublicPage });
