import { useEffect, useState } from "react";
import { api } from "../api";
import { useConfirm } from "../confirm";
import Icon from "../components/Icon";
import { useToast } from "../toast";
import BrandingUpload from "../components/BrandingUpload";
import DangerAction from "../components/DangerAction";
import { DATE_FORMAT_KEY, useSettings } from "../settings";
import { DATE_FORMATS, formatDate } from "../units";
import { applyFavicon } from "../branding";

const EXPIRY_KEY = "expiry_warning_days";
const RECEIPT_KEY = "receipt_match_threshold";

export default function Settings() {
  const { reload } = useSettings();
  const toast = useToast();
  const [days, setDays] = useState("");
  const [threshold, setThreshold] = useState("");
  const [dateFormat, setDateFormat] = useState("de");
  const [error, setError] = useState(null);
  const [busy, setBusy] = useState(false);

  async function load() {
    try {
      const settings = await api.listSettings();
      setDays(settings.find((s) => s.key === EXPIRY_KEY)?.value ?? "7");
      setThreshold(settings.find((s) => s.key === RECEIPT_KEY)?.value ?? "45");
      setDateFormat(settings.find((s) => s.key === DATE_FORMAT_KEY)?.value ?? "de");
    } catch (err) {
      setError(err.message);
    }
  }

  useEffect(() => { load(); }, []);

  async function save(e) {
    e.preventDefault();
    setError(null); setBusy(true);
    try {
      await api.setSetting(EXPIRY_KEY, String(parseInt(days, 10)));
      await api.setSetting(RECEIPT_KEY, String(Math.max(0, Math.min(100, parseInt(threshold, 10) || 0))));
      await api.setSetting(DATE_FORMAT_KEY, dateFormat);
      await reload();
      toast("Gespeichert.");
    } catch (err) {
      setError(err.message);
    } finally {
      setBusy(false);
    }
  }

  // Beispiel mit einem festen Datum, damit man die Wirkung sofort sieht.
  const preview = formatDate("2026-12-23", dateFormat);

  return (
    <div>
      <div className="page-head">
        <div>
          <h1>Einstellungen</h1>
          <div className="sub">Allgemeine Konfiguration der Anwendung</div>
        </div>
      </div>
      {error && <div className="alert error"><Icon name="alert" size={16} />{error}</div>}

      <form className="card form-narrow" onSubmit={save}>
        <div className="card-head"><Icon name="clock" /><h2>Ablaufwarnung</h2></div>
        <label>
          Vorwarnzeit (Tage)
          <input type="number" min="0" step="1" value={days}
            onChange={(e) => setDays(e.target.value)} style={{ maxWidth: 160 }} />
        </label>
        <p className="muted small mt-0">
          Chargen, deren Mindesthaltbarkeitsdatum innerhalb dieser Frist liegt (oder
          bereits überschritten ist), erscheinen auf der Übersicht unter „Bald ablaufend“.
        </p>

        <div className="card-head" style={{ marginTop: "var(--sp-5)" }}>
          <Icon name="cart" /><h2>Kassenzettel-Scan</h2>
        </div>
        <label>
          Trefferschwelle (%)
          <input type="number" min="0" max="100" step="1" value={threshold}
            onChange={(e) => setThreshold(e.target.value)} style={{ maxWidth: 160 }} />
        </label>
        <p className="muted small mt-0">
          Beim Scannen eines Kassenzettels (iOS) werden je Zeile nur Artikel vorgeschlagen,
          deren Übereinstimmung mindestens so hoch ist. Höher = strenger (weniger, dafür
          sicherere Vorschläge), niedriger = mehr Vorschläge.
        </p>

        <div className="card-head" style={{ marginTop: "var(--sp-5)" }}>
          <Icon name="settings" /><h2>Darstellung</h2>
        </div>
        <label>
          Datumsformat
          <select value={dateFormat} onChange={(e) => setDateFormat(e.target.value)}>
            {DATE_FORMATS.map((f) => (
              <option key={f.value} value={f.value}>{f.label}</option>
            ))}
          </select>
        </label>

        <BrandingUpload
          kind="logo"
          title="Eigenes Logo"
          empfehlung="etwa 400 × 72 px, PNG oder SVG mit durchsichtigem Hintergrund
                      (höchstens 512 KB)"
          hint="Ersetzt Zeichen und Schriftzug oben in der Seitenleiste. Dargestellt wird
                es mit 36 px Höhe und höchstens 200 px Breite – die doppelte Größe sorgt
                für ein scharfes Bild auf hochauflösenden Bildschirmen. Ohne Angabe bleibt
                das eingebaute Zeichen stehen."
        />
        <BrandingUpload
          kind="favicon"
          title="Eigenes Favicon"
          empfehlung="quadratisch, 64 × 64 px, PNG, SVG oder ICO (höchstens 512 KB)"
          hint="Das Symbol im Browser-Tab. Ohne Angabe wird das Standardzeichen verwendet.
                Änderungen werden nach einem Neuladen der Seite sichtbar."
          onChanged={applyFavicon}
        />
        <p className="muted small mt-0">Beispiel: {preview}</p>

        <button className="btn primary" disabled={busy}>{busy ? "Speichern…" : "Speichern"}</button>
      </form>

      <ApiTokensCard />
      <DangerZoneCard />
    </div>
  );
}

/** Langlebige Tokens für externe Zugriffe (Home Assistant, Skripte). */
function ApiTokensCard() {
  const confirm = useConfirm();
  const [tokens, setTokens] = useState([]);
  const [name, setName] = useState("");
  const [fresh, setFresh] = useState(null);
  const [error, setError] = useState(null);

  async function load() {
    try {
      setTokens(await api.listApiTokens());
    } catch (err) {
      setError(err.message);
    }
  }

  useEffect(() => { load(); }, []);

  async function create(e) {
    e.preventDefault();
    setError(null);
    try {
      const created = await api.createApiToken({ name });
      setFresh(created.token);
      setName("");
      load();
    } catch (err) {
      setError(err.message);
    }
  }

  async function remove(token) {
    const ok = await confirm({
      title: `Token „${token.name}“ widerrufen?`,
      message: "Zugriffe mit diesem Token funktionieren sofort nicht mehr.",
      confirmLabel: "Widerrufen",
      danger: true,
    });
    if (!ok) return;
    try {
      await api.deleteApiToken(token.id);
      load();
    } catch (err) {
      setError(err.message);
    }
  }

  return (
    <section className="card">
      <div className="card-head"><Icon name="users" /><h2>API-Zugriff (z.B. Home Assistant)</h2></div>
      {error && <div className="alert error"><Icon name="alert" size={16} />{error}</div>}

      <p className="muted small mt-0">
        Mit einem Token lässt sich die Einkaufsliste dauerhaft abfragen, ohne dass eine
        Anmeldung abläuft. Der Token wird nur einmal angezeigt – danach ist nur noch
        sein Fingerabdruck gespeichert.
      </p>

      {fresh && (
        <div className="alert ok">
          <Icon name="check" size={16} />
          <span>
            Neuer Token – bitte jetzt kopieren:
            <div><code className="strong" style={{ wordBreak: "break-all" }}>{fresh}</code></div>
          </span>
        </div>
      )}

      <ul className="simple-list">
        {tokens.map((t) => (
          <li key={t.id}>
            <span>
              <strong>{t.name}</strong>
              <span className="muted small">
                {" "}· angelegt {new Date(t.created_at).toLocaleDateString("de-DE")}
                {t.last_used_at
                  ? ` · zuletzt genutzt ${new Date(t.last_used_at).toLocaleDateString("de-DE")}`
                  : " · noch nicht genutzt"}
              </span>
            </span>
            <button className="btn-icon danger" onClick={() => remove(t)} title="Widerrufen">
              <Icon name="trash" size={16} />
            </button>
          </li>
        ))}
        {tokens.length === 0 && <li className="muted small">Noch keine Tokens.</li>}
      </ul>

      <form className="field-inline" onSubmit={create}>
        <input placeholder="Name, z.B. Home Assistant" value={name}
          onChange={(e) => setName(e.target.value)} required />
        <button className="btn"><Icon name="plus" size={16} />Token erzeugen</button>
      </form>

      <details style={{ marginTop: "var(--sp-3)" }}>
        <summary className="muted small">Beispiel für Home Assistant</summary>
        <pre style={{ overflowX: "auto", fontSize: "0.78rem" }}>{`# configuration.yaml
rest:
  - resource: http://DEIN-SERVER:8080/api/shopping-list
    scan_interval: 900
    headers:
      Authorization: "Bearer DEIN_TOKEN"
    sensor:
      - name: "Einkaufsliste Anzahl"
        value_template: "{{ value_json | length }}"
        json_attributes_path: "$"
      - name: "Einkaufsliste"
        value_template: "{{ value_json | map(attribute='name') | join(', ') }}"`}</pre>
      </details>
    </section>
  );
}


/**
 * Gefahrenbereich: Daten in großem Stil löschen.
 *
 * Drei Stufen, damit man nicht mehr wegwirft als nötig. Benutzer, API-Tokens,
 * Einstellungen und das eigene Logo bleiben in allen Stufen erhalten.
 */
function DangerZoneCard() {
  const toast = useToast();
  const [zahlen, setZahlen] = useState(null);
  const [error, setError] = useState(null);

  async function load() {
    try {
      setZahlen(await api.maintenanceSummary());
    } catch (err) {
      setError(err.message);
    }
  }

  useEffect(() => { load(); }, []);

  function run(aktion, meldung) {
    return async () => {
      setError(null);
      try {
        setZahlen(await aktion());
        toast(meldung);
      } catch (err) {
        setError(err.message);
      }
    };
  }

  if (!zahlen) return null;

  const n = (wert, eins, mehr) => `${wert} ${wert === 1 ? eins : mehr}`;

  return (
    <section className="card danger-zone">
      <div className="card-head">
        <Icon name="alert" /><h2>Gefahrenbereich</h2>
      </div>
      <p className="muted small mt-0">
        Diese Aktionen lassen sich nicht rückgängig machen. Lege vorher ein Backup an
        (Import / Export → Backup als JSON). Benutzer, API-Tokens, Einstellungen und
        dein Logo bleiben in allen Fällen erhalten.
      </p>

      {error && <div className="alert error"><Icon name="alert" size={16} />{error}</div>}

      <DangerAction
        title="Alle Bestände löschen"
        description="Entfernt sämtliche Chargen und den Bewegungsverlauf. Die Artikel
                     selbst bleiben mit allen Stammdaten erhalten – der Bestand steht
                     danach überall auf null."
        impact={`Betrifft ${n(zahlen.lots, "Charge", "Chargen")} und ${n(zahlen.movements, "Bewegung", "Bewegungen")}.`}
        buttonLabel="Bestände löschen"
        onRun={run(api.resetStock, "Alle Bestände wurden gelöscht.")}
      />

      <DangerAction
        title="Alle Artikel löschen"
        description="Entfernt zusätzlich den gesamten Artikelkatalog samt seiner
                     EAN-Codes. Gruppen, Kategorien, Lagerorte und Einheiten bleiben."
        impact={`Betrifft ${n(zahlen.products, "Artikel", "Artikel")} samt ${n(zahlen.lots, "Charge", "Chargen")}.`}
        buttonLabel="Artikel löschen"
        onRun={run(api.resetProducts, "Alle Artikel und Bestände wurden gelöscht.")}
      />

      <DangerAction
        title="Alles zurücksetzen"
        description="Entfernt zusätzlich Gruppen, Kategorien, Lagerorte und Einheiten.
                     Die eingebauten Einheiten und die Kategorie-Startliste werden
                     danach sofort neu angelegt, damit die Installation benutzbar bleibt."
        impact={`Betrifft ${n(zahlen.products, "Artikel", "Artikel")}, ${n(zahlen.groups, "Gruppe", "Gruppen")}, ${n(zahlen.categories, "Kategorie", "Kategorien")}, ${n(zahlen.locations, "Lagerort", "Lagerorte")} und ${n(zahlen.units, "Einheit", "Einheiten")}.`}
        buttonLabel="Alles zurücksetzen"
        onRun={run(api.resetAll, "Alles wurde zurückgesetzt. Einheiten und Startkategorien sind wieder angelegt.")}
      />
    </section>
  );
}
