// Solo staff admin area — Invoices. Reached via the sidebar nav in
// AdminShell (see admin-shell.jsx). Reuses ModalError/SectionLabel/
// EmptyNote/ActionButton/adminInputStyle/adminSelectStyle from
// admin-assets-page.jsx (loaded earlier — see index.html).
//
// READ-ONLY ON PURPOSE: invoice records will be pulled from Xero/
// QuickBooks rather than raised in Solo Secure directly, so create/edit/
// status-change controls have been removed from this page (and the
// backing endpoints in routes/admin-invoices.ts). Staff can only VIEW
// invoice records here.
//
// SYNC: once a single customer is selected in the Customer filter, a
// "Sync from Xero/QuickBooks" button appears (never shown with "All
// customers" selected — this is a live, on-demand, per-company pull,
// not a bulk/background job). Calls GET /api/admin/invoices/sync?
// companyId=, which reads LIVE from whichever accounting system that
// company's region maps to (Xero for UK/EU/Rest of the World, QuickBooks
// for North America — see routes/admin-invoices.ts) and returns the
// result directly; nothing is written to our own `invoices` table. Fully
// re-runnable on demand, per the confirmed design ("Should be live with
// the ability to update"). The synced list is rendered separately, above
// our own local invoice records, so the two never get confused with each
// other.

const INVOICE_STATUS_LABELS_UI = { draft: "Draft", sent: "Sent", paid: "Paid", overdue: "Overdue", cancelled: "Cancelled" };
const INVOICE_STATUS_COLORS = {
  draft: "rgba(0,0,0,0.55)",
  sent: "rgba(30,110,190,0.95)",
  paid: "rgba(20,140,60,0.95)",
  overdue: "rgba(180,110,0,0.95)",
  cancelled: "rgba(190,40,40,0.9)",
};
const INVOICE_STATUS_FLOW = ["draft", "sent", "paid", "overdue", "cancelled"];

function money(amount, currency) {
  const symbols = { GBP: "£", USD: "$", EUR: "€" };
  return `${symbols[currency] || ""}${Number(amount).toFixed(2)}`;
}

// Region -> accounting system label, same gate used server-side
// (isValidRegion(region) && region === "North America" -> QuickBooks).
function accountingSystemFor(region) {
  return region === "North America" ? "QuickBooks" : "Xero";
}

function SyncedInvoiceRow({ inv, system }) {
  return (
    <div style={{
      display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10, flexWrap: "wrap",
      padding: "10px 14px", background: "rgba(0,0,0,0.02)", border: "1px solid rgba(0,0,0,0.1)",
    }}>
      <div style={{ fontFamily: "var(--font-body)", fontSize: 13, color: "rgba(0,0,0,0.8)" }}>
        {inv.invoiceNumber || "(no number)"}
        {inv.date && <span style={{ color: "rgba(0,0,0,0.45)" }}> · {inv.date}</span>}
        {inv.dueDate && <span style={{ color: "rgba(0,0,0,0.45)" }}> · due {inv.dueDate}</span>}
        {inv.status && <span style={{ color: "rgba(0,0,0,0.45)", textTransform: "uppercase" }}> · {inv.status}</span>}
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
        <div style={{ fontFamily: "var(--font-body)", fontSize: 13, color: "rgba(0,0,0,0.8)", fontWeight: 600 }}>
          {money(inv.total, inv.currency)}
          {system === "quickbooks"
            ? (inv.balance ? <span style={{ fontWeight: 400, color: "rgba(180,110,0,0.95)" }}> ({money(inv.balance, inv.currency)} due)</span> : null)
            : (inv.amountDue ? <span style={{ fontWeight: 400, color: "rgba(180,110,0,0.95)" }}> ({money(inv.amountDue, inv.currency)} due)</span> : null)}
        </div>
        {inv.url && (
          <a href={inv.url} target="_blank" rel="noreferrer" style={{ fontFamily: "var(--font-body)", fontSize: 11.5, letterSpacing: "0.1em", textTransform: "uppercase", color: "rgba(30,110,190,0.95)", textDecoration: "underline" }}>
            Open →
          </a>
        )}
      </div>
    </div>
  );
}

function InvoiceSyncPanel({ companyId, companyName, companyRegion }) {
  const [state, setState] = useState({ status: "idle" });
  const system = accountingSystemFor(companyRegion);

  const runSync = () => {
    setState({ status: "loading" });
    fetch(`/api/admin/invoices/sync?companyId=${companyId}`, { credentials: "same-origin" })
      .then((r) => r.json().then((d) => ({ ok: r.ok, d })))
      .then(({ ok, d }) => {
        if (!ok) { setState({ status: "error", error: d.error || "Sync failed." }); return; }
        setState({ status: "ready", data: d });
      })
      .catch(() => setState({ status: "error", error: "Couldn't reach the server. Check your connection and try again." }));
  };

  return (
    <div style={{ background: "rgba(30,110,190,0.04)", border: "1px solid rgba(30,110,190,0.25)", padding: "18px 20px", marginBottom: 24 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
        <div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.18em", textTransform: "uppercase", color: "rgba(30,110,190,0.95)", fontWeight: 500, marginBottom: 4 }}>
            Live sync — {system}
          </div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 13, color: "rgba(0,0,0,0.65)" }}>
            Pull <strong>{companyName}</strong>'s invoices straight from {system}. Nothing is saved locally — re-run any time.
          </div>
        </div>
        <ActionButton testId="invoice-sync-run" disabled={state.status === "loading"} onClick={runSync}>
          {state.status === "loading" ? "Syncing…" : state.status === "ready" ? `Re-sync from ${system}` : `Sync from ${system}`}
        </ActionButton>
      </div>

      {state.status === "error" && (
        <div style={{ marginTop: 14 }}><ModalError>{state.error}</ModalError></div>
      )}

      {state.status === "ready" && !state.data.connected && (
        <div style={{ marginTop: 14, fontFamily: "var(--font-body)", fontSize: 13, color: "rgba(190,40,40,0.9)" }}>
          {system} isn't connected yet. Connect it on the Settings page's Data Connections section, then try again.
        </div>
      )}
      {state.status === "ready" && state.data.connected && state.data.linked === false && (
        <div style={{ marginTop: 14, fontFamily: "var(--font-body)", fontSize: 13, color: "rgba(190,40,40,0.9)" }}>
          {companyName} isn't linked to a {system} {system === "Xero" ? "contact" : "customer"} yet. Link it on the Customer record page, then try again.
        </div>
      )}
      {state.status === "ready" && state.data.connected && state.data.linked !== false && state.data.error && (
        <div style={{ marginTop: 14 }}><ModalError>{state.data.error}</ModalError></div>
      )}
      {state.status === "ready" && state.data.connected && state.data.linked !== false && !state.data.error && (
        state.data.invoices.length === 0 ? (
          <div style={{ marginTop: 14, fontFamily: "var(--font-body)", fontSize: 13, color: "rgba(0,0,0,0.5)" }}>
            No invoices found in {system} for this customer.
          </div>
        ) : (
          <div style={{ display: "flex", flexDirection: "column", gap: 8, marginTop: 14 }}>
            {state.data.invoices.map((inv) => (
              <SyncedInvoiceRow key={inv.invoiceId} inv={inv} system={state.data.source} />
            ))}
          </div>
        )
      )}
    </div>
  );
}

function AdminInvoicesPage({ onNavigate }) {
  const [state, setState] = useState({ status: "loading", admin: null, invoices: [], companies: [] });
  const [companyFilter, setCompanyFilter] = useState("");
  const [statusFilter, setStatusFilter] = useState("");
  const [openId, setOpenId] = useState(null);

  const load = () => {
    const params = new URLSearchParams();
    if (companyFilter) params.set("companyId", companyFilter);
    if (statusFilter) params.set("status", statusFilter);
    Promise.all([
      fetch("/api/admin/me", { credentials: "same-origin" }).then((r) => (r.ok ? r.json() : Promise.reject())),
      fetch(`/api/admin/invoices?${params.toString()}`, { credentials: "same-origin" }).then((r) => (r.ok ? r.json() : Promise.reject())),
      fetch("/api/admin/companies", { credentials: "same-origin" }).then((r) => (r.ok ? r.json() : Promise.reject())),
    ])
      .then(([me, invoices, companies]) => {
        setState({
          status: "ready", admin: me.admin,
          invoices: invoices.invoices || [], companies: companies.companies || [],
        });
      })
      .catch(() => onNavigate("admin-login"));
  };

  useEffect(load, [companyFilter, statusFilter]); // eslint-disable-line react-hooks/exhaustive-deps

  if (state.status === "loading") {
    return <section style={{ background: "#fff", minHeight: "calc(100vh - 88px)" }} />;
  }

  const selectedCompany = companyFilter ? state.companies.find((co) => String(co.id) === String(companyFilter)) : null;

  return (
    <AdminShell admin={state.admin} page="admin-invoices" onNavigate={onNavigate}
      subtitle="Staff only — read-only, pulled from Xero/QuickBooks" title="Invoices.">
      <div style={{ display: "flex", gap: 12, flexWrap: "wrap", marginBottom: 24 }}>
        <MiniField label="Customer">
          <select value={companyFilter} onChange={(e) => setCompanyFilter(e.target.value)} style={adminSelectStyle}>
            <option value="">All customers</option>
            {state.companies.map((co) => <option key={co.id} value={co.id}>{co.name}</option>)}
          </select>
        </MiniField>
        <MiniField label="Status">
          <select value={statusFilter} onChange={(e) => setStatusFilter(e.target.value)} style={adminSelectStyle}>
            <option value="">All statuses</option>
            {INVOICE_STATUS_FLOW.map((s) => <option key={s} value={s}>{INVOICE_STATUS_LABELS_UI[s]}</option>)}
          </select>
        </MiniField>
      </div>

      {selectedCompany && (
        <InvoiceSyncPanel
          key={selectedCompany.id}
          companyId={selectedCompany.id}
          companyName={selectedCompany.name}
          companyRegion={selectedCompany.region}
        />
      )}

      <SectionLabel>Invoices ({state.invoices.length})</SectionLabel>
      {state.invoices.length === 0 ? (
        <EmptyNote>No invoices raised yet.</EmptyNote>
      ) : (
        <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          {state.invoices.map((inv) => (
            <InvoiceRow
              key={inv.id} invoice={inv}
              open={openId === inv.id}
              onToggle={() => setOpenId(openId === inv.id ? null : inv.id)}
            />
          ))}
        </div>
      )}
    </AdminShell>
  );
}

function InvoiceRow({ invoice, open, onToggle }) {
  return (
    <div data-testid={`invoice-row-${invoice.id}`} style={{
      background: "rgba(0,0,0,0.02)", border: "1px solid rgba(0,0,0,0.14)",
    }}>
      <button
        type="button" onClick={onToggle} data-testid={`invoice-toggle-${invoice.id}`}
        style={{
          width: "100%", background: "none", border: "none", cursor: "pointer",
          padding: "16px 20px", display: "flex", justifyContent: "space-between",
          alignItems: "center", flexWrap: "wrap", gap: 12, textAlign: "left",
        }}>
        <div>
          <div style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 15, textTransform: "uppercase", color: "#000" }}>
            Invoice #{invoice.id} <span style={{ color: "rgba(0,0,0,0.55)", fontSize: 12, fontWeight: 400 }}>· {invoice.company_name}</span>
          </div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 12, color: "rgba(0,0,0,0.55)", marginTop: 4 }}>
            <span style={{ color: INVOICE_STATUS_COLORS[invoice.status] || "rgba(0,0,0,0.55)", textTransform: "uppercase", letterSpacing: "0.08em", fontSize: 11 }}>
              {INVOICE_STATUS_LABELS_UI[invoice.status] || invoice.status}
            </span>
            {" · "}{invoice.item_count} item{invoice.item_count === 1 ? "" : "s"} · {money(invoice.total, invoice.currency)}
            {invoice.order_id && <> · from Order #{invoice.order_id}</>}
          </div>
        </div>
        <span style={{ fontFamily: "var(--font-body)", fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.55)" }}>
          {open ? "Close ↑" : "Amend →"}
        </span>
      </button>
      {open && <InvoiceDetail invoiceId={invoice.id} />}
    </div>
  );
}

function InvoiceDetail({ invoiceId }) {
  const [data, setData] = useState(null);
  const [error, setError] = useState("");

  const load = () => {
    fetch(`/api/admin/invoices/${invoiceId}`, { credentials: "same-origin" })
      .then((r) => (r.ok ? r.json() : Promise.reject()))
      .then((d) => setData(d))
      .catch(() => setError("Couldn't load this invoice."));
  };

  useEffect(load, [invoiceId]); // eslint-disable-line react-hooks/exhaustive-deps

  if (!data) {
    return (
      <div style={{ borderTop: "1px solid rgba(0,0,0,0.14)", padding: "20px" }}>
        {error ? <ModalError>{error}</ModalError> : <EmptyNote>Loading…</EmptyNote>}
      </div>
    );
  }

  const { invoice, items } = data;

  const subtotal = items.reduce((sum, it) => sum + it.unit_price * it.quantity * (1 - (it.discount_percent || 0) / 100), 0);

  return (
    <div style={{ borderTop: "1px solid rgba(0,0,0,0.14)", padding: "20px" }}>
      {error && <ModalError>{error}</ModalError>}

      <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.24em", textTransform: "uppercase", color: "rgba(180,110,0,0.95)", fontWeight: 500, marginBottom: 12 }}>
        Line items ({items.length}) <span style={{ textTransform: "none", letterSpacing: 0, fontWeight: 400, color: "rgba(0,0,0,0.4)" }}>— read-only, from Xero/QuickBooks</span>
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 8, marginBottom: 16 }}>
        {items.map((it) => (
          <div key={it.id} style={{
            display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10, flexWrap: "wrap",
            padding: "8px 12px", background: "rgba(0,0,0,0.02)", border: "1px solid rgba(0,0,0,0.1)",
          }}>
            <div style={{ fontFamily: "var(--font-body)", fontSize: 13, color: "rgba(0,0,0,0.8)" }}>
              {it.description || it.product_name} × {it.quantity} @ {money(it.unit_price, invoice.currency)}
              {it.discount_percent ? ` (-${it.discount_percent}%)` : ""}
            </div>
          </div>
        ))}
      </div>

      <div style={{ display: "grid", gap: 14, gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))", marginBottom: 14 }}>
        {invoice.discount_percent ? (
          <div>
            <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.45)", marginBottom: 4 }}>Discount %</div>
            <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)" }}>{invoice.discount_percent}%</div>
          </div>
        ) : null}
        {invoice.due_at ? (
          <div>
            <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.45)", marginBottom: 4 }}>Due date</div>
            <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)" }}>{String(invoice.due_at).slice(0, 10)}</div>
          </div>
        ) : null}
      </div>
      {invoice.notes ? (
        <div style={{ marginBottom: 14 }}>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "rgba(0,0,0,0.45)", marginBottom: 4 }}>Notes</div>
          <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)", whiteSpace: "pre-wrap" }}>{invoice.notes}</div>
        </div>
      ) : null}
      <div style={{ display: "flex", alignItems: "center", gap: 12, marginTop: 6 }}>
        <div style={{ fontFamily: "var(--font-body)", fontSize: 13.5, color: "rgba(0,0,0,0.8)" }}>
          Subtotal {money(subtotal, invoice.currency)} → Total <strong>{money(subtotal * (1 - (invoice.discount_percent || 0) / 100), invoice.currency)}</strong>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { AdminInvoicesPage });
