// ═══════════════════════════════════════════════════════════════
//  app.jsx — shell, state, persistence, live preview, actions
// ═══════════════════════════════════════════════════════════════
const { useState, useEffect, useRef, useCallback } = React;

const freshInv = () => ({
  docType: "invoice",
  num: "0000000001",
  issueDate: today(),
  supplyDate: today(),
  dueDate: "",
  currency: "EUR",
  defaultVat: 20,
  payMethod: "bank",
  ground: "",
  groundCustom: "",
  refNum: "",
  refDate: "",
  client: { ...DEFAULT_CLIENT },
  items: [{ ...DEFAULT_ITEM }],
  notes: "",
  style: "studio",
});

const NAV = [
  { v: "create", l: "Нова фактура", icon: "doc" },
  { v: "history", l: "История", icon: "history" },
  { v: "clients", l: "Клиенти", icon: "users" },
  { v: "items", l: "Артикули", icon: "box" },
  { v: "templates", l: "Шаблони", icon: "repeat" },
  { v: "dashboard", l: "Статистика", icon: "chart" },
  { v: "archive", l: "Архив", icon: "gear" },
];

function App() {
  const [loaded, setLoaded] = useState(false);
  const [view, setView] = useState("create");
  const [lang, setLang] = useState("bg");
  const [dark, setDark] = useState(false);
  const [company, setCompany] = useState(DEFAULT_COMPANY);
  const [inv, setInv] = useState(freshInv());
  const [lastNum, setLastNum] = useState(0);
  const [history, setHistory] = useState([]);
  const [clients, setClients] = useState([]);
  const [savedItems, setSavedItems] = useState([]);
  const [templates, setTemplates] = useState([]);
  const [confirmReset, setConfirmReset] = useState(false);
  const [toast, setToast] = useState("");

  const T = dark ? THEME_DARK : THEME_LIGHT;

  // ─── Load ───
  useEffect(() => {
    try {
      const raw = localStorage.getItem(STORE_KEY);
      if (raw) {
        const d = JSON.parse(raw);
        if (d.company) setCompany({ ...DEFAULT_COMPANY, ...d.company });
        if (d.inv) setInv({ ...freshInv(), ...d.inv, client: { ...DEFAULT_CLIENT, ...(d.inv.client || {}) }, items: (d.inv.items || [{ ...DEFAULT_ITEM }]).map(i => ({ ...DEFAULT_ITEM, ...i })) });
        if (typeof d.lastNum === "number") setLastNum(d.lastNum);
        if (d.history) setHistory(d.history);
        if (d.clients) setClients(d.clients);
        if (d.savedItems) setSavedItems(d.savedItems);
        if (d.templates) setTemplates(d.templates);
        if (d.lang) setLang(d.lang);
        if (typeof d.dark === "boolean") setDark(d.dark);
      }
    } catch (e) {}
    setLoaded(true);
  }, []);

  // ─── Save (debounced via effect) ───
  useEffect(() => {
    if (!loaded) return;
    try {
      localStorage.setItem(STORE_KEY, JSON.stringify({ company, inv, lastNum, history, clients, savedItems, templates, lang, dark }));
    } catch (e) {}
  }, [loaded, company, inv, lastNum, history, clients, savedItems, templates, lang, dark]);

  const flash = (msg) => { setToast(msg); setTimeout(() => setToast(""), 2200); };

  // ─── Derived ───
  const groundDef = VAT_GROUNDS.find(g => g.v === inv.ground);
  const groundActive = inv.ground !== "" && (inv.ground !== "custom" || inv.groundCustom.trim() !== "");
  const groundText = !groundActive ? "" : (inv.ground === "custom" ? inv.groundCustom : (lang === "en" ? groundDef.en : groundDef.bg));
  const calcs = inv.items.map(it => lineCalc(it, groundActive, inv.defaultVat));
  const base = calcs.reduce((s, c) => s + c.net, 0);
  const vat = calcs.reduce((s, c) => s + c.vat, 0);
  const total = base + vat;

  const docData = {
    docType: inv.docType, num: inv.num, issueDate: inv.issueDate, supplyDate: inv.supplyDate, dueDate: inv.dueDate,
    company, client: inv.client, items: inv.items, currency: inv.currency, defaultVat: inv.defaultVat,
    payMethod: inv.payMethod, notes: inv.notes, groundText, refNum: inv.refNum, refDate: inv.refDate,
  };

  // ─── Updaters ───
  const updateInv = useCallback((patch) => setInv(p => ({ ...p, ...patch })), []);
  const updateCompany = useCallback((patch) => setCompany(p => ({ ...p, ...patch })), []);
  const addItem = () => setInv(p => ({ ...p, items: [...p.items, { ...DEFAULT_ITEM, vat: p.defaultVat }] }));
  const updateItem = (i, patch) => setInv(p => ({ ...p, items: p.items.map((it, j) => j === i ? { ...it, ...patch } : it) }));
  const removeItem = (i) => setInv(p => ({ ...p, items: p.items.length > 1 ? p.items.filter((_, j) => j !== i) : p.items }));

  // ─── Clients ───
  const saveClient = () => {
    const c = inv.client;
    if (!c.name && !c.nameEn) { flash("Въведи име на клиента"); return; }
    setClients(prev => {
      const idx = prev.findIndex(x => (c.eik && x.eik === c.eik) || (!c.eik && x.name === c.name));
      if (idx >= 0) { const n = [...prev]; n[idx] = { ...c }; return n; }
      return [...prev, { ...c }];
    });
    flash("Клиентът е запазен");
  };
  const loadClient = (idx) => updateInv({ client: { ...DEFAULT_CLIENT, ...clients[idx] } });
  const useClient = (c) => { updateInv({ client: { ...DEFAULT_CLIENT, ...c } }); setView("create"); };
  const deleteClient = (idx) => setClients(prev => prev.filter((_, i) => i !== idx));

  // ─── Saved items ───
  const saveItem = (it) => {
    if (!it.desc && !it.descEn) { flash("Артикулът няма описание"); return; }
    setSavedItems(prev => [...prev, { ...it }]);
    flash("Артикулът е запазен");
  };
  const loadItem = (savedIdx, intoIndex) => {
    const s = savedItems[savedIdx]; if (!s) return;
    updateItem(intoIndex, { desc: s.desc, descEn: s.descEn, unit: s.unit, unitEn: s.unitEn, price: s.price, vat: s.vat, disc: s.disc || 0, discType: s.discType || "%" });
  };
  const deleteSavedItem = (idx) => setSavedItems(prev => prev.filter((_, i) => i !== idx));

  // ─── Save / open invoices ───
  const nextNumber = (cur) => { const n = parseInt(String(cur).replace(/\D/g, ""), 10); return padNum((isNaN(n) ? lastNum : n) + 1); };
  const saveInvoice = () => {
    const snap = { id: Date.now(), ...docData, ground: inv.ground, groundCustom: inv.groundCustom, style: inv.style, base, vat, total };
    setHistory(prev => [snap, ...prev]);
    const numInt = parseInt(String(inv.num).replace(/\D/g, ""), 10);
    if (!isNaN(numInt)) setLastNum(numInt);
    if (inv.client.name || inv.client.nameEn) saveClientSilent(inv.client);
    setInv(p => ({ ...freshInv(), num: nextNumber(p.num), currency: p.currency, defaultVat: p.defaultVat, payMethod: p.payMethod, style: p.style }));
    flash("Документът е запазен в историята");
    setView("create");
  };
  const saveClientSilent = (c) => setClients(prev => {
    const idx = prev.findIndex(x => (c.eik && x.eik === c.eik) || (!c.eik && x.name === c.name));
    if (idx >= 0) { const n = [...prev]; n[idx] = { ...c }; return n; }
    return [...prev, { ...c }];
  });
  const openInvoice = (snap) => {
    setInv({ ...freshInv(), docType: snap.docType, num: snap.num, issueDate: snap.issueDate, supplyDate: snap.supplyDate, dueDate: snap.dueDate || "",
      currency: snap.currency, defaultVat: snap.defaultVat, payMethod: snap.payMethod, ground: snap.ground || "", groundCustom: snap.groundCustom || "",
      refNum: snap.refNum || "", refDate: snap.refDate || "", client: { ...DEFAULT_CLIENT, ...snap.client }, items: snap.items.map(i => ({ ...DEFAULT_ITEM, ...i })), notes: snap.notes || "", style: snap.style || "studio" });
    setView("create");
  };
  const duplicateInvoice = (snap) => { openInvoice(snap); setInv(p => ({ ...p, num: nextNumber(snap.num), issueDate: today(), supplyDate: today(), dueDate: "" })); flash("Дублирано — нов номер"); };
  const deleteInvoice = (id) => setHistory(prev => prev.filter(i => i.id !== id));

  // ─── Templates ───
  const saveTemplate = () => {
    if (!inv.client.name && !inv.client.nameEn && !inv.items[0].desc) { flash("Попълни клиент или артикул"); return; }
    const tp = { id: Date.now(), name: `${inv.client.name || inv.client.nameEn || "Шаблон"} — ${inv.items[0]?.desc || inv.items[0]?.descEn || "услуга"}`,
      docType: inv.docType, currency: inv.currency, defaultVat: inv.defaultVat, payMethod: inv.payMethod, ground: inv.ground, groundCustom: inv.groundCustom,
      client: { ...inv.client }, items: inv.items.map(i => ({ ...i })), notes: inv.notes, style: inv.style };
    setTemplates(prev => [...prev, tp]); flash("Шаблонът е запазен");
  };
  const useTemplate = (tp) => {
    setInv(p => ({ ...freshInv(), num: p.num, docType: tp.docType, currency: tp.currency, defaultVat: tp.defaultVat, payMethod: tp.payMethod,
      ground: tp.ground || "", groundCustom: tp.groundCustom || "", client: { ...DEFAULT_CLIENT, ...tp.client }, items: tp.items.map(i => ({ ...DEFAULT_ITEM, ...i })), notes: tp.notes || "", style: tp.style || "studio" }));
    setView("create"); flash("Шаблонът е зареден");
  };
  const deleteTemplate = (id) => setTemplates(prev => prev.filter(t => t.id !== id));

  // ─── Output ───
  const downloadHTML = () => {
    const html = buildInvoiceHTML(docData, lang, inv.style);
    const blob = new Blob([html], { type: "text/html;charset=utf-8" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a"); a.href = url;
    const dt = DOC_TYPES.find(x => x.v === inv.docType);
    a.download = `${dt.bg.replace(/\s/g, "-")}-${inv.num}.html`;
    document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url);
  };
  const printDoc = () => {
    const html = buildInvoiceHTML(docData, lang, inv.style);
    const f = document.createElement("iframe");
    f.style.position = "fixed"; f.style.right = "0"; f.style.bottom = "0"; f.style.width = "0"; f.style.height = "0"; f.style.border = "0";
    document.body.appendChild(f);
    f.contentDocument.open(); f.contentDocument.write(html); f.contentDocument.close();
    let done = false;
    const go = () => { if (done) return; done = true; f.contentWindow.focus(); f.contentWindow.print(); setTimeout(() => document.body.removeChild(f), 1000); };
    const fd = f.contentDocument.fonts;
    if (fd && fd.ready) { fd.ready.then(() => setTimeout(go, 150)); setTimeout(go, 1800); }
    else setTimeout(go, 800);
  };
  const exportCSV = () => {
    const head = "Тип,Номер,Дата,Клиент,ЕИК,Основа,ДДС,Общо,Валута\n";
    const rows = history.map(i => {
      const dt = DOC_TYPES.find(x => x.v === i.docType)?.bg || "Фактура";
      const cn = (i.client?.name || i.client?.nameEn || "").replace(/,/g, " ");
      return `${dt},${i.num},${i.issueDate},${cn},${i.client?.eik || ""},${i.base.toFixed(2)},${i.vat.toFixed(2)},${i.total.toFixed(2)},${i.currency}`;
    }).join("\n");
    const blob = new Blob(["\uFEFF" + head + rows], { type: "text/csv;charset=utf-8" });
    const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "fakturi.csv";
    document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url);
  };
  const backup = () => {
    const data = { company, lastNum, history, clients, savedItems, templates, date: new Date().toISOString() };
    const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
    const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `fakturi-backup-${today()}.json`;
    document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url);
  };
  const restore = (e) => {
    const file = e.target.files?.[0]; if (!file) return;
    const r = new FileReader();
    r.onload = (ev) => {
      try { const d = JSON.parse(ev.target.result);
        if (d.company) setCompany({ ...DEFAULT_COMPANY, ...d.company });
        if (d.history) setHistory(d.history); if (typeof d.lastNum === "number") setLastNum(d.lastNum);
        if (d.clients) setClients(d.clients); if (d.savedItems) setSavedItems(d.savedItems); if (d.templates) setTemplates(d.templates);
        flash("Данните са възстановени");
      } catch (err) { flash("Грешен файл"); }
    };
    r.readAsText(file); e.target.value = "";
  };
  const reset = () => {
    if (!confirmReset) { setConfirmReset(true); setTimeout(() => setConfirmReset(false), 4000); return; }
    setHistory([]); setClients([]); setSavedItems([]); setTemplates([]); setLastNum(0); setConfirmReset(false); flash("Изтрито");
  };

  // ─── Preview scaling ───
  const previewRef = useRef(null);
  const [scale, setScale] = useState(0.6);
  useEffect(() => {
    if (!previewRef.current) return;
    const ro = new ResizeObserver(entries => {
      const w = entries[0].contentRect.width;
      setScale(Math.min((w - 4) / 794, 1));
    });
    ro.observe(previewRef.current);
    return () => ro.disconnect();
  }, [loaded, view]);

  if (!loaded) return <div style={{ minHeight: "100vh", display: "flex", alignItems: "center", justifyContent: "center", fontFamily: MONO, color: T.faint, background: T.bg }}>Зареждане…</div>;

  const langBtn = (v, l) => (
    <button key={v} onClick={() => setLang(v)} style={{ padding: "5px 11px", borderRadius: 6, fontSize: 11, fontWeight: 600, fontFamily: MONO, cursor: "pointer",
      border: `1px solid ${lang === v ? T.blue : T.line}`, background: lang === v ? T.blueSoft : "transparent", color: lang === v ? T.blue : T.sub }}>{l}</button>
  );

  return (
    <div style={{ minHeight: "100vh", background: T.bg, color: T.ink, fontFamily: MONO, display: "flex", flexDirection: "column" }}>
      {/* TOP BAR */}
      <header style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "13px 22px", background: T.panel, borderBottom: `1px solid ${T.line}`, position: "sticky", top: 0, zIndex: 50 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 11 }}>
          <Mark size={28} color={T.ink} accent={T.blue} />
          <div>
            <div style={{ fontSize: 15, fontWeight: 600, letterSpacing: "-0.02em" }}>shortcut<span style={{ opacity: 0.4 }}>/</span>studio</div>
            <div style={{ fontSize: 9.5, letterSpacing: "0.16em", textTransform: "uppercase", color: T.faint }}>Фактуриране</div>
          </div>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <div style={{ display: "flex", gap: 5 }}>{langBtn("bg", "БГ")}{langBtn("en", "EN")}{langBtn("both", "БГ·EN")}</div>
          <button onClick={() => setDark(d => !d)} title="Тема" style={{ padding: 7, borderRadius: 6, border: `1px solid ${T.line}`, background: "transparent", color: T.ink, cursor: "pointer", display: "flex" }}><Icon name={dark ? "sun" : "moon"} size={15} /></button>
        </div>
      </header>

      <div style={{ display: "flex", flex: 1, minHeight: 0 }}>
        {/* SIDEBAR */}
        <nav style={{ width: 210, flexShrink: 0, padding: "18px 14px", borderRight: `1px solid ${T.line}`, background: T.panel, display: "flex", flexDirection: "column", gap: 3 }}>
          {NAV.map(n => {
            const active = view === n.v;
            const count = n.v === "history" ? history.length : n.v === "clients" ? clients.length : n.v === "items" ? savedItems.length : n.v === "templates" ? templates.length : 0;
            return (
              <button key={n.v} onClick={() => setView(n.v)} style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 12px", borderRadius: 8, border: "none", cursor: "pointer",
                background: active ? T.blue : "transparent", color: active ? "#fff" : T.sub, fontFamily: MONO, fontSize: 12.5, fontWeight: active ? 600 : 500, textAlign: "left", width: "100%" }}>
                <Icon name={n.icon} size={16} /><span style={{ flex: 1 }}>{n.l}</span>
                {count > 0 && <span style={{ fontSize: 10, fontWeight: 700, padding: "1px 6px", borderRadius: 9, background: active ? "rgba(255,255,255,0.22)" : T.blueSoft, color: active ? "#fff" : T.blue }}>{count}</span>}
              </button>
            );
          })}
          <div style={{ flex: 1 }} />
          <div style={{ fontSize: 9.5, color: T.faint, padding: "10px 12px", lineHeight: 1.6 }}>Данните се пазят локално в браузъра. Свали резервно копие от „Архив“.</div>
        </nav>

        {/* MAIN */}
        <main style={{ flex: 1, minWidth: 0, overflow: "auto" }}>
          {view === "create" ? (
            <div style={{ display: "grid", gridTemplateColumns: "minmax(420px, 1fr) minmax(360px, 0.85fr)", gap: 0, minHeight: "100%" }}>
              {/* Editor column */}
              <div style={{ padding: "22px 24px", overflow: "auto", borderRight: `1px solid ${T.line}` }}>
                <Editor T={T} lang={lang} inv={inv} company={company} updateInv={updateInv} updateCompany={updateCompany}
                  items={inv.items} addItem={addItem} updateItem={updateItem} removeItem={removeItem}
                  clients={clients} onSaveClient={saveClient} onLoadClient={loadClient}
                  savedItems={savedItems} onSaveItem={saveItem} onLoadItem={loadItem} onDeleteSavedItem={deleteSavedItem}
                  groundActive={groundActive} base={base} vat={vat} total={total} />
              </div>
              {/* Preview column */}
              <div style={{ display: "flex", flexDirection: "column", background: T.bg, minWidth: 0 }}>
                <div style={{ display: "flex", flexWrap: "wrap", gap: 8, padding: "14px 18px", borderBottom: `1px solid ${T.line}`, position: "sticky", top: 0, background: T.bg, zIndex: 10 }}>
                  <Button T={T} kind="primary" icon="save" size="sm" onClick={saveInvoice}>Запази</Button>
                  <Button T={T} kind="ghost" icon="repeat" size="sm" onClick={saveTemplate}>Шаблон</Button>
                  <div style={{ flex: 1 }} />
                  <Button T={T} kind="ghost" icon="print" size="sm" onClick={printDoc}>Печат / PDF</Button>
                  <Button T={T} kind="solid" icon="download" size="sm" onClick={downloadHTML}>HTML</Button>
                </div>
                <div ref={previewRef} style={{ flex: 1, overflow: "auto", padding: 18, display: "flex", justifyContent: "center", alignItems: "flex-start" }}>
                  <InvoiceDoc d={docData} lang={lang} style={inv.style} scale={scale} />
                </div>
              </div>
            </div>
          ) : (
            <div style={{ maxWidth: 920, margin: "0 auto", padding: "28px 28px 60px" }}>
              <h2 style={{ fontSize: 18, fontWeight: 600, letterSpacing: "-0.02em", margin: "0 0 20px" }}>{NAV.find(n => n.v === view).l}</h2>
              {view === "history" && <HistoryView T={T} history={history} onOpen={openInvoice} onDuplicate={duplicateInvoice} onDelete={deleteInvoice} />}
              {view === "clients" && <ClientsView T={T} clients={clients} onUse={useClient} onDelete={deleteClient} />}
              {view === "items" && <ItemsView T={T} savedItems={savedItems} onDelete={deleteSavedItem} />}
              {view === "templates" && <TemplatesView T={T} templates={templates} onUse={useTemplate} onDelete={deleteTemplate} />}
              {view === "dashboard" && <DashboardView T={T} history={history} />}
              {view === "archive" && <ArchiveView T={T} history={history} onCSV={exportCSV} onBackup={backup} onRestore={restore} onReset={reset} confirmReset={confirmReset} />}
            </div>
          )}
        </main>
      </div>

      {/* TOAST */}
      {toast && (
        <div style={{ position: "fixed", bottom: 22, left: "50%", transform: "translateX(-50%)", background: T.ink, color: T.panel, padding: "11px 20px", borderRadius: 9, fontSize: 12.5, fontWeight: 600, fontFamily: MONO, boxShadow: "0 8px 30px rgba(0,0,0,0.25)", zIndex: 200, display: "flex", alignItems: "center", gap: 8 }}>
          <Icon name="check" size={15} />{toast}
        </div>
      )}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
