/* global React, ReactDOM */

// admin.jsx — Verwaltung dashboard for Konzentriert Mit Uns.
// State is persisted to localStorage under STORAGE_KEY; the Onepager
// reads the same key on load and listens to `storage` events so changes
// here propagate live to any open public-site tab.

const STORAGE_KEY = "konzentriert.termine";
const AUTH_KEY = "km.admin.authed";
const DEMO_PASSWORD = "juliadamaris";

// ─── Storage helpers ────────────────────────────────────────────────────
function normalize(source) {
  const list = Array.isArray(source.list)
    ? source.list
    : ["t1", "t2", "t3"].map((k) => source[k]).filter(Boolean);
  return {
    variant: source.variant === "b" ? "b" : "a",
    email: source.email || "",
    list: list.map((x, i) => ({
      id: x.id || `k${Date.now()}_${i}`,
      title: x.title || "",
      dates: Array.isArray(x.dates) ? [...x.dates] : [],
      time: x.time || "",
      location: x.location || "",
      ageGroup: x.ageGroup || "",
      seats: x.seats || "",
      active: x.active !== false,
    })),
  };
}

function loadData() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (raw) return normalize(JSON.parse(raw));
  } catch (e) { /* fall through */ }
  return normalize(window.TERMINE_DEFAULTS || {});
}

function saveData(data) {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
}

function resetData() {
  localStorage.removeItem(STORAGE_KEY);
  return normalize(window.TERMINE_DEFAULTS || {});
}

// ─── Date helpers ───────────────────────────────────────────────────────
function fmtDateLong(iso) {
  const d = new Date(iso + "T00:00:00");
  if (isNaN(d)) return iso;
  return d.toLocaleDateString("de-DE", { weekday: "short", day: "numeric", month: "short", year: "numeric" });
}
function fmtDateShort(iso) {
  const d = new Date(iso + "T00:00:00");
  if (isNaN(d)) return iso;
  return d.toLocaleDateString("de-DE", { day: "numeric", month: "long" });
}

// ─── App root ───────────────────────────────────────────────────────────
function App() {
  const [authed, setAuthed] = React.useState(
    sessionStorage.getItem(AUTH_KEY) === "1"
  );

  if (!authed) {
    return <Login onAuth={() => {
      sessionStorage.setItem(AUTH_KEY, "1");
      setAuthed(true);
    }} />;
  }

  return <Dashboard onLogout={() => {
    sessionStorage.removeItem(AUTH_KEY);
    setAuthed(false);
  }} />;
}

// ─── Login ──────────────────────────────────────────────────────────────
function Login({ onAuth }) {
  const [pw, setPw] = React.useState("");
  const [err, setErr] = React.useState("");

  const submit = (e) => {
    e.preventDefault();
    if (pw === DEMO_PASSWORD) {
      onAuth();
    } else {
      setErr("Passwort stimmt nicht. Bitte erneut versuchen.");
      setPw("");
    }
  };

  return (
    <div className="login">
      <form className="login__card" onSubmit={submit}>
        <img className="login__logo" src="assets/konzentriert-logo.png" width="130" height="80" alt="" />
        <p className="login__eyebrow">Verwaltung</p>
        <h1 className="login__title">Willkommen.</h1>
        <p className="login__sub">Bitte mit dem Verwaltungs&shy;passwort anmelden, um Termine und Verfügbarkeit zu pflegen.</p>
        <input
          className="login__input"
          type="password"
          value={pw}
          onChange={(e) => { setPw(e.target.value); setErr(""); }}
          placeholder="Passwort"
          autoFocus
        />
        {err && <p className="login__err">{err}</p>}
        <button className="btn btn-primary btn-lg" type="submit" style={{ width: "100%", justifyContent: "center" }}>
          Anmelden →
        </button>
        <a className="login__back" href="index.html">← Zurück zur Webseite</a>
      </form>
    </div>
  );
}

// ─── Dashboard ──────────────────────────────────────────────────────────
function Dashboard({ onLogout }) {
  const [data, setData] = React.useState(loadData);
  const [baseline, setBaseline] = React.useState(() => JSON.stringify(loadData()));
  const [savedAt, setSavedAt] = React.useState(null);
  const [toast, setToast] = React.useState("");

  const dirty = JSON.stringify(data) !== baseline;

  // Warn on tab close if dirty.
  React.useEffect(() => {
    const handler = (e) => {
      if (dirty) { e.preventDefault(); e.returnValue = ""; }
    };
    window.addEventListener("beforeunload", handler);
    return () => window.removeEventListener("beforeunload", handler);
  }, [dirty]);

  const showToast = (msg) => {
    setToast(msg);
    setTimeout(() => setToast(""), 2400);
  };

  const save = () => {
    saveData(data);
    setBaseline(JSON.stringify(data));
    setSavedAt(new Date());
    showToast("Änderungen veröffentlicht.");
  };

  const discard = () => {
    if (!confirm("Alle ungespeicherten Änderungen verwerfen?")) return;
    setData(JSON.parse(baseline));
  };

  const resetAll = () => {
    if (!confirm("Alle Termine auf die Ausgangsdaten zurücksetzen? Diese Aktion lässt sich nicht rückgängig machen.")) return;
    const fresh = resetData();
    setData(fresh);
    setBaseline(JSON.stringify(fresh));
    setSavedAt(new Date());
    showToast("Auf Ausgangsdaten zurückgesetzt.");
  };

  // Mutators
  const updateTermin = (i, patch) =>
    setData((d) => ({ ...d, list: d.list.map((x, idx) => idx === i ? { ...x, ...patch } : x) }));

  const removeTermin = (i) =>
    setData((d) => ({ ...d, list: d.list.filter((_, idx) => idx !== i) }));

  const addTermin = () =>
    setData((d) => ({
      ...d,
      list: [...d.list, {
        id: `k${Date.now()}`,
        title: "Neuer Kurs",
        dates: [],
        time: "09:00 – 11:30 Uhr",
        location: "Studio Düsseldorf",
        ageGroup: "8 – 14 Jahre",
        seats: "Anmeldung offen",
        active: true,
      }],
    }));

  const move = (i, dir) =>
    setData((d) => {
      const list = [...d.list];
      const j = i + dir;
      if (j < 0 || j >= list.length) return d;
      [list[i], list[j]] = [list[j], list[i]];
      return { ...d, list };
    });

  // Stats
  const activeCourses = data.list.filter((t) => t.active).length;
  const totalDates = data.list.reduce((n, t) => n + (t.active ? t.dates.length : 0), 0);
  const upcoming = data.list
    .filter((t) => t.active)
    .flatMap((t) => t.dates)
    .filter((iso) => new Date(iso + "T00:00:00") >= new Date(new Date().toDateString()))
    .sort();
  const nextIso = upcoming[0];

  return (
    <>
      {/* Top bar */}
      <header className="adm-topbar">
        <a className="adm-brand" href="index.html">
          <img src="assets/konzentriert-logo.png" width="60" height="36" alt="" />
          <span className="adm-brand__divider"></span>
          <span className="adm-brand__label">Verwaltung</span>
        </a>
        <div className="adm-top-actions">
          {savedAt && !dirty && (
            <span className="adm-saved">
              Gespeichert · {savedAt.toLocaleTimeString("de-DE", { hour: "2-digit", minute: "2-digit" })}
            </span>
          )}
          <a className="adm-top-link" href="index.html" target="_blank" rel="noopener">Webseite ansehen ↗</a>
          <button className="adm-top-logout" onClick={onLogout}>Abmelden</button>
        </div>
      </header>

      {/* Main */}
      <main className="adm-main">
        <section className="adm-hero">
          <span className="eyebrow">Hallo Julia &amp; Damaris</span>
          <h1 className="adm-hero__title">Termine &amp; Verfügbarkeit.</h1>
          <p className="adm-hero__sub">
            Pflegen Sie hier Daten, Uhrzeiten, Orte und freie Plätze. Mit »Änderungen veröffentlichen« erscheinen sie sofort auf der Webseite.
          </p>
        </section>

        {/* Stats */}
        <section className="adm-stats">
          <div className="adm-stat">
            <span className="adm-stat__n">{activeCourses}</span>
            <span className="adm-stat__l">Aktive Kurse</span>
          </div>
          <div className="adm-stat">
            <span className="adm-stat__n">{totalDates}</span>
            <span className="adm-stat__l">Trainingstage geplant</span>
          </div>
          <div className="adm-stat">
            <span className={"adm-stat__n " + (nextIso ? "" : "adm-stat__n--small")}>
              {nextIso ? fmtDateShort(nextIso) : "—"}
            </span>
            <span className="adm-stat__l">Nächster Termin</span>
          </div>
        </section>

        {/* Termine */}
        <section className="adm-section">
          <div className="adm-section__head">
            <h2>Kurstermine</h2>
            <p className="adm-section__help">
              Pausierte Kurse erscheinen nicht auf der Webseite. Reihenfolge per ↑↓ ändern.
            </p>
          </div>
          <div className="adm-cards">
            {data.list.map((termin, i) => (
              <TerminEditor
                key={termin.id}
                termin={termin}
                first={i === 0}
                last={i === data.list.length - 1}
                onChange={(patch) => updateTermin(i, patch)}
                onRemove={() => removeTermin(i)}
                onMoveUp={() => move(i, -1)}
                onMoveDown={() => move(i, 1)}
              />
            ))}
            {data.list.length === 0 && (
              <p className="adm-empty" style={{ padding: "32px 0", textAlign: "center" }}>
                Aktuell sind keine Termine angelegt.
              </p>
            )}
            <div className="adm-add-row">
              <button className="adm-add-btn" onClick={addTermin}>+ Termin hinzufügen</button>
            </div>
          </div>
        </section>

        {/* Settings */}
        <section className="adm-section">
          <div className="adm-section__head">
            <h2>Einstellungen</h2>
            <p className="adm-section__help">Gelten für alle Termine auf der Webseite.</p>
          </div>
          <div className="adm-card adm-settings">
            <div className="adm-field">
              <label>E-Mail für Anfragen</label>
              <input
                type="email"
                value={data.email}
                onChange={(e) => setData({ ...data, email: e.target.value })}
                placeholder="hallo@konzentriert-mit-uns.de"
              />
              <p className="adm-section__help" style={{ marginTop: 0 }}>
                Wird in den „Jetzt anfragen“-Buttons verwendet.
              </p>
            </div>
            <div className="adm-field">
              <label>Karten-Variante</label>
              <div className="adm-variant">
                <label className={data.variant === "a" ? "is-on" : ""}>
                  <input type="radio" name="variant" checked={data.variant === "a"} onChange={() => setData({ ...data, variant: "a" })} />
                  <span>
                    <b>Listen-Karten</b>
                    <small>Daten als Spalte, mit Wochentagen.</small>
                  </span>
                </label>
                <label className={data.variant === "b" ? "is-on" : ""}>
                  <input type="radio" name="variant" checked={data.variant === "b"} onChange={() => setData({ ...data, variant: "b" })} />
                  <span>
                    <b>Stempel-Karten</b>
                    <small>Großer Datum-Stempel pro Kurs.</small>
                  </span>
                </label>
              </div>
            </div>
          </div>
        </section>

        {/* Danger / reset */}
        <section className="adm-section">
          <div className="adm-section__head">
            <h2>Erweitert</h2>
          </div>
          <div className="adm-card" style={{ padding: "22px", display: "flex", justifyContent: "space-between", alignItems: "center", gap: "16px", flexWrap: "wrap" }}>
            <div>
              <p style={{ margin: 0, fontWeight: 700, color: "var(--k-navy)" }}>Auf Ausgangsdaten zurücksetzen</p>
              <p style={{ margin: "4px 0 0", fontSize: 14, color: "var(--k-navy-300)" }}>
                Setzt alle Termine und Einstellungen auf die im Code hinterlegten Werte zurück.
              </p>
            </div>
            <button className="adm-top-logout" onClick={resetAll} style={{ color: "var(--k-coral)" }}>
              Zurücksetzen
            </button>
          </div>
        </section>
      </main>

      {/* Sticky save bar */}
      {dirty && (
        <div className="adm-savebar" role="status">
          <span className="adm-savebar__msg">
            <b>Ungespeicherte Änderungen.</b> Bereit zum Veröffentlichen?
          </span>
          <div className="adm-savebar__actions">
            <button className="btn-link" onClick={discard}>Verwerfen</button>
            <button className="btn btn-primary" onClick={save}>Änderungen veröffentlichen →</button>
          </div>
        </div>
      )}

      {toast && <div className="adm-toast">♥ {toast}</div>}
    </>
  );
}

// ─── Termin editor card ─────────────────────────────────────────────────
function TerminEditor({ termin, first, last, onChange, onRemove, onMoveUp, onMoveDown }) {
  const [newDate, setNewDate] = React.useState("");

  const addDate = () => {
    if (!newDate) return;
    const next = [...new Set([...termin.dates, newDate])].sort();
    onChange({ dates: next });
    setNewDate("");
  };

  const removeDate = (iso) => {
    onChange({ dates: termin.dates.filter((d) => d !== iso) });
  };

  const sortedDates = [...termin.dates].sort();

  return (
    <article className={"adm-card" + (termin.active ? "" : " is-paused")}>
      <header className="adm-card__head">
        <div className="adm-card__title-row">
          <input
            className="adm-card__title"
            value={termin.title}
            onChange={(e) => onChange({ title: e.target.value })}
            placeholder="Kurstitel"
          />
          <p className="adm-section__help" style={{ marginTop: 4 }}>Tipp: <code>\n</code> fügt einen Zeilenumbruch im Titel ein.</p>
          <label className={"adm-toggle " + (termin.active ? "is-on" : "")}>
            <input type="checkbox" checked={termin.active} onChange={(e) => onChange({ active: e.target.checked })} />
            <span className="adm-toggle__track"><span className="adm-toggle__thumb"></span></span>
            <span className="adm-toggle__label">{termin.active ? "Aktiv" : "Pausiert"}</span>
          </label>
        </div>
        <div className="adm-card__tools">
          <button className="adm-icon" onClick={onMoveUp} disabled={first} title="Nach oben">↑</button>
          <button className="adm-icon" onClick={onMoveDown} disabled={last} title="Nach unten">↓</button>
          <button
            className="adm-icon adm-icon--danger"
            onClick={() => { if (confirm(`Termin »${termin.title || "(ohne Titel)"}« wirklich entfernen?`)) onRemove(); }}
            title="Termin entfernen"
          >✕</button>
        </div>
      </header>

      <div className="adm-card__body">
        <div className="adm-field adm-field--wide">
          <label>Trainingstage</label>
          {sortedDates.length === 0
            ? <p className="adm-empty">Noch keine Daten hinterlegt — unten ein Datum auswählen.</p>
            : <ul className="adm-dates">
                {sortedDates.map((iso) => (
                  <li key={iso} className="adm-date-chip">
                    <span>{fmtDateLong(iso)}</span>
                    <button onClick={() => removeDate(iso)} aria-label="Datum entfernen" title="Datum entfernen">×</button>
                  </li>
                ))}
              </ul>
          }
          <div className="adm-date-adder">
            <input
              type="date"
              value={newDate}
              onChange={(e) => setNewDate(e.target.value)}
              onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); addDate(); } }}
            />
            <button className="btn btn-secondary" onClick={addDate} disabled={!newDate}>+ Tag hinzufügen</button>
          </div>
        </div>

        <div className="adm-field">
          <label>Uhrzeit</label>
          <input
            type="text"
            value={termin.time}
            onChange={(e) => onChange({ time: e.target.value })}
            placeholder="z. B. 09:00 – 11:30 Uhr"
          />
        </div>
        <div className="adm-field">
          <label>Ort</label>
          <input
            type="text"
            value={termin.location}
            onChange={(e) => onChange({ location: e.target.value })}
            placeholder="z. B. Studio Düsseldorf"
          />
        </div>
        <div className="adm-field">
          <label>Altersgruppe</label>
          <input
            type="text"
            value={termin.ageGroup}
            onChange={(e) => onChange({ ageGroup: e.target.value })}
            placeholder="z. B. 8 – 11 Jahre"
          />
        </div>
        <div className="adm-field">
          <label>Verfügbarkeit</label>
          <input
            type="text"
            value={termin.seats}
            onChange={(e) => onChange({ seats: e.target.value })}
            placeholder="z. B. Noch 3 Plätze frei"
          />
          <div className="adm-quick">
            {["Noch 1 Platz frei", "Noch 3 Plätze frei", "Wenige Plätze frei", "Anmeldung offen", "Warteliste"].map((opt) => (
              <button key={opt} className="adm-chip" onClick={() => onChange({ seats: opt })}>{opt}</button>
            ))}
          </div>
        </div>
      </div>
    </article>
  );
}

// ─── Mount ──────────────────────────────────────────────────────────────
// Wait for webfonts to load before mounting so the first paint isn't
// immediately followed by a swap-reflow (which can trip Chromium's
// "ResizeObserver loop" notice in observer-instrumented hosts).
function mount() {
  ReactDOM.createRoot(document.getElementById("root")).render(<App />);
}
if (document.fonts && document.fonts.ready) {
  document.fonts.ready.then(mount);
} else {
  mount();
}
