/* AZIS redesign scaffold — main app ==================================== */
const { useMemo } = React;

function pad(n) { return String(n).padStart(2, "0"); }

/* ---------- Today hero ---------- */
function TodayHero({ day, reduced, layout, onPunch }) {
  // Phase 4-Hotfix: punchState kommt jetzt aus dem RAW entry (Bridge), nicht
  // aus day.b1s/b1e — dort wird bei abweichend+start+!end das end von app.js
  // auf "jetzt" gesetzt (resolveTimes Live-Anzeige) was den Punch faelschlich
  // sofort auf "complete" springen liess.
  const punchState = day.punchState || "idle";
  const rawStart = day.punchRawStart || "";
  const blocked = day.weekend || (day.status !== "standard" && day.status !== "abweichend" && day.status !== "wochenende");

  const [now, setNow] = useState(Date.now());
  useEffect(() => {
    if (punchState !== "running") return;
    const id = setInterval(() => setNow(Date.now()), 1000);
    return () => clearInterval(id);
  }, [punchState]);

  const toggle = () => {
    if (blocked && punchState === "idle") return;
    if (typeof AZIS.punch === "function") AZIS.punch();
    if (typeof onPunch === "function") onPunch();
  };

  const hhmmss = (s) => pad(Math.floor(s / 3600)) + ":" + pad(Math.floor((s % 3600) / 60)) + ":" + pad(s % 60);
  let elapsed = 0;
  if (punchState === "running" && rawStart) {
    const [hh, mm] = rawStart.split(":").map((x) => parseInt(x, 10) || 0);
    const startDate = new Date(); startDate.setHours(hh, mm, 0, 0);
    elapsed = Math.max(0, Math.floor((now - startDate.getTime()) / 1000));
  }

  return (
    <section className={"card hero stagger" + (layout === "centered" ? " hero--centered" : "")} style={{ animationDelay: "40ms" }}>
      <div className="hero__head">
        <div>
          <div className="hero__day">{day.dowLong} · heute</div>
          <div className="hero__date">{pad(day.dom)}. {day.monthName}</div>
          <div className="hero__status"><span className="dot" />{AZIS.STATUS[day.status].label}</div>
        </div>
        <ProgressRing ist={day.ist} soll={day.soll} reduced={reduced} />
      </div>

      <div className="hero__saldo-row">
        <span className="hero__saldo-label">Saldo heute</span>
        <SaldoCount className="hero__saldo" minutes={day.saldo} plus reduced={reduced} />
      </div>

      <button className={"punch" + (punchState === "running" ? " punch--running" : "")}
        disabled={punchState === "complete" || (blocked && punchState === "idle")}
        onClick={toggle}>
        {punchState === "running"
          ? <React.Fragment><span className="punch__pulse" /><span className="punch__timer">{hhmmss(elapsed)}</span><span>· Ausstempeln</span></React.Fragment>
          : punchState === "complete"
            ? <React.Fragment><Icon name="check" /><span>Heute abgeschlossen</span></React.Fragment>
            : blocked
              ? <React.Fragment><span>Heute kein Stempeln</span></React.Fragment>
              : <React.Fragment><Icon name="play" /><span>Dienst beginnen</span></React.Fragment>}
      </button>
    </section>
  );
}

/* ---------- Konto band ---------- */
const KONTI = [
  { key: "mehrarbeit", label: "Mehrarbeit", icon: "zap", unit: "h", trend: "—" },
  { key: "gleitzeit", label: "Gleitzeit", icon: "clock", unit: "h", trend: "—" },
  { key: "eu", label: "EU-Tage", icon: "plane", unit: "Tg", trend: "—" },
  { key: "atb", label: "ATB-Tage", icon: "award", unit: "Tg", trend: "—" },
];

function KontoBand({ days, year, monthIdx, onPrev, onNext, reduced }) {
  const sums = useMemo(() => {
    let ist = 0, soll = 0, saldo = 0;
    days.forEach((d) => { ist += d.ist; soll += d.soll; saldo += d.saldo; });
    return { ist, soll, saldo };
  }, [days]);

  // Phase 3: Konten kommen aus app.js (overallMehrarbeitKonto / Gleitzeit /
  // EU-Tage-Rest / ATB-Tage-Rest). Bridge stellt window.AZIS.getKontos.
  const konti = useMemo(() => {
    if (typeof AZIS.getKontos === "function") return AZIS.getKontos(year, monthIdx);
    return { mehrarbeit: 0, gleitzeit: 0, eu: 0, atb: 0 };
  }, [year, monthIdx, days]);

  const istC = useCountUp(sums.ist, [sums.ist], reduced);
  const sollC = useCountUp(sums.soll, [sums.soll], reduced);

  return (
    <section className="card band stagger" style={{ animationDelay: "120ms" }}>
      <div className="band__top">
        <div>
          <div className="band__label">Monats-Saldo</div>
          <SaldoCount className="band__saldo" minutes={sums.saldo} plus reduced={reduced} />
          <div className="band__sub">{AZIS.fmt(istC)} Ist · {AZIS.fmt(sollC)} Soll</div>
        </div>
        <div className="mnav">
          <button onClick={onPrev} aria-label="Vorheriger Monat">‹</button>
          <span className="mnav__label">{AZIS.MONTHS[monthIdx]} {year}</span>
          <button onClick={onNext} aria-label="Nächster Monat">›</button>
        </div>
      </div>

      <Sparkline days={days} reduced={reduced} />

      <div className="chips">
        {KONTI.map((k) => {
          const raw = konti[k.key];
          const isTage = k.unit !== "h";
          const display = isTage ? (Number.isInteger(raw) ? raw : raw.toFixed(1)) : AZIS.fmt(raw, { plus: k.key === "gleitzeit" });
          const cls = k.key === "gleitzeit" ? (raw >= 0 ? "val-pos" : "val-neg") : "";
          return (
            <button key={k.key} className="chip" onClick={() => {
              if (typeof AZIS.openKontoDialog === "function") AZIS.openKontoDialog(k.key);
            }}>
              <div className="chip__top">
                <Icon name={k.icon} className="chip__icon" />
                <span className="chip__label">{k.label}</span>
              </div>
              <div className={"chip__val " + cls}>{display}<small>{k.unit}</small></div>
              <div className="chip__trend" style={{ color: "var(--text-muted)" }}>{k.trend}</div>
            </button>
          );
        })}
      </div>
    </section>
  );
}

/* ---------- Month list (KW groups) ---------- */
function DayCard({ day, onOpen, idx, reduced }) {
  const tone = AZIS.toneClass(day.status, day.saldo);
  const st = AZIS.STATUS[day.status];
  const showSaldo = !day.weekend && day.status !== "wochenende";
  const saldoCls = day.saldo > 0 ? "val-pos" : day.saldo < 0 ? "val-neg" : "val-zero";
  return (
    <button
      className={"day " + tone + (day.weekend ? " is-weekend" : "") + (day.isToday ? " is-today" : "") + " stagger"}
      style={{ animationDelay: reduced ? "0ms" : (60 + idx * 22) + "ms" }}
      onClick={() => onOpen(day)}>
      <div className="day__num">
        <div className="day__dow">{day.dowShort}</div>
        <div className="day__dom">{pad(day.dom)}</div>
      </div>
      <div className="day__main">
        <div className="day__label">
          {day.weekend ? "Wochenende" : st.label}
        </div>
        <div className="day__meta">
          {day.weekend ? "frei" : (day.meta || st.label)}
        </div>
      </div>
      <div className="day__right">
        {showSaldo
          ? <React.Fragment>
              <div className={"day__saldo " + saldoCls}>{AZIS.fmt(day.saldo, { plus: true })}</div>
              <div className="day__hours">{AZIS.fmt(day.ist)} / {AZIS.fmt(day.soll)}</div>
            </React.Fragment>
          : <div className="day__hours">—</div>}
      </div>
      <Icon name="chevron" className="day__chev" />
    </button>
  );
}

function MonthList({ groups, onOpen, reduced }) {
  let counter = 0;
  return (
    <div>
      {groups.map((g) => (
        <div className="kw" key={g.kw}>
          <div className="kw__head">
            <span className="kw__tag">KW {g.kw}</span>
            <span className="kw__range">{g.range}</span>
            <span className={"kw__sum " + (g.sum > 0 ? "val-pos" : g.sum < 0 ? "val-neg" : "val-zero")}>
              {AZIS.fmt(g.sum, { plus: true })}
            </span>
          </div>
          <div className="daylist">
            {g.days.map((d) => <DayCard key={d.dom} day={d} onOpen={onOpen} idx={counter++} reduced={reduced} />)}
          </div>
        </div>
      ))}
    </div>
  );
}

/* ---------- Settings screen ---------- */
const FAMILIES = [
  { key: "electric", label: "Electric", a: "#22d3ee", bg: "#0a0c10", meta: "Cyan · Standard" },
  { key: "classic", label: "Classic", a: "#27b3a9", bg: "#101116", meta: "Teal · ruhig" },
];
const EGGS = [
  { key: "camo", label: "Camo", a: "#c08a3e", bg: "#1a1f15", meta: "OD-Grün / Coyote" },
  { key: "terminal", label: "Terminal", a: "#4ade80", bg: "#040805", meta: "Phosphor · Mono" },
];

const BUNDESLAND_TO_CODE = {
  "Baden-Württemberg": "BW", "Bayern": "BY", "Berlin": "BE", "Brandenburg": "BB",
  "Bremen": "HB", "Hamburg": "HH", "Hessen": "HE", "Mecklenburg-Vorpommern": "MV",
  "Niedersachsen": "NI", "Nordrhein-Westfalen": "NW", "Rheinland-Pfalz": "RP",
  "Saarland": "SL", "Sachsen": "SN", "Sachsen-Anhalt": "ST", "Schleswig-Holstein": "SH",
  "Thüringen": "TH",
};
const CODE_TO_BUNDESLAND = Object.fromEntries(Object.entries(BUNDESLAND_TO_CODE).map(([k, v]) => [v, k]));

function SettingsScreen({ family, setFamily, mode, setMode, unlocked, onOpenSub, onReplayTour }) {
  const fixed = family === "camo" || family === "terminal"; // eggs ignore light/dark

  // Bundesland: controlled + persistiert sofort via AZIS.saveSettings.
  const [bundesland, setBundesland] = useState(() => {
    const s = typeof AZIS.getSettings === "function" ? AZIS.getSettings() : {};
    return CODE_TO_BUNDESLAND[s.state] || "Bayern";
  });
  const onBundeslandChange = (e) => {
    const name = e.target.value;
    setBundesland(name);
    const code = BUNDESLAND_TO_CODE[name] || "BY";
    if (typeof AZIS.saveSettings === "function") AZIS.saveSettings({ state: code });
  };
  const renderCard = (t, locked) => {
    const isEgg = locked || t.key === "camo" || t.key === "terminal";
    return (
      <button key={t.key}
        className={"theme-card" + (family === t.key ? " active" : "") + (locked ? " locked" : "")}
        onClick={() => { if (!locked) setFamily(t.key); }}>
        <div className="theme-card__swatch" style={{ background: t.bg }}>
          <i style={{ background: t.a, boxShadow: "0 0 9px " + t.a }} />
          {locked && <span className="lock"><Icon name="lock" /></span>}
        </div>
        <div className="theme-card__name">
          {t.label}
          {isEgg
            ? <span className="theme-card__tag egg">{locked ? "Locked" : "Egg"}</span>
            : (t.key === "electric" && <span className="theme-card__tag">Standard</span>)}
        </div>
        <div className="theme-card__meta">{locked ? "Easter Egg — freischalten" : t.meta}</div>
      </button>
    );
  };

  return (
    <div className="stagger" style={{ animationDelay: "40ms" }}>
      <div className="section-title">Darstellung · Theme</div>
      <div className="theme-grid">
        {FAMILIES.map((t) => renderCard(t, false))}
        {EGGS.map((t) => renderCard(t, !unlocked))}
      </div>

      <div className="section-title">Hell / Dunkel</div>
      <div className={"seg" + (fixed ? " disabled" : "")}>
        <button className={mode === "light" && !fixed ? "active" : ""} onClick={() => setMode("light")}>
          <Icon name="sun" />Hell
        </button>
        <button className={mode === "dark" || fixed ? "active" : ""} onClick={() => setMode("dark")}>
          <Icon name="moon" />Dunkel
        </button>
      </div>
      {fixed && <p style={{ margin: "8px 6px 0", fontSize: 11, color: "var(--text-muted)" }}>{family === "terminal" ? "Terminal" : "Camo"} bringt einen festen Look — Hell/Dunkel gilt für Electric & Classic.</p>}

      <div className="section-title">Stundenzettel</div>
      <div className="settings-list">
        {[["briefcase", "Kopfdaten · Name, Dienstgrad", "kopfdaten"], ["clock", "Gleitzeit-Regeln", "gleitzeit"]].map(([ic, lb, key]) => (
          <button key={lb} className="srow" onClick={() => onOpenSub(key)}><Icon name={ic} className="srow__icon" /><span className="srow__label">{lb}</span><span className="srow__chev">›</span></button>
        ))}
      </div>

      <div className="section-title">Bundesland</div>
      <div className="sfield">
        <select value={bundesland} onChange={onBundeslandChange}>
          {Object.keys(BUNDESLAND_TO_CODE).map((o) => <option key={o}>{o}</option>)}
        </select>
      </div>
      <p style={{ margin: "8px 6px 0", fontSize: 11, color: "var(--text-muted)", lineHeight: 1.5 }}>
        Bw-Feiertage werden automatisch nach Bundesland gesetzt — inklusive 24./31.12. als Sondertag.
      </p>

      <div className="section-title">Sicherheit & System</div>
      <div className="settings-list">
        <button className="srow" onClick={() => onOpenSub("pin")}><Icon name="zap" className="srow__icon" /><span className="srow__label">PIN ändern</span><span className="srow__chev">›</span></button>
        <button className="srow" onClick={() => onOpenSub("puk")}><Icon name="award" className="srow__icon" /><span className="srow__label">PUK-Wiederherstellung</span><span className="srow__chev">›</span></button>
        <button className="srow" onClick={onReplayTour}><Icon name="sparkle" className="srow__icon" /><span className="srow__label">Was-ist-neu-Tour erneut zeigen</span><span className="srow__chev">›</span></button>
      </div>
      <p style={{ margin: "14px 6px 0", fontSize: 11, color: "var(--text-muted)", lineHeight: 1.5 }}>
        Admin-Zugang: Versions-Pill <b>6.0</b> oben rechts 5 Sek. gedrückt halten.
      </p>
    </div>
  );
}

/* ---------- Settings sub-screens (Kopfdaten / Gleitzeit-Regeln / …) ----------
   `k` = key in state.settings. SubScreen hydratisiert per AZIS.getSettings()
   und persistiert per AZIS.saveSettings(patch). Fields ohne `k` werden nur
   angezeigt (z.B. PIN/PUK — die haben eigene Flows). ----------------------- */
const SETTINGS_SUBS = {
  kopfdaten: {
    title: "Kopfdaten", sub: "Erscheinen im PDF-Stundenzettel",
    groups: [
      { label: "Person", fields: [
        { l: "Nachname", k: "name", v: "" },
        { l: "Vorname", k: "vorname", v: "" },
        { l: "Dienstgrad", k: "dienstgrad", v: "" },
        { l: "Soll-Arbeitszeit / Woche", type: "select",
          opts: ["40h", "41h", "teilzeit"], optLabels: { teilzeit: "Teilzeit" },
          k: "sollMode", v: "41h" },
      ]},
      { label: "Überträge (Vormonat)", fields: [
        { l: "Mehrarbeit (h:mm)", k: "uebertragMehrarbeit", v: "", mono: true, half: true },
        { l: "Gleitzeit (h:mm)", k: "uebertragGleitzeit", v: "", mono: true, half: true },
        { l: "EU-Startkonto (Tage)", k: "euStartDays", v: "30", num: true, half: true },
        { l: "ATB-Startkonto (Tage)", k: "atbStartDays", v: "5", num: true, half: true },
      ]},
    ],
    note: "Ort/Datum werden im PDF automatisch gesetzt: „Feldkirchen, <Exportdatum>“.",
  },
  gleitzeit: {
    title: "Gleitzeit-Regeln", sub: "Kernzeit, Fenster und Pausen",
    groups: [
      { label: "Kernarbeitszeit", fields: [
        { l: "Start", k: "coreStart", v: "08:30", mono: true, time: true, half: true },
        { l: "Ende", k: "coreEnd", v: "14:00", mono: true, time: true, half: true },
      ]},
      { label: "Gleitzeitfenster 1", fields: [
        { l: "Start", k: "gleitWindow1Start", v: "06:00", mono: true, time: true, half: true },
        { l: "Ende", k: "gleitWindow1End", v: "08:30", mono: true, time: true, half: true },
      ]},
      { label: "Gleitzeitfenster 2", fields: [
        { l: "Start", k: "gleitWindow2Start", v: "14:00", mono: true, time: true, half: true },
        { l: "Ende", k: "gleitWindow2End", v: "19:00", mono: true, time: true, half: true },
      ]},
      { label: "Pausen", fields: [
        { l: "Basispause (Min)", k: "baseBreakMin", v: "30", num: true, half: true },
        { l: "Extra-Pause bei Mehrarbeit (Min)", k: "extraBreakMin", v: "15", num: true, half: true },
      ]},
    ],
    note: "Stundenweiser Gleitzeitabbau nur außerhalb der Kernzeit und innerhalb der Fenster. Ganze/halbe Gleittage sind antragspflichtig.",
  },
  pin: {
    title: "PIN ändern", sub: "Lokale Verschlüsselung (AES-GCM)",
    groups: [
      { label: "Verifizierung", fields: [{ l: "Aktuelle PIN", v: "", pw: true, ph: "••••" }] },
      { label: "Neue PIN", fields: [
        { l: "Neue PIN", v: "", pw: true, ph: "••••", half: true },
        { l: "Wiederholen", v: "", pw: true, ph: "••••", half: true },
      ]},
    ],
    note: "Triviale PINs (z. B. 0000, 1234) werden blockiert. Bei zu vielen Fehlversuchen greift eine Sperre.",
  },
  puk: {
    title: "PUK-Wiederherstellung", sub: "Zugang bei vergessener PIN",
    groups: [
      { label: "Recovery", fields: [{ l: "Recovery-PUK", v: "", mono: true, ph: "XXXX-XXXX-XXXX" }] },
    ],
    note: "Nach erfolgreicher PUK-Wiederherstellung werden PIN und PUK zwingend neu gesetzt (erzwungene Rotation).",
  },
};

function SubScreen({ subKey, open, onClose, onSaved }) {
  const cfg = subKey ? SETTINGS_SUBS[subKey] : null;

  // Sammle alle Felder. Felder mit `k` werden zu state.settings persistiert;
  // Felder ohne `k` (z.B. PIN-Eingaben) werden im local-state per `l` gehalten.
  const fieldKeys = useMemo(() => {
    if (!cfg) return [];
    const keys = [];
    cfg.groups.forEach((g) => g.fields.forEach((f) => keys.push(f)));
    return keys;
  }, [cfg]);
  const storageKeyFor = (f) => f.k || f.l;

  const [values, setValues] = useState({});

  // Hydratisiere bei Open mit den echten Werten aus state.settings.
  useEffect(() => {
    if (!cfg || !open) return;
    const settings = typeof AZIS.getSettings === "function" ? AZIS.getSettings() : {};
    const next = {};
    fieldKeys.forEach((f) => {
      if (f.k) {
        const cur = settings[f.k];
        next[f.k] = cur != null && cur !== "" ? String(cur) : (f.v || "");
      } else {
        // Felder ohne `k` (PIN/PUK) starten immer leer.
        next[f.l] = "";
      }
    });
    setValues(next);
  }, [cfg, open, fieldKeys]);

  if (!cfg) return <div className={"subscreen" + (open ? " show" : "")} />;

  const setField = (k, v) => setValues((prev) => ({ ...prev, [k]: v }));
  const getValue = (f) => values[storageKeyFor(f)];

  const handleSave = async () => {
    // PIN ändern: Sonder-Flow. Felder sind ohne `k` → patch-Loop greift
    // sie nicht. Wir lesen die 3 Werte ueber ihre Labels und triggern
    // AZIS.changePin → app.js's changePinSecurely (Argon2-Re-Derive +
    // Re-Encrypt). Falscher PIN / triviale PIN / Mismatch → app.js wirft.
    if (subKey === "pin") {
      const get = (label) => {
        const f = cfg.groups.flatMap((g) => g.fields).find((x) => x.l === label);
        return values[f?.l] != null ? values[f.l] : "";
      };
      const curr = (get("Aktuelle PIN") || "").trim();
      const next = (get("Neue PIN") || "").trim();
      const conf = (get("Wiederholen") || "").trim();
      if (!curr || !next || !conf) { alert("Bitte alle PIN-Felder ausfüllen."); return; }
      try {
        await AZIS.changePin(curr, next, conf);
        onSaved("PIN geändert");
      } catch (e) {
        alert("PIN-Aenderung fehlgeschlagen: " + (e?.message || e));
      }
      return;
    }

    // PUK-Wiederherstellung: app.js's recoverWithPuk macht den ganzen
    // Multi-Step-Flow (PUK-Eingabe + neue PIN + Re-Encrypt) selbst in der
    // pukRecovery-UI. Wir triggern nur den Start.
    if (subKey === "puk") {
      try {
        await AZIS.startPukRecovery();
        onSaved("PIN per PUK zurückgesetzt");
      } catch (e) {
        if (e?.message !== "PUK_CANCELLED") {
          alert("PUK-Wiederherstellung fehlgeschlagen: " + (e?.message || e));
        }
      }
      return;
    }

    // Standard-Patch zusammenstellen. Wichtig: leere Strings NICHT in den patch
    // aufnehmen — sonst wuerde z.B. ein nicht-hydratisiertes euStartDays-
    // Feld den realen Wert (30) mit 0 ueberschreiben. Nur Felder mit
    // explizitem Inhalt persistieren.
    const patch = {};
    fieldKeys.forEach((f) => {
      const raw = values[f.k];
      if (raw == null) return;
      const trimmed = typeof raw === "string" ? raw.trim() : raw;
      if (trimmed === "") return;
      if (f.num) {
        const n = Number(trimmed);
        if (!Number.isFinite(n)) return;
        patch[f.k] = n;
      } else {
        patch[f.k] = trimmed;
      }
    });
    if (Object.keys(patch).length && typeof AZIS.saveSettings === "function") {
      AZIS.saveSettings(patch);
    }
    onSaved(cfg.title);
  };

  return (
    <div className={"subscreen" + (open ? " show" : "")}>
      <div className="sub-head">
        <button className="sub-head__back" onClick={onClose} aria-label="Zurück"><Icon name="arrow" /></button>
        <div><div className="sub-head__title">{cfg.title}</div><div className="sub-head__sub">{cfg.sub}</div></div>
      </div>
      <div className="sub-body">
        {cfg.groups.map((g, gi) => (
          <React.Fragment key={gi}>
            <div className="section-title" style={{ marginTop: gi === 0 ? 4 : 18 }}>{g.label}</div>
            <div className={g.fields.every((f) => f.half) ? "sfield-2" : ""}>
              {g.fields.map((f, fi) => {
                const sk = storageKeyFor(f);
                const cur = values[sk] != null ? values[sk] : "";
                const onCh = (e) => setField(sk, f.time ? (e.target.value || "00:00") : e.target.value);
                return (
                  <div className="sfield" key={fi} style={f.half ? { marginBottom: 0 } : null}>
                    <label>{f.l}</label>
                    {f.type === "select"
                      ? <select value={cur} onChange={onCh}>{f.opts.map((o) => <option key={o} value={o}>{(f.optLabels && f.optLabels[o]) || o}</option>)}</select>
                      : f.type === "static"
                        ? <input value={cur} readOnly style={{ color: "var(--muted)" }} />
                        : <input className={f.mono || f.num ? "mono" : ""} type={f.pw ? "password" : f.time ? "time" : "text"} step={f.time ? "60" : undefined} inputMode={f.num ? "numeric" : undefined} value={cur} onChange={onCh} placeholder={f.ph || ""} />}
                  </div>
                );
              })}
            </div>
          </React.Fragment>
        ))}
        {cfg.note && <p className="sub-note">{cfg.note}</p>}
        <div className="sub-save"><button onClick={handleSave}>Speichern</button></div>
      </div>
    </div>
  );
}

function ExportScreen() {
  const fileInputRef = useRef(null);
  const [busy, setBusy] = useState(null);

  const onExportBackup = async () => {
    if (busy) return;
    if (typeof AZIS.exportBackup !== "function") { alert("Bridge nicht bereit."); return; }
    setBusy("export");
    try { await AZIS.exportBackup(); }
    catch (e) { alert("Export fehlgeschlagen: " + (e && e.message || e)); }
    finally { setBusy(null); }
  };
  const onRestoreClick = () => {
    if (busy) return;
    fileInputRef.current && fileInputRef.current.click();
  };
  const onRestoreFile = (e) => {
    const f = e.target.files && e.target.files[0];
    e.target.value = "";
    if (!f) return;
    if (typeof AZIS.restoreBackup !== "function") { alert("Bridge nicht bereit."); return; }
    setBusy("restore");
    // app.js.restoreBackup arbeitet async ueber FileReader und blockiert
    // anschliessend mit alert(). Bridge wrappt window.restoreBackup und
    // pollt auf den State-Swap; sobald der erfolgte ist, reloadet die
    // Bridge nach kurzer Pause (Erfolgs-Alert muss noch wegklickbar sein).
    try { AZIS.restoreBackup(f); }
    catch (er) {
      alert("Restore fehlgeschlagen: " + (er && er.message || er));
      setBusy(null);
    }
  };

  return (
    <div className="stagger" style={{ animationDelay: "40ms" }}>
      <div className="section-title">Export</div>
      <div className="settings-list">
        <button className="srow" disabled={busy === "pdf"} onClick={async () => {
          if (typeof AZIS.exportPdf !== "function") return;
          setBusy("pdf");
          try { await AZIS.exportPdf(); }
          catch (e) { alert("PDF-Export fehlgeschlagen: " + (e?.message || e)); }
          finally { setBusy(null); }
        }}>
          <Icon name="download" className="srow__icon" /><span className="srow__label">{busy === "pdf" ? "Exportiere PDF…" : "PDF · Stundenzettel"}</span><span className="srow__chev">›</span>
        </button>
        <button className="srow" disabled={busy === "csvmonth"} onClick={async () => {
          if (typeof AZIS.exportCsvMonth !== "function") return;
          setBusy("csvmonth");
          try { await AZIS.exportCsvMonth(); }
          catch (e) { alert("CSV-Export fehlgeschlagen: " + (e?.message || e)); }
          finally { setBusy(null); }
        }}>
          <Icon name="chart" className="srow__icon" /><span className="srow__label">CSV · Monatsdaten</span><span className="srow__chev">›</span>
        </button>
        <button className="srow" disabled={busy === "csvsheet"} onClick={async () => {
          if (typeof AZIS.exportCsvSheet !== "function") return;
          setBusy("csvsheet");
          try { await AZIS.exportCsvSheet(); }
          catch (e) { alert("CSV-Export fehlgeschlagen: " + (e?.message || e)); }
          finally { setBusy(null); }
        }}>
          <Icon name="chart" className="srow__icon" /><span className="srow__label">CSV · Stundenzettel</span><span className="srow__chev">›</span>
        </button>
      </div>
      <div className="section-title">Backup</div>
      <div className="settings-list">
        <button className="srow" onClick={onExportBackup} disabled={busy === "export"}>
          <Icon name="download" className="srow__icon" /><span className="srow__label">{busy === "export" ? "Exportiere…" : "JSON-Backup exportieren"}</span><span className="srow__chev">›</span>
        </button>
        <button className="srow" onClick={onRestoreClick} disabled={busy === "restore"}>
          <Icon name="briefcase" className="srow__icon" /><span className="srow__label">{busy === "restore" ? "Stelle wieder her…" : "Backup wiederherstellen"}</span><span className="srow__chev">›</span>
        </button>
        <input ref={fileInputRef} type="file" accept="application/json" hidden onChange={onRestoreFile} />
      </div>
      <p style={{ margin: "16px 6px", fontSize: 11.5, color: "var(--text-muted)", lineHeight: 1.5 }}>
        JSON-Backup enthaelt alle verschluesselten Eintraege + Settings. Beim Wiederherstellen wird die App neu geladen.
      </p>
    </div>
  );
}

window.AZISApp = { TodayHero, KontoBand, MonthList, SettingsScreen, SubScreen, ExportScreen };
