// Admin/Moderator-Oberfläche — Login, Treffen verwalten, ad-hoc starten.

function AdminApp({ onEnterCall, onLogout }) {
  const [authed, setAuthed] = React.useState(window.Api?.isAdminAuthed() ?? false);

  if (!authed) {
    return <AdminLogin onAuthed={() => setAuthed(true)}/>;
  }
  return <AdminDashboard onEnterCall={onEnterCall} onLogout={() => {
    window.Api.clearAdminToken();
    setAuthed(false);
    onLogout?.();
  }}/>;
}

function AdminLogin({ onAuthed }) {
  const [user, setUser] = React.useState('moderator');
  const [pass, setPass] = React.useState('');
  const [error, setError] = React.useState(null);
  const [loading, setLoading] = React.useState(false);

  async function submit(e) {
    e.preventDefault();
    if (!user || !pass) return;
    if (!window.Api?.isConfigured()) {
      setError('Backend nicht konfiguriert. Bitte config.js ausfüllen.');
      return;
    }
    setLoading(true);
    setError(null);
    try {
      const { token, expiresIn } = await window.Api.login(user, pass);
      window.Api.setAdminToken(token, expiresIn);
      onAuthed();
    } catch (err) {
      setError(err.message || 'Login fehlgeschlagen');
      setLoading(false);
    }
  }

  return (
    <div style={{ minHeight: '100vh', display: 'grid', placeItems: 'center', padding: 20 }}>
      <div className="card" style={{ maxWidth: 440, width: '100%', padding: 40 }} role="region" aria-label="Moderator-Anmeldung">
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 28 }}>
          <div className="brand-mark" style={{ width: 56, height: 56, borderRadius: 18, background: 'var(--blue-700)', display: 'grid', placeItems: 'center' }} aria-hidden="true">
            <Icon.Lock size={28}/>
          </div>
          <div>
            <div className="muted" style={{ fontSize: 13, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.06em' }}>Mitreden</div>
            <h1 className="h-2" style={{ margin: 0 }} data-focus-target tabIndex="-1">Moderator-Anmeldung</h1>
          </div>
        </div>

        <form onSubmit={submit} aria-label="Anmeldung">
          <div className="field">
            <label htmlFor="adm-user">Benutzername</label>
            <input id="adm-user" type="text" value={user} onChange={e => setUser(e.target.value)} autoComplete="username"/>
          </div>
          <div className="field">
            <label htmlFor="adm-pass">Passwort</label>
            <input id="adm-pass" type="password" value={pass} onChange={e => setPass(e.target.value)} autoComplete="current-password"/>
          </div>

          {error && (
            <div role="alert" style={{ background: 'var(--red-soft)', color: 'var(--red)', padding: '12px 16px', borderRadius: 12, fontSize: 15, fontWeight: 700, marginBottom: 16 }}>
              {error}
            </div>
          )}

          <button type="submit" className="btn btn-primary btn-block" disabled={loading || !user || !pass}>
            {loading ? 'Anmelden...' : 'Anmelden'}
          </button>
        </form>

        <div className="muted" style={{ fontSize: 13, marginTop: 18, textAlign: 'center' }}>
          Nur für Moderatoren. Teilnehmer brauchen kein Passwort.
        </div>
      </div>
    </div>
  );
}

function AdminDashboard({ onEnterCall, onLogout }) {
  const [meetings, setMeetings] = React.useState(null);
  const [error, setError] = React.useState(null);
  const [view, setView] = React.useState('list');
  const [actioning, setActioning] = React.useState(null);
  const [dialog, setDialog] = React.useState(null);

  async function load() {
    try {
      const { meetings } = await window.Api.listAllMeetings();
      setMeetings(meetings || []);
      setError(null);
    } catch (e) {
      if (e.status === 401) {
        window.Api.clearAdminToken();
        onLogout?.();
        return;
      }
      if (window.showToast) {
        window.showToast('Das Laden hat nicht geklappt. Bitte versuche es noch einmal.', 'error');
      }
      setError(e.message);
    }
  }

  React.useEffect(() => {
    load();
    const t = setInterval(load, 10000);
    return () => clearInterval(t);
  }, []);

  function startAdHoc() {
    setDialog({
      type: 'prompt',
      message: 'Worüber wollt ihr reden? (Titel des Treffens)',
      defaultValue: '',
      onSubmit: async (title) => {
        setDialog(null);
        if (!title) return;
        setActioning('ad-hoc');
        try {
          const conn = await window.Api.adHocMeeting(title);
          onEnterCall(conn);
        } catch (e) {
          if (window.showToast) window.showToast('Das Treffen konnte nicht gestartet werden. Bitte versuche es noch einmal.', 'error');
          setActioning(null);
        }
      },
      onCancel: () => setDialog(null),
    });
  }

  async function startMeeting(m) {
    setActioning(m.id);
    try {
      const conn = await window.Api.startMeeting(m.id);
      onEnterCall(conn);
    } catch (e) {
      if (window.showToast) window.showToast('Das Treffen konnte nicht gestartet werden. Bitte versuche es noch einmal.', 'error');
      setError(e.message);
      setActioning(null);
    }
  }

  async function moderateMeeting(m) {
    setActioning(m.id);
    try {
      const conn = await window.Api.moderateMeeting(m.id);
      onEnterCall(conn);
    } catch (e) {
      if (window.showToast) window.showToast('Das hat leider nicht geklappt. Bitte versuche es noch einmal.', 'error');
      setError(e.message);
      setActioning(null);
    }
  }

  function endMeeting(m) {
    setDialog({
      type: 'confirm',
      message: `Treffen "${m.title}" wirklich beenden?`,
      onConfirm: async () => {
        setDialog(null);
        setActioning(m.id);
        try {
          await window.Api.endMeeting(m.id);
          await load();
        } catch (e) {
          if (window.showToast) window.showToast('Das Beenden hat nicht geklappt. Bitte versuche es noch einmal.', 'error');
          setError(e.message);
        }
        setActioning(null);
      },
      onCancel: () => setDialog(null),
    });
  }

  function deleteMeeting(m) {
    setDialog({
      type: 'confirm',
      message: `Treffen "${m.title}" wirklich löschen?`,
      onConfirm: async () => {
        setDialog(null);
        setActioning(m.id);
        try {
          await window.Api.deleteMeeting(m.id);
          await load();
        } catch (e) {
          if (window.showToast) window.showToast('Das Löschen hat nicht geklappt. Bitte versuche es noch einmal.', 'error');
          setError(e.message);
        }
        setActioning(null);
      },
      onCancel: () => setDialog(null),
    });
  }

  const running = (meetings || []).filter(m => m.status === 'running');
  const scheduled = (meetings || []).filter(m => m.status === 'scheduled')
    .sort((a, b) => (a.scheduledAt || '9999') < (b.scheduledAt || '9999') ? -1 : 1);
  const ended = (meetings || []).filter(m => m.status === 'ended')
    .sort((a, b) => (b.endedAt || '') < (a.endedAt || '') ? -1 : 1)
    .slice(0, 5);

  return (
    <div className="app">
      <a className="skip-link" href="#admin-main">
        Zum Inhalt springen
      </a>
      <header className="topbar" role="banner">
        <div className="brand">
          <div className="brand-mark" aria-hidden="true">
            <img src="/favicon.svg" width="30" height="30" alt=""/>
          </div>
          Mitreden
        </div>
        <span className="eyebrow"><Icon.Settings size={16} aria-hidden="true"/> Moderator-Bereich</span>
        <nav className="topbar-right" aria-label="Moderator-Navigation">
          <button className="btn btn-ghost" onClick={onLogout} style={{ padding: '8px 14px', fontSize: 15 }} aria-label="Vom Moderator-Bereich abmelden">
            Abmelden
          </button>
        </nav>
      </header>

      <main className="main" id="admin-main">
        {view === 'list' && (
          <>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', flexWrap: 'wrap', gap: 20, marginBottom: 24 }}>
              <div>
                <h1 className="h-display" data-focus-target tabIndex="-1">Treffen</h1>
                <p className="muted" style={{ fontSize: 20, marginTop: 8 }}>
                  Starten Sie ein Treffen oder planen Sie eines für später.
                </p>
              </div>
              <div style={{ display: 'flex', gap: 12, marginTop: 24, flexWrap: 'wrap' }}>
                <button className="btn btn-secondary" onClick={() => setView('new')}>
                  <Icon.Plus size={20} aria-hidden="true"/> Treffen planen
                </button>
                <button className="btn btn-primary" onClick={startAdHoc} disabled={actioning === 'ad-hoc'}>
                  <Icon.Play size={20} aria-hidden="true"/> {actioning === 'ad-hoc' ? 'Starte...' : 'Jetzt starten (ad hoc)'}
                </button>
              </div>
            </div>

            {error && (
              <div role="alert" style={{ background: 'var(--red-soft)', color: 'var(--red)', padding: '12px 16px', borderRadius: 12, fontSize: 15, fontWeight: 700, marginBottom: 16 }}>
                {error}
              </div>
            )}

            {meetings === null ? (
              <div className="muted" role="status" style={{ padding: 24 }}>Lädt...</div>
            ) : (
              <>
                {running.length > 0 && (
                  <section aria-labelledby="running-heading" style={{ marginBottom: 32 }}>
                    <h2 className="h-2" id="running-heading" style={{ marginBottom: 16, display: 'flex', alignItems: 'center', gap: 10 }}>
                      <span style={{ width: 12, height: 12, borderRadius: '50%', background: 'var(--red)', animation: 'pulse 1.6s ease-in-out infinite' }} aria-hidden="true"></span>
                      Läuft gerade
                    </h2>
                    {running.map(m => (
                      <MeetingRow
                        key={m.id}
                        meeting={m}
                        busy={actioning === m.id}
                        actions={[
                          { label: 'Moderieren', primary: true, onClick: () => moderateMeeting(m) },
                          { label: 'Beenden', danger: true, onClick: () => endMeeting(m) },
                        ]}
                      />
                    ))}
                  </section>
                )}

                <section aria-labelledby="scheduled-heading" style={{ marginBottom: 32 }}>
                  <h2 className="h-2" id="scheduled-heading" style={{ marginBottom: 16 }}>Geplante Treffen</h2>
                  {scheduled.length === 0 ? (
                    <div className="card-warm" style={{ padding: 24 }}>
                      <p className="muted" style={{ margin: 0 }}>Keine geplanten Treffen. Lege oben eins an.</p>
                    </div>
                  ) : (
                    scheduled.map(m => (
                      <MeetingRow
                        key={m.id}
                        meeting={m}
                        busy={actioning === m.id}
                        actions={[
                          { label: 'Starten', primary: true, onClick: () => startMeeting(m) },
                          { label: 'Löschen', onClick: () => deleteMeeting(m) },
                        ]}
                      />
                    ))
                  )}
                </section>

                {ended.length > 0 && (
                  <section aria-labelledby="ended-heading">
                    <h2 className="h-2" id="ended-heading" style={{ marginBottom: 16 }}>Beendete Treffen</h2>
                    {ended.map(m => (
                      <MeetingRow
                        key={m.id}
                        meeting={m}
                        busy={actioning === m.id}
                        actions={[
                          { label: 'Löschen', onClick: () => deleteMeeting(m) },
                        ]}
                      />
                    ))}
                  </section>
                )}
              </>
            )}
          </>
        )}

        {view === 'new' && (
          <NewMeetingForm
            onCancel={() => setView('list')}
            onSaved={async () => { await load(); setView('list'); }}
          />
        )}
      </main>

      {dialog && dialog.type === 'confirm' && (
        <ConfirmDialog
          message={dialog.message}
          onConfirm={dialog.onConfirm}
          onCancel={dialog.onCancel}
        />
      )}
      {dialog && dialog.type === 'prompt' && (
        <PromptDialog
          message={dialog.message}
          defaultValue={dialog.defaultValue}
          onSubmit={dialog.onSubmit}
          onCancel={dialog.onCancel}
        />
      )}
    </div>
  );
}

function MeetingRow({ meeting, busy, actions }) {
  const statusLabel = {
    running: 'Läuft',
    scheduled: 'Geplant',
    ended: 'Beendet',
  }[meeting.status] || meeting.status;
  const statusColor = {
    running: { bg: 'var(--red-soft)', fg: 'var(--red)' },
    scheduled: { bg: 'var(--green-soft)', fg: 'var(--green)' },
    ended: { bg: 'var(--line)', fg: 'var(--ink-muted)' },
  }[meeting.status] || { bg: 'var(--blue-50)', fg: 'var(--blue-700)' };

  const dt = meeting.scheduledAt ? new Date(meeting.scheduledAt) : null;

  return (
    <article className="meeting-row" style={{ alignItems: 'flex-start' }} aria-label={`${meeting.title} — ${statusLabel}`}>
      {dt && (
        <div className="meeting-day" aria-hidden="true">
          <span className="d">{String(dt.getDate()).padStart(2, '0')}</span>
          <span className="m">{['Jan','Feb','Mrz','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'][dt.getMonth()]}</span>
        </div>
      )}
      <div className="meeting-info">
        <div className="title">{meeting.title}</div>
        <div className="time" style={{ alignItems: 'center' }}>
          {dt && <span><Icon.Clock size={18} aria-hidden="true"/> {String(dt.getHours()).padStart(2,'0')}:{String(dt.getMinutes()).padStart(2,'0')} Uhr</span>}
          {!dt && meeting.startedAt && (
            <span><Icon.Play size={18} aria-hidden="true"/> Gestartet um {formatHM(meeting.startedAt)}</span>
          )}
          <span role="status" style={{
            display: 'inline-flex', padding: '4px 12px', borderRadius: 999,
            fontSize: 13, fontWeight: 700,
            background: statusColor.bg, color: statusColor.fg,
          }}>{statusLabel}</span>
        </div>
      </div>
      <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', justifyContent: 'flex-end' }} role="group" aria-label={`Aktionen für ${meeting.title}`}>
        {actions.map((a, i) => (
          <button
            key={i}
            className={"btn " + (a.primary ? 'btn-primary' : a.danger ? 'btn-secondary' : 'btn-secondary')}
            onClick={a.onClick}
            disabled={busy}
            style={a.danger ? { color: 'var(--red)' } : {}}
            aria-label={`${a.label}: ${meeting.title}`}
          >
            {busy ? '...' : a.label}
          </button>
        ))}
      </div>
    </article>
  );
}

function NewMeetingForm({ onCancel, onSaved }) {
  const [title, setTitle] = React.useState('');
  const [date, setDate] = React.useState('');
  const [time, setTime] = React.useState('');
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState(null);
  const headingRef = React.useRef(null);

  React.useEffect(() => {
    const d = new Date();
    d.setDate(d.getDate() + 1);
    setDate(d.toISOString().slice(0, 10));
    setTime('15:00');
    if (headingRef.current) headingRef.current.focus();
  }, []);

  async function submit(e) {
    e.preventDefault();
    if (!title.trim()) return;
    setSaving(true);
    setError(null);
    try {
      let scheduledAt = null;
      if (date && time) {
        scheduledAt = new Date(`${date}T${time}:00`).toISOString();
      }
      await window.Api.createMeeting(title.trim(), scheduledAt);
      onSaved();
    } catch (e) {
      setError(e.message);
      setSaving(false);
    }
  }

  return (
    <div>
      <div style={{ marginBottom: 24 }}>
        <button className="btn btn-ghost" onClick={onCancel} style={{ padding: '8px 14px', fontSize: 15 }} aria-label="Zurück zur Treffen-Übersicht">
          &#8592; Zurück
        </button>
      </div>

      <h1 className="h-display" ref={headingRef} tabIndex="-1" data-focus-target>Neues Treffen planen</h1>
      <p className="muted" style={{ fontSize: 20, marginTop: 8, marginBottom: 32 }}>
        Gib einen Titel und eine Uhrzeit ein.
      </p>

      <div className="card" style={{ padding: 36, maxWidth: 720 }}>
        <form onSubmit={submit} aria-label="Neues Treffen erstellen">
          <div className="field">
            <label htmlFor="meeting-title">Titel des Treffens</label>
            <span className="hint" id="meeting-title-hint">In leichter Sprache — kurze Sätze, einfache Wörter.</span>
            <input id="meeting-title" type="text" value={title} onChange={e => setTitle(e.target.value)}
                   placeholder="z. B. Was machst du gerne in deiner Freizeit?"
                   aria-describedby="meeting-title-hint"/>
          </div>

          <div className="field-row">
            <div className="field">
              <label htmlFor="meeting-date">Datum</label>
              <input id="meeting-date" type="date" value={date} onChange={e => setDate(e.target.value)}/>
            </div>
            <div className="field">
              <label htmlFor="meeting-time">Uhrzeit</label>
              <input id="meeting-time" type="time" value={time} onChange={e => setTime(e.target.value)}/>
            </div>
          </div>

          {error && (
            <div role="alert" style={{ background: 'var(--red-soft)', color: 'var(--red)', padding: '12px 16px', borderRadius: 12, fontSize: 15, fontWeight: 700, marginBottom: 16 }}>
              {error}
            </div>
          )}

          <div style={{ display: 'flex', gap: 12, marginTop: 24, justifyContent: 'flex-end', flexWrap: 'wrap' }}>
            <button type="button" className="btn btn-secondary" onClick={onCancel}>Abbrechen</button>
            <button type="submit" className="btn btn-primary" disabled={saving || !title.trim()}>
              <Icon.Calendar size={20} aria-hidden="true"/>
              {saving ? 'Speichere...' : 'Treffen planen'}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

function formatHM(iso) {
  if (!iso) return '';
  const d = new Date(iso);
  return `${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')}`;
}

Object.assign(window, { AdminApp });
