// Backend serializes InvoiceStatus as int — map to/from the strings the UI uses.
const INV_STATUS_TO_STR = { 1: "draft", 2: "pending", 3: "paid", 4: "overdue", 5: "cancelled" };
const INV_STR_TO_STATUS = { draft: 1, pending: 2, paid: 3, overdue: 4, cancelled: 5 };

function nextInvoiceNumber(existing) {
  const used = new Set(existing.map(i => i.number));
  let n = 1;
  while (used.has(`F${String(n).padStart(5, "0")}`)) n++;
  return `F${String(n).padStart(5, "0")}`;
}

// Invoices screen — Invoices + Clients tabs with full functionality
function round2(n) {
  // Always round UP to 2 decimals (12.341 → 12.35, 12.349 → 12.35, 12.30 → 12.30).
  // toFixed(10) first to strip float drift (e.g. 0.1+0.2 = 0.30000000000000004),
  // otherwise an already-2-decimal value would be ceil'd up by one cent.
  if (!Number.isFinite(n)) return 0;
  const clean = Number(n.toFixed(10));
  return Math.ceil(clean * 100) / 100;
}

function ClientArchiveButton({ client, toast, onChanged }) {
  const [busy, setBusy] = React.useState(false);
  const Icons = window.Icons;
  const archived = !!client.isArchived;
  const Icon = archived ? Icons.ArchiveRestore : Icons.Archive;
  const tooltip = archived ? "Desarchivar" : "Archivar";

  const handle = async (e) => {
    e.stopPropagation();
    if (busy) return;
    setBusy(true);
    try {
      if (archived) await window.api.clients.unarchive(client.id);
      else          await window.api.clients.archive(client.id);
      toast(archived ? "Cliente desarchivado" : "Cliente archivado", "success");
      onChanged && onChanged();
    } catch (err) {
      toast(err.message || "No se pudo cambiar el estado", "danger");
    } finally {
      setBusy(false);
    }
  };

  return (
    <button
      type="button"
      className="icon-btn"
      style={{ width: 26, height: 26, opacity: busy ? 0.5 : 1 }}
      title={tooltip}
      aria-label={tooltip}
      disabled={busy}
      onClick={handle}
    >
      <Icon style={{ width: 14, height: 14 }} />
    </button>
  );
}

function AutoGrowText({ value, onChange, placeholder }) {
  const ref = React.useRef(null);
  const resize = () => {
    const el = ref.current;
    if (!el) return;
    el.style.height = "auto";
    el.style.height = el.scrollHeight + "px";
  };
  React.useLayoutEffect(() => { resize(); }, [value]);
  return (
    <textarea
      ref={ref}
      className="input desc-input"
      rows={1}
      placeholder={placeholder}
      value={value}
      onChange={e => onChange(e.target.value)}
    />
  );
}

// Maps sidebar subnav IDs ↔ screen state. Keys must match SUBNAVS.fiscal ids.
const INVOICES_SUBTAB_MAP = {
  // Comercial — Facturas
  "all":              { section: "invoices", status: "all" },
  "paid":             { section: "invoices", status: "paid" },
  "pending":          { section: "invoices", status: "pending" },
  "overdue":          { section: "invoices", status: "overdue" },
  "drafts":           { section: "invoices", status: "draft" },
  "templates":        { section: "invoices", status: "all" },
  // Comercial — Clientes (clientView matches Client.isArchived from API)
  "clients-all":      { section: "clients",  clientView: "all" },
  "clients-active":   { section: "clients",  clientView: "active" },
  "clients-archived": { section: "clients",  clientView: "archived" },
  // Contabilidad — placeholders (la lógica es país-específica y se desarrollará después)
  "journal":          { section: "coming-soon", titleKey: "journal_book" },
  "ledger":           { section: "coming-soon", titleKey: "ledger_book" },
  "accounts":         { section: "coming-soon", titleKey: "chart_of_accounts" },
};

window.InvoicesScreen = function InvoicesScreen({ t, subTab, setSubTab }) {
  const sub = INVOICES_SUBTAB_MAP[subTab] || INVOICES_SUBTAB_MAP.all;
  const section = sub.section;
  const filterStatus = sub.status;

  const setSection = (id) => setSubTab(id === "invoices" ? "all" : "clients-all");
  // Pill values use singular "draft"; subnav uses plural "drafts" — translate here.
  const setFilterStatus = (s) => setSubTab(s === "draft" ? "drafts" : s);

  const [showNew, setShowNew] = React.useState(false);
  const [showNewClient, setShowNewClient] = React.useState(false);
  const [openInvoice, setOpenInvoice] = React.useState(null);
  const [openClient, setOpenClient] = React.useState(null);
  const [showFilter, setShowFilter] = React.useState(false);
  const [clientFilter, setClientFilter] = React.useState({ countries: [] });
  const [invFilter, setInvFilter] = React.useState({ minTotal: "", maxTotal: "", from: "", to: "", clients: [] });
  const [search, setSearch] = React.useState("");
  const filterBtnRef = React.useRef(null);
  const Icons = window.Icons;
  const toast = window.useToast();

  // Clients backed by the API. Loaded first because invoice filtering needs clientsById.
  const [allClients, setAllClients] = React.useState([]);
  const [clientsError, setClientsError] = React.useState(null);
  const [clientsLoading, setClientsLoading] = React.useState(true);
  const [clientsRefreshKey, setClientsRefreshKey] = React.useState(0);
  const refreshClients = React.useCallback(() => setClientsRefreshKey(k => k + 1), []);

  React.useEffect(() => {
    let cancelled = false;
    setClientsLoading(true);
    window.api.clients.list()
      .then(list => { if (!cancelled) { setAllClients(list); setClientsError(null); } })
      .catch(err => { if (!cancelled) setClientsError(err.message); })
      .finally(() => { if (!cancelled) setClientsLoading(false); });
    return () => { cancelled = true; };
  }, [clientsRefreshKey]);

  const clientView = sub.clientView || "all"; // active | archived | all
  const clientsById = React.useMemo(
    () => Object.fromEntries(allClients.map(c => [c.id, c])),
    [allClients]
  );

  // Invoices from the API.
  const [allInv, setAllInv] = React.useState([]);
  const [invLoading, setInvLoading] = React.useState(true);
  const [invError, setInvError] = React.useState(null);
  const [invRefreshKey, setInvRefreshKey] = React.useState(0);
  const refreshInvoices = React.useCallback(() => setInvRefreshKey(k => k + 1), []);
  React.useEffect(() => {
    let cancelled = false;
    setInvLoading(true);
    window.api.invoices.list()
      .then(list => { if (!cancelled) { setAllInv(list); setInvError(null); } })
      .catch(err => { if (!cancelled) setInvError(err.message); })
      .finally(() => { if (!cancelled) setInvLoading(false); });
    return () => { cancelled = true; };
  }, [invRefreshKey]);

  // Derived: invoice count per client (cancelled excluded). Computed on the front
  // because the API doesn't ship aggregates yet and the data is already loaded here.
  const invoiceCountByClient = React.useMemo(() => {
    const acc = {};
    for (const i of allInv) {
      if (INV_STATUS_TO_STR[i.status] === "cancelled") continue;
      acc[i.clientId] = (acc[i.clientId] || 0) + 1;
    }
    return acc;
  }, [allInv]);

  const filteredInv = allInv.filter(i => {
    const statusStr = INV_STATUS_TO_STR[i.status] || "";
    if (filterStatus !== "all" && statusStr !== filterStatus) return false;
    const clientName = clientsById[i.clientId]?.name || "";
    if (search && !(`${i.number} ${clientName} ${i.issuerName}`.toLowerCase().includes(search.toLowerCase()))) return false;
    if (invFilter.minTotal && i.total < parseFloat(invFilter.minTotal)) return false;
    if (invFilter.maxTotal && i.total > parseFloat(invFilter.maxTotal)) return false;
    if (invFilter.clients.length && !invFilter.clients.includes(i.clientId)) return false;
    return true;
  });

  const invFilterActive = !!(invFilter.minTotal || invFilter.maxTotal || invFilter.clients.length);

  const filteredClients = allClients.filter(c => {
    if (clientView === "active" && c.isArchived) return false;
    if (clientView === "archived" && !c.isArchived) return false;
    if (search && !(`${c.name} ${c.email}`.toLowerCase().includes(search.toLowerCase()))) return false;
    if (clientFilter.countries.length && !clientFilter.countries.includes(c.country)) return false;
    return true;
  });

  const handleExport = () => {
    const rows = [
      ["Number", "Date", "Issuer", "Client", "Status", "Currency", "Total"],
      ...filteredInv.map(i => [
        i.number,
        i.issueDate,
        i.issuerName,
        clientsById[i.clientId]?.name || "?",
        INV_STATUS_TO_STR[i.status] || "?",
        i.currency,
        i.total.toFixed(2),
      ]),
    ];
    window.downloadCSV(`vildez-invoices-${new Date().toISOString().slice(0,10)}.csv`, rows);
    toast(t("exported_csv") || "CSV downloaded", "success");
  };

  // Page-level header content varies by section.
  const isCommercial = section === "invoices" || section === "clients";
  const isComingSoon = section === "coming-soon";
  const pageTitle =
    isComingSoon ? t(sub.titleKey) :
    section === "invoices" ? t("invoices_title") : t("clients_title");
  const pageSubtitle =
    isComingSoon ? t("coming_soon_sub") :
    section === "invoices" ? t("invoices_sub") : t("clients_sub");

  return (
    <div className="page">
      <window.PageHeader
        title={pageTitle}
        subtitle={pageSubtitle}
        actions={isCommercial ? (
          <>
            {section === "invoices" && <window.Btn variant="ghost" icon={Icons.Download} onClick={handleExport}>{t("export")}</window.Btn>}
            <window.Btn variant="brand" icon={Icons.Plus} onClick={() => section === "invoices" ? setShowNew(true) : setShowNewClient(true)}>
              {section === "invoices" ? t("new_invoice") : t("new_client")}
            </window.Btn>
          </>
        ) : null}
      />

      {isCommercial && (
        <div style={{ display: "flex", gap: 4, borderBottom: "1px solid var(--border)", marginBottom: 16 }}>
          {[
            { id: "invoices", label: t("invoices") },
            { id: "clients", label: t("clients") },
          ].map((tt) => (
            <button
              key={tt.id}
              onClick={() => setSection(tt.id)}
              className="page-tab"
              data-active={section === tt.id}
            >
              {tt.label}
            </button>
          ))}
        </div>
      )}

      {isComingSoon ? (
        <div className="card" style={{ padding: 48, textAlign: "center" }}>
          <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 8 }}>{t("coming_soon_title")}</div>
          <div style={{ fontSize: 12.5, color: "var(--text-muted)", maxWidth: 480, margin: "0 auto", lineHeight: 1.6 }}>
            {t("coming_soon_sub")}
          </div>
        </div>
      ) : section === "invoices" ? (
        <>
          <window.Toolbar>
            <input className="input" placeholder={t("search_ph")} style={{ maxWidth: 280 }} value={search} onChange={e => setSearch(e.target.value)} />
            <div className="tab-bar">
              {["all", "paid", "pending", "overdue", "draft"].map((f) => (
                <button key={f} className={filterStatus === f ? "active" : ""} onClick={() => setFilterStatus(f)}>{t(f)}</button>
              ))}
            </div>
            <button ref={filterBtnRef} className={`btn ghost${invFilterActive ? " active-pill" : ""}`} onClick={() => setShowFilter(s => !s)}>
              <Icons.Filter /> {t("filter")}
              {invFilterActive && <span className="dot-brand" />}
            </button>
            <span style={{ marginLeft: "auto", color: "var(--text-muted)", fontSize: 12 }}>
              {filteredInv.length} {t("invoices").toLowerCase()}
            </span>
          </window.Toolbar>

          <window.Popover open={showFilter} onClose={() => setShowFilter(false)} anchorRef={filterBtnRef} width={280}>
            <div className="ui-popover-section">
              <div className="ui-popover-label">{t("amount_range")}</div>
              <div style={{ display: "flex", gap: 6, padding: "4px 10px" }}>
                <input className="input" placeholder="Min" value={invFilter.minTotal} onChange={e => setInvFilter({ ...invFilter, minTotal: e.target.value })} />
                <input className="input" placeholder="Max" value={invFilter.maxTotal} onChange={e => setInvFilter({ ...invFilter, maxTotal: e.target.value })} />
              </div>
            </div>
            <div className="ui-popover-divider" />
            <div className="ui-popover-section">
              <div className="ui-popover-label">{t("client")}</div>
              <div style={{ maxHeight: 200, overflowY: "auto" }}>
                {allClients.length === 0 ? (
                  <div style={{ padding: "6px 10px", color: "var(--text-faint)", fontSize: 12 }}>—</div>
                ) : (
                  [...allClients]
                    .sort((a, b) => a.name.localeCompare(b.name))
                    .map(c => {
                      const checked = invFilter.clients.includes(c.id);
                      return (
                        <button key={c.id} className="ui-popover-item" onClick={() => {
                          const list = checked
                            ? invFilter.clients.filter(id => id !== c.id)
                            : [...invFilter.clients, c.id];
                          setInvFilter({ ...invFilter, clients: list });
                        }}>
                          <span className="ui-popover-checkbox" data-checked={checked} />
                          <span>{c.name}</span>
                        </button>
                      );
                    })
                )}
              </div>
            </div>
            {invFilterActive && (
              <>
                <div className="ui-popover-divider" />
                <div className="ui-popover-section">
                  <button className="ui-popover-item" onClick={() => { setInvFilter({ minTotal: "", maxTotal: "", from: "", to: "", clients: [] }); setShowFilter(false); }}>
                    {t("clear_filters")}
                  </button>
                </div>
              </>
            )}
          </window.Popover>

          <div className="card">
            <table className="tbl">
              <thead>
                <tr>
                  <th>{t("number")}</th>
                  <th>{t("date")}</th>
                  <th>{t("issuer")}</th>
                  <th>{t("client")}</th>
                  <th>{t("status")}</th>
                  <th className="right">{t("total")}</th>
                  <th style={{ width: 40 }}></th>
                </tr>
              </thead>
              <tbody>
                {invLoading && allInv.length === 0 && (
                  <tr><td colSpan={7} style={{ textAlign: "center", padding: 32, color: "var(--text-muted)" }}>Cargando…</td></tr>
                )}
                {invError && (
                  <tr><td colSpan={7} style={{ textAlign: "center", padding: 32, color: "var(--danger)" }}>{invError}</td></tr>
                )}
                {!invLoading && !invError && filteredInv.map((inv) => {
                  const statusStr = INV_STATUS_TO_STR[inv.status] || "?";
                  const clientName = clientsById[inv.clientId]?.name || "—";
                  const currencySymbol = inv.currency === "USD" ? "$" : inv.currency === "GBP" ? "£" : "€";
                  return (
                    <tr
                      key={inv.id}
                      onDoubleClick={() => setOpenInvoice(inv)}
                      title="Doble click para abrir"
                      style={{ cursor: "default" }}
                    >
                      <td className="mono" style={{ color: "var(--brand)", fontWeight: 500 }}>#{inv.number}</td>
                      <td className="num" style={{ color: "var(--text-muted)" }}>{inv.issueDate}</td>
                      <td>{inv.issuerName}</td>
                      <td>{clientName}</td>
                      <td><window.StatusBadge status={statusStr} t={t} /></td>
                      <td className="right num" style={{ fontWeight: 600 }}>{currencySymbol}{window.formatAmount(inv.total)}</td>
                      <td onDoubleClick={(e) => e.stopPropagation()}><button className="icon-btn" style={{ width: 24, height: 24 }} onClick={() => setOpenInvoice(inv)}><Icons.MoreHorizontal /></button></td>
                    </tr>
                  );
                })}
                {!invLoading && !invError && filteredInv.length === 0 && (
                  <tr><td colSpan={7} style={{ textAlign: "center", padding: 32, color: "var(--text-muted)" }}>{t("no_results") || "No invoices match your filters."}</td></tr>
                )}
              </tbody>
            </table>
          </div>
        </>
      ) : (
        <>
          <window.Toolbar>
            <input className="input" placeholder={t("search_ph")} style={{ maxWidth: 280 }} value={search} onChange={e => setSearch(e.target.value)} />
            <div className="tab-bar">
              {[
                { id: "all",      subTab: "clients-all",      label: t("all") },
                { id: "active",   subTab: "clients-active",   label: t("active") },
                { id: "archived", subTab: "clients-archived", label: t("archived") },
              ].map(p => (
                <button
                  key={p.id}
                  className={clientView === p.id ? "active" : ""}
                  onClick={() => setSubTab(p.subTab)}
                >
                  {p.label}
                </button>
              ))}
            </div>
            <button ref={filterBtnRef} className={`btn ghost${clientFilter.countries.length ? " active-pill" : ""}`} onClick={() => setShowFilter(s => !s)}>
              <Icons.Filter /> {t("filter")}
              {clientFilter.countries.length > 0 && <span className="dot-brand" />}
            </button>
            <span style={{ marginLeft: "auto", color: "var(--text-muted)", fontSize: 12 }}>
              {filteredClients.length} {t("clients").toLowerCase()}
            </span>
          </window.Toolbar>

          <window.Popover open={showFilter} onClose={() => setShowFilter(false)} anchorRef={filterBtnRef} width={220}>
            <div className="ui-popover-section">
              <div className="ui-popover-label">{t("country") || "Country"}</div>
              {[...new Set(allClients.map(c => c.country))].map(country => {
                const checked = clientFilter.countries.includes(country);
                return (
                  <button key={country} className="ui-popover-item" onClick={() => {
                    const list = checked ? clientFilter.countries.filter(c => c !== country) : [...clientFilter.countries, country];
                    setClientFilter({ countries: list });
                  }}>
                    <span className="ui-popover-checkbox" data-checked={checked} />
                    <span>{country}</span>
                  </button>
                );
              })}
            </div>
            {clientFilter.countries.length > 0 && (
              <>
                <div className="ui-popover-divider" />
                <button className="ui-popover-item" onClick={() => { setClientFilter({ countries: [] }); setShowFilter(false); }}>
                  {t("clear_filters") || "Clear filters"}
                </button>
              </>
            )}
          </window.Popover>

          <div className="card">
            <table className="tbl">
              <thead>
                <tr>
                  <th>{t("name")}</th>
                  <th>{t("email")}</th>
                  <th>{t("phone")}</th>
                  <th>{t("country")}</th>
                  <th className="right">{t("invoices_count")}</th>
                  <th style={{ width: 40 }}></th>
                </tr>
              </thead>
              <tbody>
                {clientsLoading && allClients.length === 0 && (
                  <tr><td colSpan={6} style={{ textAlign: "center", padding: 32, color: "var(--text-muted)" }}>Cargando…</td></tr>
                )}
                {clientsError && (
                  <tr><td colSpan={6} style={{ textAlign: "center", padding: 32, color: "var(--danger)" }}>{clientsError}</td></tr>
                )}
                {!clientsLoading && !clientsError && filteredClients.map((c) => (
                  <tr
                    key={c.id || c.name}
                    style={{ opacity: c.isArchived ? 0.55 : 1, cursor: "default" }}
                    onDoubleClick={() => setOpenClient(c)}
                    title="Doble click para editar"
                  >
                    <td>
                      <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                        <window.Avatar initials={c.name.split(" ").map(w=>w[0]).slice(0,2).join("").toUpperCase()} size="sm" />
                        <span style={{ fontWeight: 500 }}>{c.name}</span>
                      </div>
                    </td>
                    <td className="mono" style={{ color: "var(--text-muted)", fontSize: 12 }}>{c.email}</td>
                    <td className="mono" style={{ color: "var(--text-muted)", fontSize: 12 }}>{c.phone || "—"}</td>
                    <td>{c.country ? <span className="badge neutral">{c.country}</span> : <span style={{ color: "var(--text-faint)" }}>—</span>}</td>
                    <td className="right num" style={{ fontWeight: 500 }}>{invoiceCountByClient[c.id] ?? 0}</td>
                    <td onDoubleClick={(e) => e.stopPropagation()}>
                      <ClientArchiveButton client={c} toast={toast} onChanged={refreshClients} />
                    </td>
                  </tr>
                ))}
                {!clientsLoading && !clientsError && filteredClients.length === 0 && (
                  <tr><td colSpan={6} style={{ textAlign: "center", padding: 32, color: "var(--text-muted)" }}>{t("no_results") || "No clients match your filters."}</td></tr>
                )}
              </tbody>
            </table>
          </div>
        </>
      )}

      <NewInvoiceModal open={showNew} onClose={() => setShowNew(false)} t={t} toast={toast} clients={allClients} existingInvoices={allInv} onCreated={refreshInvoices} />
      <NewClientModal open={showNewClient} onClose={() => setShowNewClient(false)} t={t} toast={toast} onCreated={refreshClients} />
      <InvoiceDetailModal invoice={openInvoice} onClose={() => setOpenInvoice(null)} t={t} toast={toast} clientsById={clientsById} onChanged={refreshInvoices} />
      <ClientDetailModal client={openClient} onClose={() => setOpenClient(null)} t={t} toast={toast} onChanged={refreshClients} />
    </div>
  );
};

function NewInvoiceModal({ open, onClose, t, toast, clients = [], existingInvoices = [], onCreated }) {
  const lang = (window.__TWEAK_DEFAULTS?.language) || "es";
  const today = new Date().toISOString().slice(0, 10);
  const [form, setForm] = React.useState({
    simplified: false,
    issuer: "Rodrigo Vidal",
    client: "",
    name: "",
    issueDate: today,
    dueDate: "",
    confirmDate: false,
    status: "pending",   // initial state of the new invoice
    currency: "EUR",
    items: [{ desc: "", qty: 1, price: 0, vat: 21 }],
    applyIRPF: false,
    irpfRate: 15,
    paymentMethod: "Transferencia bancaria directa",
    savePayment: true,
    thanks: "",
    saveThanks: false,
  });

  const update = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const updateItem = (i, k, v) => setForm(f => ({ ...f, items: f.items.map((it, idx) => idx === i ? { ...it, [k]: v } : it) }));
  const addItem = () => setForm(f => ({ ...f, items: [...f.items, { desc: "", qty: 1, price: 0, vat: 21 }] }));
  const removeItem = (i) => setForm(f => ({ ...f, items: f.items.filter((_, idx) => idx !== i) }));

  const subtotal = form.items.reduce((s, it) => s + (it.qty || 0) * (it.price || 0), 0);
  const vatTotal = form.items.reduce((s, it) => s + ((it.qty || 0) * (it.price || 0)) * ((it.vat || 0) / 100), 0);
  const irpfAmount = form.applyIRPF ? subtotal * (form.irpfRate / 100) : 0;
  const total = subtotal + vatTotal - irpfAmount;
  const validLines = form.items.filter(it => it.desc && it.desc.trim() && (it.qty || 0) > 0);
  const canCreate = form.client && form.confirmDate && validLines.length > 0;
  const [submitting, setSubmitting] = React.useState(false);

  const handleCreate = async () => {
    if (!canCreate || submitting) return;
    setSubmitting(true);
    try {
      const number = nextInvoiceNumber(existingInvoices);
      await window.api.invoices.create({
        number,
        clientId: form.client,
        issuerName: form.issuer,
        issueDate: form.issueDate,
        dueDate: form.dueDate || null,
        status: INV_STR_TO_STATUS[form.status] || 2,
        currency: form.currency,
        notes: form.thanks || null,
        lines: validLines.map(it => ({
          description: it.desc.trim(),
          quantity:  parseFloat(it.qty)   || 0,
          unitPrice: parseFloat(it.price) || 0,
          vatRate:   parseFloat(it.vat)   || 0,
        })),
      });
      toast(`${t("invoice_created") || "Factura creada"} (${number})`, "success");
      onCreated && onCreated();
      onClose();
    } catch (err) {
      toast(err.message || "No se pudo crear la factura", "danger");
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <window.Modal open={open} onClose={onClose} title={t("new_invoice")} subtitle={t("new_invoice_sub") || "Rellena los datos para emitir una factura."} width={680}
      footer={
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", width: "100%" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 12, color: canCreate ? "transparent" : "var(--warning)" }}>
            {!canCreate && (<>
              <window.Icons.AlertTriangle style={{ width: 14, height: 14 }} />
              <span>{!form.client ? "Selecciona la empresa cliente" : "Confirma la fecha de emisión para poder crear la factura"}</span>
            </>)}
          </div>
          <div style={{ display: "flex", gap: 8 }}>
            <window.Btn variant="ghost" onClick={onClose} disabled={submitting}>Cancelar</window.Btn>
            <window.Btn variant="brand" onClick={handleCreate} disabled={!canCreate || submitting}>
              {submitting ? "Creando…" : "Crear Factura"}
            </window.Btn>
          </div>
        </div>
      }
    >
      {/* EMPRESAS */}
      <FormSection title="Empresas" headerRight={
        <label className="check-inline">
          <input type="checkbox" checked={form.simplified} onChange={e => update("simplified", e.target.checked)} />
          <span>Factura simplificada</span>
        </label>
      }>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          <div className="field"><span>Empresa emisora <i className="req">*</i></span>
            <window.Select
              value={form.issuer}
              onChange={v => update("issuer", v)}
              options={["Rodrigo Vidal", "Vildez SL"]}
            />
          </div>
          <div className="field"><span>Empresa cliente <i className="req">*</i></span>
            <window.Select
              value={form.client}
              onChange={v => update("client", v)}
              options={clients.map(c => ({ value: c.id, label: c.name }))}
              placeholder={clients.length === 0 ? "No hay clientes" : "Seleccionar..."}
              disabled={clients.length === 0}
            />
          </div>
        </div>
      </FormSection>

      {/* DETALLES */}
      <FormSection title="Detalles">
        <label className="field" style={{ marginBottom: 12 }}><span>Nombre de la factura</span>
          <input className="input" placeholder="Ej: Servicios marzo 2026" value={form.name} onChange={e => update("name", e.target.value)} />
        </label>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 10 }}>
          <div className="field"><span>Fecha de emisión <i className="req">*</i></span>
            <window.DatePicker value={form.issueDate} onChange={v => update("issueDate", v)} clearable={false} />
          </div>
          <div className="field"><span>Fecha de vencimiento (opcional)</span>
            <window.DatePicker value={form.dueDate} onChange={v => update("dueDate", v)} placeholder="Seleccionar fecha..." />
          </div>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 10 }}>
          <div className="field"><span>Estado inicial</span>
            <window.Select
              value={form.status}
              onChange={v => update("status", v)}
              options={[
                { value: "draft",   label: t("draft")   || "Borrador" },
                { value: "pending", label: t("pending") || "Pendiente" },
                { value: "paid",    label: t("paid")    || "Pagada" },
              ]}
            />
          </div>
          <div className="field"><span>Moneda</span>
            <window.Select
              value={form.currency}
              onChange={v => update("currency", v)}
              options={[
                { value: "EUR", label: "EUR (€)" },
                { value: "USD", label: "USD ($)" },
                { value: "GBP", label: "GBP (£)" },
              ]}
            />
          </div>
        </div>
        <label className="check-inline">
          <input type="checkbox" checked={form.confirmDate} onChange={e => update("confirmDate", e.target.checked)} />
          <span>He confirmado que la fecha de emisión es correcta</span>
        </label>
      </FormSection>

      {/* LÍNEAS DE FACTURA */}
      <FormSection title="Líneas de factura">
        <div style={{ background: "var(--bg-sunken)", border: "1px solid var(--border)", borderRadius: 8, overflow: "hidden" }}>
          <table className="tbl lines-table" style={{ fontSize: 12.5 }}>
            <thead>
              <tr>
                <th>Descripción</th>
                <th className="right" style={{ width: 72 }}>Cant.</th>
                <th className="right" style={{ width: 112 }}>Precio (€)</th>
                <th className="right" style={{ width: 70 }}>IVA %</th>
                <th className="right" style={{ width: 90 }}>Subtotal</th>
                <th className="right" style={{ width: 90 }}>Total</th>
                <th style={{ width: 28 }}></th>
              </tr>
            </thead>
            <tbody>
              {form.items.map((it, i) => {
                const sub = (it.qty || 0) * (it.price || 0);
                const lineTotal = sub * (1 + (it.vat || 0) / 100);
                return (
                  <tr key={i}>
                    <td><AutoGrowText placeholder="Descripción del servicio..." value={it.desc} onChange={v => updateItem(i, "desc", v)} /></td>
                    <td><input className="input num-input" type="number" min="0" value={it.qty} onChange={e => updateItem(i, "qty", parseFloat(e.target.value) || 0)} /></td>
                    <td><input className="input num-input" type="number" step="0.01" min="0" inputMode="decimal" value={it.price} onChange={e => updateItem(i, "price", parseFloat(e.target.value) || 0)} onBlur={e => updateItem(i, "price", round2(parseFloat(e.target.value) || 0))} /></td>
                    <td><input className="input num-input" type="number" min="0" max="100" value={it.vat} onChange={e => updateItem(i, "vat", parseFloat(e.target.value) || 0)} /></td>
                    <td className="right num" style={{ color: "var(--text-muted)" }}>{window.formatAmount(sub)} €</td>
                    <td className="right num" style={{ fontWeight: 600 }}>{window.formatAmount(lineTotal)} €</td>
                    <td>{form.items.length > 1 && <button className="icon-btn" style={{ width: 22, height: 22 }} onClick={() => removeItem(i)}><window.Icons.X /></button>}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginTop: 12, gap: 16 }}>
          <button className="btn ghost" onClick={addItem} style={{ borderStyle: "dashed" }}>
            <window.Icons.Plus /> Añadir línea
          </button>
          <div style={{ flex: 1, maxWidth: 280 }}>
            <label className="check-inline" style={{ marginBottom: 8, justifyContent: "flex-end" }}>
              <input type="checkbox" checked={form.applyIRPF} onChange={e => update("applyIRPF", e.target.checked)} />
              <span>Aplicar IRPF</span>
              {form.applyIRPF && (
                <input className="input" type="number" value={form.irpfRate} onChange={e => update("irpfRate", parseFloat(e.target.value) || 0)} style={{ width: 56, marginLeft: 6 }} />
              )}
            </label>
            <div style={{ borderTop: "1px solid var(--border)", paddingTop: 8 }}>
              <SumLine label="Subtotal" value={`${window.formatAmount(subtotal)} €`} />
              <SumLine label="IVA" value={`${window.formatAmount(vatTotal)} €`} />
              {form.applyIRPF && <SumLine label={`IRPF (${form.irpfRate}%)`} value={`−${window.formatAmount(irpfAmount)} €`} />}
              <div style={{ borderTop: "1px solid var(--border)", marginTop: 6, paddingTop: 8, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                <span style={{ fontSize: 13, fontWeight: 600 }}>Total</span>
                <span style={{ fontSize: 18, fontWeight: 700, color: "var(--brand)", fontFamily: "var(--font-mono)" }}>{window.formatAmount(total)} €</span>
              </div>
            </div>
          </div>
        </div>
      </FormSection>

      {/* MENSAJES OPCIONALES */}
      <FormSection title="Mensajes opcionales">
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 4 }}>
          <span className="field-lab">Método de pago</span>
          <label className="check-inline">
            <input type="checkbox" checked={form.savePayment} onChange={e => update("savePayment", e.target.checked)} />
            <span>Guardar como predeterminado</span>
          </label>
        </div>
        <textarea className="input" rows="2" value={form.paymentMethod} onChange={e => update("paymentMethod", e.target.value)} style={{ resize: "vertical", marginBottom: 14 }} />

        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 4 }}>
          <span className="field-lab">Mensaje de agradecimiento</span>
          <label className="check-inline">
            <input type="checkbox" checked={form.saveThanks} onChange={e => update("saveThanks", e.target.checked)} />
            <span>Guardar como predeterminado</span>
          </label>
        </div>
        <textarea className="input" rows="2" placeholder="Ej: Gracias por confiar en nosotros. Ha sido un placer trabajar con usted." value={form.thanks} onChange={e => update("thanks", e.target.value)} style={{ resize: "vertical" }} />
      </FormSection>
    </window.Modal>
  );
}

function FormSection({ title, headerRight, children }) {
  return (
    <div className="form-section">
      <div className="form-section-head">
        <span className="form-section-title">{title}</span>
        {headerRight}
      </div>
      <div>{children}</div>
    </div>
  );
}

function SumLine({ label, value }) {
  return (
    <div style={{ display: "flex", justifyContent: "space-between", fontSize: 12.5, padding: "3px 0", color: "var(--text-muted)" }}>
      <span>{label}</span>
      <span className="num">{value}</span>
    </div>
  );
}

function ClientDetailModal({ client, onClose, t, toast, onChanged }) {
  const [form, setForm] = React.useState(null);
  const [submitting, setSubmitting] = React.useState(false);

  React.useEffect(() => {
    if (client) {
      setForm({
        name: client.name || "",
        email: client.email || "",
        phone: client.phone || "",
        country: client.country || "",
      });
    }
  }, [client]);

  const open = !!client;
  const canSubmit = form && form.name.trim() && form.email.trim() && !submitting;

  const handleSave = async () => {
    if (!canSubmit) return;
    setSubmitting(true);
    try {
      await window.api.clients.update(client.id, {
        name: form.name.trim(),
        email: form.email.trim(),
        phone: form.phone.trim() || null,
        country: form.country || null,
      });
      toast(`Cliente ${form.name.trim()} actualizado`, "success");
      onChanged && onChanged();
      onClose();
    } catch (err) {
      toast(err.message || "No se pudo guardar el cliente", "danger");
    } finally {
      setSubmitting(false);
    }
  };

  if (!open || !form) return null;

  return (
    <window.Modal open={open} onClose={onClose} title={t("edit_client") || "Editar cliente"} subtitle={client.email} width={480}
      footer={
        <>
          <window.Btn variant="ghost" onClick={onClose} disabled={submitting}>{t("cancel") || "Cancelar"}</window.Btn>
          <window.Btn variant="brand" onClick={handleSave} disabled={!canSubmit}>
            {submitting ? "Guardando…" : (t("save") || "Guardar")}
          </window.Btn>
        </>
      }
    >
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
        <label className="field" style={{ gridColumn: "1 / -1" }}><span>{t("name")} <i className="req">*</i></span>
          <input className="input" value={form.name} onChange={e => setForm({ ...form, name: e.target.value })} />
        </label>
        <label className="field"><span>{t("email")} <i className="req">*</i></span>
          <input className="input" type="email" value={form.email} onChange={e => setForm({ ...form, email: e.target.value })} />
        </label>
        <label className="field"><span>{t("phone")}</span>
          <input className="input" value={form.phone} onChange={e => setForm({ ...form, phone: e.target.value })} />
        </label>
        <div className="field"><span>{t("country")}</span>
          <window.Select
            value={form.country || ""}
            onChange={v => setForm({ ...form, country: v })}
            options={["ES","GB","US","DE","FR","PT","IT","NL"]}
          />
        </div>
      </div>
    </window.Modal>
  );
}

function NewClientModal({ open, onClose, t, toast, onCreated }) {
  const [form, setForm] = React.useState({ name: "", email: "", phone: "", country: "ES" });
  const [submitting, setSubmitting] = React.useState(false);

  // Reset on open so a previous attempt doesn't leak in.
  React.useEffect(() => {
    if (open) setForm({ name: "", email: "", phone: "", country: "ES" });
  }, [open]);

  const canSubmit = form.name.trim() && form.email.trim() && !submitting;

  const handleCreate = async () => {
    if (!canSubmit) return;
    setSubmitting(true);
    try {
      await window.api.clients.create({
        name: form.name.trim(),
        email: form.email.trim(),
        phone: form.phone.trim() || null,
        country: form.country || null,
      });
      toast(t("client_created") || "Cliente creado", "success");
      onCreated && onCreated();
      onClose();
    } catch (err) {
      toast(err.message || "No se pudo crear el cliente", "danger");
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <window.Modal open={open} onClose={onClose} title={t("new_client")} subtitle={t("new_client_sub") || "Add a new client to your workspace."} width={480}
      footer={
        <>
          <window.Btn variant="ghost" onClick={onClose} disabled={submitting}>{t("cancel") || "Cancel"}</window.Btn>
          <window.Btn variant="brand" onClick={handleCreate} disabled={!canSubmit}>
            {submitting ? "Creando…" : (t("create") || "Create")}
          </window.Btn>
        </>
      }
    >
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
        <label className="field" style={{ gridColumn: "1 / -1" }}><span>{t("name")} <i className="req">*</i></span>
          <input className="input" value={form.name} onChange={e => setForm({ ...form, name: e.target.value })} placeholder="Acme Studios" />
        </label>
        <label className="field"><span>{t("email")} <i className="req">*</i></span>
          <input className="input" type="email" value={form.email} onChange={e => setForm({ ...form, email: e.target.value })} placeholder="hello@acme.com" />
        </label>
        <label className="field"><span>{t("phone")}</span>
          <input className="input" value={form.phone} onChange={e => setForm({ ...form, phone: e.target.value })} placeholder="+34 600 000 000" />
        </label>
        <div className="field"><span>{t("country")}</span>
          <window.Select
            value={form.country}
            onChange={v => setForm({ ...form, country: v })}
            options={["ES","GB","US","DE","FR","PT","IT","NL"]}
          />
        </div>
      </div>
    </window.Modal>
  );
}

function InvoiceDetailModal({ invoice, onClose, t, toast, clientsById = {}, onChanged }) {
  const [editing, setEditing] = React.useState(false);
  const [form, setForm] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const Icons = window.Icons;

  React.useEffect(() => {
    if (invoice) {
      setForm({
        invoiceId: invoice.id,
        num: invoice.number,
        issuer: invoice.issuerName,
        clientId: invoice.clientId,
        client: clientsById[invoice.clientId]?.name || "—",
        date: invoice.issueDate,
        dueDate: invoice.dueDate || "",
        status: INV_STATUS_TO_STR[invoice.status] || "draft",
        currency: invoice.currency || "EUR",
        name: "",
        items: (invoice.lines || []).map(l => ({
          desc: l.description,
          qty: l.quantity,
          price: l.unitPrice,
          vat: l.vatRate,
        })),
        paymentMethod: "",
        thanks: invoice.notes || "",
        notes: invoice.notes || "",
      });
      setEditing(false);
    }
  }, [invoice, clientsById]);

  if (!invoice || !form) return null;

  const update = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const updateItem = (i, k, v) => setForm(f => ({ ...f, items: f.items.map((it, idx) => idx === i ? { ...it, [k]: v } : it) }));
  const addItem = () => setForm(f => ({ ...f, items: [...f.items, { desc: "", qty: 1, price: 0, vat: 21 }] }));
  const removeItem = (i) => setForm(f => ({ ...f, items: f.items.filter((_, idx) => idx !== i) }));

  const subtotal = form.items.reduce((s, it) => s + (it.qty || 0) * (it.price || 0), 0);
  const vatTotal = form.items.reduce((s, it) => s + ((it.qty || 0) * (it.price || 0)) * ((it.vat || 0) / 100), 0);
  const total = subtotal + vatTotal;

  const handleSave = async () => {
    if (busy) return;
    const validLines = form.items.filter(it => it.desc && it.desc.trim() && (it.qty || 0) > 0);
    if (validLines.length === 0) {
      toast("Añade al menos una línea con descripción", "danger");
      return;
    }
    setBusy(true);
    try {
      await window.api.invoices.update(form.invoiceId, {
        number: form.num,
        clientId: form.clientId,
        issuerName: form.issuer,
        issueDate: form.date,
        dueDate: form.dueDate || null,
        status: INV_STR_TO_STATUS[form.status] || 1,
        currency: form.currency,
        notes: form.notes || null,
        lines: validLines.map(it => ({
          description: it.desc.trim(),
          quantity:  parseFloat(it.qty)   || 0,
          unitPrice: parseFloat(it.price) || 0,
          vatRate:   parseFloat(it.vat)   || 0,
        })),
      });
      toast(`Factura #${form.num} actualizada`, "success");
      setEditing(false);
      onChanged && onChanged();
      onClose();
    } catch (err) {
      toast(err.message || "No se pudo guardar la factura", "danger");
    } finally {
      setBusy(false);
    }
  };

  const handleExportPDF = () => {
    exportInvoiceToPDF(form, total, subtotal, vatTotal);
    toast("Generando PDF…", "info");
  };

  const handleDuplicate = () => { toast("Duplicar aún no implementado", "info"); };

  const handleDelete = async () => {
    if (busy) return;
    setBusy(true);
    try {
      await window.api.invoices.delete(form.invoiceId);
      toast(`Factura #${form.num} eliminada`, "warning");
      onChanged && onChanged();
      onClose();
    } catch (err) {
      toast(err.message || "No se pudo eliminar", "danger");
    } finally {
      setBusy(false);
    }
  };

  return (
    <window.Modal
      open={!!invoice}
      onClose={onClose}
      title={
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <span className="mono" style={{ color: "var(--brand)" }}>#{form.num}</span>
          <window.StatusBadge status={form.status} t={t} />
        </div>
      }
      subtitle={editing ? "Editando factura" : `${form.client} · ${form.date}`}
      width={780}
      footer={
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", width: "100%" }}>
          <div style={{ display: "flex", gap: 6 }}>
            {!editing && <>
              <window.Btn variant="ghost" icon={Icons.Copy} onClick={handleDuplicate}>Duplicar</window.Btn>
              <button className="btn ghost" onClick={handleDelete} style={{ color: "var(--danger)" }}>
                <Icons.Trash /> Eliminar
              </button>
            </>}
          </div>
          <div style={{ display: "flex", gap: 8 }}>
            {editing ? (
              <>
                <window.Btn variant="ghost" onClick={() => setEditing(false)}>Cancelar</window.Btn>
                <window.Btn variant="brand" icon={Icons.Check} onClick={handleSave}>Guardar cambios</window.Btn>
              </>
            ) : (
              <>
                <window.Btn variant="ghost" icon={Icons.Edit} onClick={() => setEditing(true)}>Editar</window.Btn>
                <window.Btn variant="brand" icon={Icons.Download} onClick={handleExportPDF}>Exportar PDF</window.Btn>
              </>
            )}
          </div>
        </div>
      }
    >
      {editing ? (
        <InvoiceEditor form={form} update={update} updateItem={updateItem} addItem={addItem} removeItem={removeItem} subtotal={subtotal} vatTotal={vatTotal} total={total} clientsById={clientsById} />
      ) : (
        <InvoicePreview form={form} subtotal={subtotal} vatTotal={vatTotal} total={total} />
      )}
    </window.Modal>
  );
}

function InvoicePreview({ form, subtotal, vatTotal, total }) {
  return (
    <div style={{ background: "var(--bg-elev)", border: "1px solid var(--border)", borderRadius: 10, padding: 24 }}>
      {/* Header */}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 28, paddingBottom: 20, borderBottom: "1px solid var(--border)" }}>
        <div>
          <div style={{ fontSize: 22, fontWeight: 700, marginBottom: 4 }}>FACTURA</div>
          <div className="mono" style={{ fontSize: 13, color: "var(--brand)" }}>#{form.num}</div>
          {form.name && <div style={{ fontSize: 13, color: "var(--text-muted)", marginTop: 4 }}>{form.name}</div>}
        </div>
        <div style={{ textAlign: "right", fontSize: 12, color: "var(--text-muted)" }}>
          <div style={{ marginBottom: 4 }}><span style={{ textTransform: "uppercase", fontSize: 10, letterSpacing: "0.06em" }}>Fecha emisión</span></div>
          <div className="num" style={{ color: "var(--text)", fontWeight: 500, marginBottom: 8 }}>{form.date}</div>
          {form.dueDate && <>
            <div style={{ marginBottom: 4 }}><span style={{ textTransform: "uppercase", fontSize: 10, letterSpacing: "0.06em" }}>Vencimiento</span></div>
            <div className="num" style={{ color: "var(--text)", fontWeight: 500 }}>{form.dueDate}</div>
          </>}
        </div>
      </div>

      {/* From / To */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 24, marginBottom: 28 }}>
        <div>
          <div style={{ fontSize: 10, fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.08em", color: "var(--text-faint)", marginBottom: 8 }}>De</div>
          <div style={{ fontWeight: 600, fontSize: 14, marginBottom: 2 }}>{form.issuer}</div>
          <div style={{ fontSize: 12, color: "var(--text-muted)", lineHeight: 1.6 }}>
            Calle Mayor 12<br />28013 Madrid, ES<br />NIF: 12345678A
          </div>
        </div>
        <div>
          <div style={{ fontSize: 10, fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.08em", color: "var(--text-faint)", marginBottom: 8 }}>Para</div>
          <div style={{ fontWeight: 600, fontSize: 14, marginBottom: 2 }}>{form.client}</div>
          <div style={{ fontSize: 12, color: "var(--text-muted)", lineHeight: 1.6 }}>
            Cliente activo<br />contacto@cliente.com
          </div>
        </div>
      </div>

      {/* Items */}
      <table className="tbl" style={{ marginBottom: 16 }}>
        <thead>
          <tr>
            <th>Descripción</th>
            <th style={{ width: 60 }} className="right">Cant.</th>
            <th style={{ width: 90 }} className="right">Precio</th>
            <th style={{ width: 60 }} className="right">IVA</th>
            <th style={{ width: 100 }} className="right">Total</th>
          </tr>
        </thead>
        <tbody>
          {form.items.map((it, i) => (
            <tr key={i}>
              <td>{it.desc || "—"}</td>
              <td className="right num">{it.qty}</td>
              <td className="right num">€{window.formatAmount(it.price || 0)}</td>
              <td className="right num" style={{ color: "var(--text-muted)" }}>{it.vat}%</td>
              <td className="right num" style={{ fontWeight: 600 }}>€{window.formatAmount((it.qty || 0) * (it.price || 0) * (1 + (it.vat || 0) / 100))}</td>
            </tr>
          ))}
        </tbody>
      </table>

      {/* Totals */}
      <div style={{ display: "flex", justifyContent: "flex-end", marginBottom: 24 }}>
        <div style={{ minWidth: 280 }}>
          <SumLine label="Subtotal" value={`€${window.formatAmount(subtotal)}`} />
          <SumLine label="IVA" value={`€${window.formatAmount(vatTotal)}`} />
          <div style={{ borderTop: "1px solid var(--border)", marginTop: 8, paddingTop: 10, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
            <span style={{ fontSize: 14, fontWeight: 600 }}>Total</span>
            <span style={{ fontSize: 22, fontWeight: 700, color: "var(--brand)", fontFamily: "var(--font-mono)" }}>€{window.formatAmount(total)}</span>
          </div>
        </div>
      </div>

      {/* Footer notes */}
      {(form.paymentMethod || form.thanks) && (
        <div style={{ paddingTop: 16, borderTop: "1px solid var(--border)", fontSize: 12, color: "var(--text-muted)", display: "grid", gap: 8 }}>
          {form.paymentMethod && <div><strong style={{ color: "var(--text)" }}>Método de pago:</strong> {form.paymentMethod}</div>}
          {form.thanks && <div style={{ fontStyle: "italic" }}>{form.thanks}</div>}
        </div>
      )}
    </div>
  );
}

function InvoiceEditor({ form, update, updateItem, addItem, removeItem, subtotal, vatTotal, total, clientsById = {} }) {
  const Icons = window.Icons;
  const clientOptions = Object.values(clientsById).map(c => ({ value: c.id, label: c.name }));
  const onClientChange = (clientId) => {
    update("clientId", clientId);
    update("client", clientsById[clientId]?.name || "");
  };
  return (
    <>
      <FormSection title="Detalles">
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 12 }}>
          <label className="field"><span>Empresa emisora</span>
            <input className="input" value={form.issuer} onChange={e => update("issuer", e.target.value)} />
          </label>
          <div className="field"><span>Empresa cliente</span>
            <window.Select
              value={form.clientId}
              onChange={onClientChange}
              options={clientOptions}
              placeholder={clientOptions.length === 0 ? "Sin clientes" : "Seleccionar..."}
              disabled={clientOptions.length === 0}
            />
          </div>
        </div>
        <label className="field" style={{ marginBottom: 12 }}><span>Nombre de la factura</span>
          <input className="input" value={form.name} onChange={e => update("name", e.target.value)} />
        </label>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 12 }}>
          <div className="field"><span>Fecha de emisión</span>
            <window.DatePicker value={form.date} onChange={v => update("date", v)} clearable={false} />
          </div>
          <div className="field"><span>Vencimiento</span>
            <window.DatePicker value={form.dueDate} onChange={v => update("dueDate", v)} />
          </div>
          <div className="field"><span>Estado</span>
            <window.Select
              value={form.status}
              onChange={v => update("status", v)}
              options={[
                { value: "paid", label: "Pagada" },
                { value: "pending", label: "Pendiente" },
                { value: "overdue", label: "Vencida" },
                { value: "draft", label: "Borrador" },
              ]}
            />
          </div>
        </div>
      </FormSection>

      <FormSection title="Líneas de factura">
        <div style={{ background: "var(--bg-sunken)", border: "1px solid var(--border)", borderRadius: 8, overflow: "hidden" }}>
          <table className="tbl lines-table" style={{ fontSize: 12.5 }}>
            <thead>
              <tr>
                <th>Descripción</th>
                <th className="right" style={{ width: 72 }}>Cant.</th>
                <th className="right" style={{ width: 112 }}>Precio</th>
                <th className="right" style={{ width: 70 }}>IVA %</th>
                <th className="right" style={{ width: 100 }}>Total</th>
                <th style={{ width: 28 }}></th>
              </tr>
            </thead>
            <tbody>
              {form.items.map((it, i) => {
                const lineTotal = (it.qty || 0) * (it.price || 0) * (1 + (it.vat || 0) / 100);
                return (
                  <tr key={i}>
                    <td><AutoGrowText value={it.desc} onChange={v => updateItem(i, "desc", v)} /></td>
                    <td><input className="input num-input" type="number" min="0" value={it.qty} onChange={e => updateItem(i, "qty", parseFloat(e.target.value) || 0)} /></td>
                    <td><input className="input num-input" type="number" step="0.01" min="0" inputMode="decimal" value={it.price} onChange={e => updateItem(i, "price", parseFloat(e.target.value) || 0)} onBlur={e => updateItem(i, "price", round2(parseFloat(e.target.value) || 0))} /></td>
                    <td><input className="input num-input" type="number" min="0" max="100" value={it.vat} onChange={e => updateItem(i, "vat", parseFloat(e.target.value) || 0)} /></td>
                    <td className="right num" style={{ fontWeight: 600 }}>€{window.formatAmount(lineTotal)}</td>
                    <td>{form.items.length > 1 && <button className="icon-btn" style={{ width: 22, height: 22 }} onClick={() => removeItem(i)}><Icons.X /></button>}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginTop: 12 }}>
          <button className="btn ghost" onClick={addItem} style={{ borderStyle: "dashed" }}>
            <Icons.Plus /> Añadir línea
          </button>
          <div style={{ minWidth: 240 }}>
            <SumLine label="Subtotal" value={`€${window.formatAmount(subtotal)}`} />
            <SumLine label="IVA" value={`€${window.formatAmount(vatTotal)}`} />
            <div style={{ borderTop: "1px solid var(--border)", marginTop: 6, paddingTop: 8, display: "flex", justifyContent: "space-between" }}>
              <span style={{ fontWeight: 600 }}>Total</span>
              <span style={{ fontWeight: 700, color: "var(--brand)", fontFamily: "var(--font-mono)" }}>€{window.formatAmount(total)}</span>
            </div>
          </div>
        </div>
      </FormSection>

      <FormSection title="Mensajes">
        <label className="field" style={{ marginBottom: 10 }}><span>Método de pago</span>
          <textarea className="input" rows="2" value={form.paymentMethod} onChange={e => update("paymentMethod", e.target.value)} />
        </label>
        <label className="field"><span>Mensaje de agradecimiento</span>
          <textarea className="input" rows="2" value={form.thanks} onChange={e => update("thanks", e.target.value)} />
        </label>
      </FormSection>
    </>
  );
}

function exportInvoiceToPDF(form, total, subtotal, vatTotal) {
  const w = window.open("", "_blank", "width=900,height=1100");
  if (!w) return;
  const fmt = window.formatAmount;
  const itemsHtml = form.items.map(it => {
    const lineTotal = (it.qty || 0) * (it.price || 0) * (1 + (it.vat || 0) / 100);
    return `<tr>
      <td>${it.desc || "—"}</td>
      <td class="r">${it.qty}</td>
      <td class="r">€${fmt(it.price || 0)}</td>
      <td class="r">${it.vat}%</td>
      <td class="r b">€${fmt(lineTotal)}</td>
    </tr>`;
  }).join("");
  w.document.write(`<!doctype html><html><head><meta charset="utf-8"><title>Factura ${form.num}</title>
  <style>
    @page { size: A4; margin: 18mm; }
    * { box-sizing: border-box; }
    body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, sans-serif; color: #1a1a1c; margin: 0; padding: 32px; max-width: 800px; margin: 0 auto; }
    .head { display: flex; justify-content: space-between; align-items: flex-start; padding-bottom: 20px; border-bottom: 1px solid #e5e5e5; margin-bottom: 28px; }
    .h1 { font-size: 24px; font-weight: 700; margin: 0 0 4px 0; }
    .num { font-family: ui-monospace, "SF Mono", Menlo, monospace; }
    .brand { color: #B0301A; }
    .muted { color: #6b6b6b; font-size: 12px; }
    .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin-bottom: 28px; }
    .lbl { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: #999; margin-bottom: 6px; }
    .name { font-weight: 600; font-size: 14px; margin-bottom: 2px; }
    table { width: 100%; border-collapse: collapse; margin-bottom: 16px; font-size: 13px; }
    th { text-align: left; padding: 10px 8px; border-bottom: 2px solid #e5e5e5; font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: #6b6b6b; }
    td { padding: 12px 8px; border-bottom: 1px solid #f0f0f0; }
    .r { text-align: right; }
    .b { font-weight: 600; }
    .totals { display: flex; justify-content: flex-end; margin-bottom: 24px; }
    .totals-box { min-width: 280px; }
    .sumrow { display: flex; justify-content: space-between; padding: 4px 0; color: #6b6b6b; font-size: 13px; }
    .totalrow { border-top: 1px solid #ccc; margin-top: 8px; padding-top: 10px; display: flex; justify-content: space-between; }
    .totalrow .lab { font-size: 14px; font-weight: 600; }
    .totalrow .val { font-size: 22px; font-weight: 700; color: #B0301A; font-family: ui-monospace, monospace; }
    .footer { padding-top: 16px; border-top: 1px solid #e5e5e5; font-size: 12px; color: #6b6b6b; display: grid; gap: 8px; }
    .footer strong { color: #1a1a1c; }
    @media print { body { padding: 0; } }
  </style></head><body>
    <div class="head">
      <div>
        <h1 class="h1">FACTURA</h1>
        <div class="num brand">#${form.num}</div>
        ${form.name ? `<div class="muted" style="margin-top: 4px;">${form.name}</div>` : ""}
      </div>
      <div style="text-align: right;">
        <div class="lbl">Fecha emisión</div>
        <div class="num" style="font-weight: 500; margin-bottom: 8px;">${form.date}</div>
        ${form.dueDate ? `<div class="lbl">Vencimiento</div><div class="num" style="font-weight: 500;">${form.dueDate}</div>` : ""}
      </div>
    </div>
    <div class="grid">
      <div>
        <div class="lbl">De</div>
        <div class="name">${form.issuer}</div>
        <div class="muted">Calle Mayor 12<br/>28013 Madrid, ES<br/>NIF: 12345678A</div>
      </div>
      <div>
        <div class="lbl">Para</div>
        <div class="name">${form.client}</div>
        <div class="muted">Cliente activo<br/>contacto@cliente.com</div>
      </div>
    </div>
    <table>
      <thead><tr><th>Descripción</th><th class="r">Cant.</th><th class="r">Precio</th><th class="r">IVA</th><th class="r">Total</th></tr></thead>
      <tbody>${itemsHtml}</tbody>
    </table>
    <div class="totals">
      <div class="totals-box">
        <div class="sumrow"><span>Subtotal</span><span class="num">€${fmt(subtotal)}</span></div>
        <div class="sumrow"><span>IVA</span><span class="num">€${fmt(vatTotal)}</span></div>
        <div class="totalrow"><span class="lab">Total</span><span class="val">€${fmt(total)}</span></div>
      </div>
    </div>
    ${(form.paymentMethod || form.thanks) ? `<div class="footer">
      ${form.paymentMethod ? `<div><strong>Método de pago:</strong> ${form.paymentMethod}</div>` : ""}
      ${form.thanks ? `<div style="font-style: italic;">${form.thanks}</div>` : ""}
    </div>` : ""}
    <script>window.onload = () => { setTimeout(() => window.print(), 300); };</script>
  </body></html>`);
  w.document.close();
}

Object.assign(window, { InvoicesScreen: window.InvoicesScreen });
