// Nexa — page components (Overview, Transactions, Beneficiaries)
// All data fetched live from window.TC_API.

const {
  fmtN, fmtMoney, fmtDate, fmtDateLong, fmtTime, fmtRelative, fmtUntil,
  labelOp, symbolFor,
  normTxn, normApproval, normBeneficiary, normAccount,
  useFetch,
} = window.TC_HELPERS;
const {
  StatusBadge, DirectionGlyph, Flag, AgentTag,
  Spinner, LoadingBlock, ErrorBlock,
  PlusIcon, CheckIcon, XIcon, RefreshIcon,
} = window.TC_UI;

// ────────────────────────────────────────────────────────────
// OVERVIEW
// ────────────────────────────────────────────────────────────
function OverviewPage({ agents, onNavigate, onPendingCount }) {
  const accountsQ  = useFetch(() => TC_API.getAccounts(),       [], { polling: 30000 });
  const summaryQ   = useFetch(() => TC_API.getSummary(),        [], { polling: 15000 });
  const approvalsQ = useFetch(() => TC_API.getApprovals(),      [], { polling: 5000  });
  const txnsQ      = useFetch(() => TC_API.getTransactions({ limit: 7 }), [], { polling: 10000 });

  const accounts  = useMemo(() => (accountsQ.data  || []).map(normAccount),     [accountsQ.data]);
  const approvals = useMemo(() => (approvalsQ.data || []).map(normApproval)
                                  .filter(a => a.status === "pending_approval" || a.status === "pending"),
                                [approvalsQ.data]);
  const recent    = useMemo(() => (txnsQ.data      || []).map(normTxn),         [txnsQ.data]);
  const summary   = summaryQ.data || {};
  const today     = summary.today || {};

  // Notify shell so the side-nav badge can show pending count
  useEffect(() => { onPendingCount && onPendingCount(approvals.length); }, [approvals.length, onPendingCount]);

  const onApprove = async (id) => {
    try { await TC_API.approveApproval(id); approvalsQ.refetch(); txnsQ.refetch(); accountsQ.refetch(); summaryQ.refetch(); }
    catch (e) { alert(`Approve failed: ${e.message}`); }
  };
  const onReject = async (id) => {
    try { await TC_API.rejectApproval(id); approvalsQ.refetch(); txnsQ.refetch(); accountsQ.refetch(); summaryQ.refetch(); }
    catch (e) { alert(`Reject failed: ${e.message}`); }
  };

  const paymentsEnabled = summary.payments_enabled !== false ? true : (summaryQ.loading ? null : false);
  const [activating, setActivating] = React.useState(false);
  const onActivatePayments = async () => {
    setActivating(true);
    try { await TC_API.activatePayments(); summaryQ.refetch(); }
    catch (e) { alert(`Activation failed: ${e.message}`); }
    finally { setActivating(false); }
  };

  return (
    <div className="tc-page">
      {/* Payments not active banner */}
      {paymentsEnabled === false && (
        <div className="tc-banner tc-banner--warn">
          <div className="tc-banner-body">
            <strong>Payments not yet active.</strong>{" "}
            Review your policy rules and activate payments to allow your agent to start operating.
          </div>
          <div className="tc-banner-actions">
            <button className="tc-btn tc-btn--sm" onClick={() => onNavigate && onNavigate("policies")}>
              Review policies
            </button>
            <button className="tc-btn tc-btn--primary tc-btn--sm" onClick={onActivatePayments} disabled={activating}>
              {activating ? "Activating…" : "Activate payments"}
            </button>
          </div>
        </div>
      )}
      {/* Account cards */}
      <section>
        <div className="tc-block-h">
          <h2>Accounts</h2>
          <span className="tc-block-h-meta">
            {accountsQ.loading ? "loading…" : `${accounts.length} ${accounts.length === 1 ? "account" : "accounts"}`}
          </span>
        </div>

        {accountsQ.loading && !accounts.length ? <LoadingBlock label="Loading accounts…" /> :
         accountsQ.error ? <ErrorBlock error={accountsQ.error} onRetry={accountsQ.refetch} label="Couldn't load accounts" /> :
         accounts.length === 0 ? <div className="tc-card tc-empty">No accounts yet.</div> :
         <div className="tc-accounts">
          {accounts.map(a => (
            <article key={a.id} className="tc-acct">
              <div className="tc-acct-head">
                <span className="tc-acct-cur">
                  <span className="tc-acct-cur-flag">{symbolFor(a.currency) || a.currency?.[0] || "•"}</span>
                  {a.currency}
                </span>
                <span className="tc-acct-label">{a.label || "—"}</span>
              </div>
              <div>
                <div className="tc-acct-balance">
                  <span className="tc-acct-balance-sym">{symbolFor(a.currency)}</span>
                  <span className="tc-acct-balance-v">{fmtN(a.balance)}</span>
                </div>
                <div className="tc-acct-iban">{a.iban || "—"}</div>
              </div>
              <div className="tc-acct-split">
                <div className="tc-acct-split-cell">
                  <span className="tc-acct-split-k">AVAILABLE</span>
                  <span className="tc-acct-split-v">{fmtMoney(a.available, a.currency)}</span>
                </div>
                <div className="tc-acct-split-cell">
                  <span className="tc-acct-split-k">HELD</span>
                  <span className={`tc-acct-split-v ${a.held > 0 ? "is-held" : "is-zero"}`}>
                    {fmtMoney(a.held, a.currency)}
                  </span>
                </div>
              </div>
            </article>
          ))}
         </div>}
      </section>

      {/* Summary metrics */}
      <section>
        {summaryQ.error ? <ErrorBlock error={summaryQ.error} onRetry={summaryQ.refetch} label="Couldn't load summary" /> :
         <div className="tc-metrics">
          <div className="tc-metric">
            <span className="tc-metric-k">Pending approvals</span>
            <span className={`tc-metric-v ${(summary.pending_approval_count || 0) > 0 ? "is-pending" : ""}`}>
              {summary.pending_approval_count ?? (summaryQ.loading ? <Spinner /> : 0)}
            </span>
            <span className="tc-metric-d">{(summary.pending_approval_count || 0) > 0 ? "awaiting your sign-off" : "all clear"}</span>
          </div>
          <div className="tc-metric">
            <span className="tc-metric-k">Active agents</span>
            <span className="tc-metric-v">{summary.active_agent_count ?? (summaryQ.loading ? <Spinner /> : 0)}</span>
            <span className="tc-metric-d">registered &amp; operating</span>
          </div>
          <div className="tc-metric">
            <span className="tc-metric-k">Today · transactions</span>
            <span className="tc-metric-v">{today.total_transactions ?? (summaryQ.loading ? <Spinner /> : 0)}</span>
            <span className="tc-metric-d">
              {today.approved != null ? `${today.approved} approved` : ""}
              {today.rejected != null ? ` · ${today.rejected} rejected` : ""}
            </span>
          </div>
          <div className="tc-metric">
            <span className="tc-metric-k">Open info requests</span>
            <span className="tc-metric-v">{summary.open_information_requests_count ?? (summaryQ.loading ? <Spinner /> : 0)}</span>
            <span className="tc-metric-d">agent-initiated</span>
          </div>
         </div>}
      </section>

      {/* Pending approvals */}
      <section>
        <div className="tc-block-h">
          <h2>Pending approvals</h2>
          <span className="tc-block-h-meta">held by policy</span>
        </div>

        {approvalsQ.loading && !approvals.length ? <div className="tc-card"><LoadingBlock label="Loading approvals…" /></div> :
         approvalsQ.error ? <ErrorBlock error={approvalsQ.error} onRetry={approvalsQ.refetch} label="Couldn't load approvals" /> :
         <div className="tc-card">
          {approvals.length === 0 && (
            <div className="tc-approval-empty">No instructions held. Agents are operating within policy.</div>
          )}
          {approvals.map(t => (
            <div key={t.id} className="tc-approval">
              <div className="tc-approval-l" style={{ display: "flex", gap: 20, alignItems: "stretch" }}>
                <div className="tc-approval-amt">
                  <span className="tc-approval-amt-cur">{t.currency || ""} {t.operation ? `· ${labelOp(t.operation)}` : ""}</span>
                  <span className="tc-approval-amt-v">{fmtMoney(Math.abs(t.amount), t.currency)}</span>
                  <span className="tc-approval-detail" style={{marginTop:6}}>
                    <AgentTag agentId={t.agentId} agents={agents} />
                  </span>
                </div>
                <div className="tc-approval-meta">
                  <div className="tc-approval-counterparty">
                    {t.destination && <Flag code={t.destination} />}
                    {t.counterparty || "—"}
                  </div>
                  <div className="tc-approval-detail">
                    <span>id · {t.id}</span>
                    {t.createdAt && <span>· submitted {fmtRelative(t.createdAt)}</span>}
                  </div>
                  {t.reason && <div className="tc-approval-reason">{t.reason}</div>}
                </div>
              </div>
              <div className="tc-approval-r">
                {t.expiresAt && <span className="tc-approval-time">expires {fmtUntil(t.expiresAt)}</span>}
                <div className="tc-approval-actions">
                  <button className="tc-btn tc-btn-ghost" onClick={() => onReject(t.id)}>
                    <XIcon /> Reject
                  </button>
                  <button className="tc-btn tc-btn-accent" onClick={() => onApprove(t.id)}>
                    <CheckIcon /> Approve
                  </button>
                </div>
              </div>
            </div>
          ))}
         </div>}
      </section>

      {/* Recent transactions */}
      <section>
        <div className="tc-block-h">
          <h2>Recent transactions</h2>
          <button className="tc-btn tc-btn-ghost tc-btn-sm" onClick={() => onNavigate("transactions")}>
            View all
          </button>
        </div>

        {txnsQ.loading && !recent.length ? <div className="tc-card"><LoadingBlock label="Loading transactions…" /></div> :
         txnsQ.error ? <ErrorBlock error={txnsQ.error} onRetry={txnsQ.refetch} label="Couldn't load transactions" /> :
         recent.length === 0 ? <div className="tc-card tc-empty">No transactions yet.</div> :
         <div className="tc-card">
          {recent.map(t => (
            <div key={t.id} className="tc-feed-row">
              <span className="tc-time">
                <div>{fmtTime(t.timestamp)}</div>
                <div className="tc-time-d">{fmtDate(t.timestamp)}</div>
              </span>
              <DirectionGlyph dir={t.direction} />
              <div className="tc-counterparty">
                <span className="tc-counterparty-name">{t.counterparty || "—"}</span>
                <span className="tc-counterparty-meta">{t.country || "—"} · {labelOp(t.operation)}</span>
              </div>
              <AgentTag agentId={t.agentId} agentName={t.agentName} agents={agents} />
              <span className={`tc-feed-amt ${t.direction === "in" ? "is-in" : ""} ${t.status === "rejected" ? "is-rejected" : ""}`}>
                {t.direction === "in" ? "+" : "−"}{fmtMoney(t.amount, t.currency)}
              </span>
              <StatusBadge status={t.status} />
            </div>
          ))}
         </div>}
      </section>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// TRANSACTIONS
// ────────────────────────────────────────────────────────────
function TransactionsPage({ agents }) {
  const [filter, setFilter] = useState("all");
  const txnsQ = useFetch(
    () => TC_API.getTransactions({ status: filter, limit: 200 }),
    [filter],
    { polling: 15000 }
  );
  const txns = useMemo(() => (txnsQ.data || []).map(normTxn), [txnsQ.data]);

  return (
    <div className="tc-page">
      <section>
        <div className="tc-block-h">
          <h2>All transactions</h2>
          <div className="tc-filters">
            {[
              { k: "all", label: "All" },
              { k: "approved", label: "Approved" },
              { k: "pending_approval", label: "Pending" },
              { k: "rejected", label: "Rejected" },
            ].map(f => (
              <button
                key={f.k}
                className={`tc-filter ${filter === f.k ? "is-on" : ""}`}
                onClick={() => setFilter(f.k)}
              >
                {f.label}
              </button>
            ))}
            <button className="tc-filter" onClick={txnsQ.refetch} title="Refresh">
              <RefreshIcon />
            </button>
          </div>
        </div>

        {txnsQ.loading && !txns.length ? <div className="tc-card"><LoadingBlock label="Loading transactions…" /></div> :
         txnsQ.error ? <ErrorBlock error={txnsQ.error} onRetry={txnsQ.refetch} label="Couldn't load transactions" /> :
         <div className="tc-card" style={{ overflow: "auto" }}>
          <table className="tc-table">
            <thead>
              <tr>
                <th style={{width: 90}}>Time</th>
                <th style={{width: 90}}>Date</th>
                <th style={{width: 60}}>Dir.</th>
                <th>Counterparty</th>
                <th>Agent</th>
                <th style={{width: 110}}>Currency</th>
                <th style={{width: 160, textAlign: "right"}}>Amount</th>
                <th style={{width: 160}}>Status</th>
              </tr>
            </thead>
            <tbody>
              {txns.map(t => (
                <tr key={t.id}>
                  <td className="tc-time">{fmtTime(t.timestamp)}</td>
                  <td className="tc-time">{fmtDate(t.timestamp)}</td>
                  <td><DirectionGlyph dir={t.direction} /></td>
                  <td>
                    <div className="tc-counterparty">
                      <span className="tc-counterparty-name">{t.counterparty || "—"}</span>
                      <span className="tc-counterparty-meta">
                        {t.country || "—"} · {labelOp(t.operation)} · {t.id}
                      </span>
                      {t.paymentReason && (
                        <span className="tc-counterparty-meta">↳ {t.paymentReason}</span>
                      )}
                    </div>
                  </td>
                  <td><AgentTag agentId={t.agentId} agentName={t.agentName} agents={agents} /></td>
                  <td className="is-mono">{t.currency}</td>
                  <td className={`is-num ${t.direction === "in" ? "is-in" : "is-out"} ${t.status === "rejected" ? "is-rejected-amt" : ""}`}>
                    {t.direction === "in" ? "+" : "−"}{fmtMoney(t.amount, t.currency)}
                  </td>
                  <td><StatusBadge status={t.status} /></td>
                </tr>
              ))}
              {txns.length === 0 && (
                <tr><td colSpan="8" className="tc-empty">No transactions match this filter.</td></tr>
              )}
            </tbody>
          </table>
         </div>}
      </section>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// BENEFICIARIES
// ────────────────────────────────────────────────────────────
function BeneficiariesPage() {
  const benQ = useFetch(() => TC_API.getBeneficiaries(), [], { polling: 30000 });
  const beneficiaries = useMemo(() => (benQ.data || []).map(normBeneficiary), [benQ.data]);

  const [showForm, setShowForm] = useState(false);
  const [busyId, setBusyId] = useState(null);

  const onApprove = async (id) => {
    setBusyId(id);
    try { await TC_API.approveBeneficiary(id); benQ.refetch(); }
    catch (e) { alert(`Approve failed: ${e.message}`); }
    finally { setBusyId(null); }
  };
  const onBlock = async (id) => {
    const reason = prompt("Reason for blocking this beneficiary?", "");
    if (reason == null) return;
    setBusyId(id);
    try { await TC_API.blockBeneficiary(id, reason); benQ.refetch(); }
    catch (e) { alert(`Block failed: ${e.message}`); }
    finally { setBusyId(null); }
  };

  const pendingCount = beneficiaries.filter(b => b.status === "pending_review" || b.status === "pending").length;

  return (
    <div className="tc-page">
      <section>
        <div className="tc-block-h">
          <h2>Beneficiaries</h2>
          <div style={{display:"flex", gap: 10, alignItems:"center"}}>
            <span className="tc-block-h-meta">
              {benQ.loading ? "loading…" : `${beneficiaries.length} total · ${pendingCount} pending review`}
            </span>
            <button className="tc-btn tc-btn-primary" onClick={() => setShowForm(s => !s)}>
              <PlusIcon /> {showForm ? "Cancel" : "Add beneficiary"}
            </button>
          </div>
        </div>

        {showForm && (
          <AddBeneficiaryForm
            onCancel={() => setShowForm(false)}
            onSubmit={async (b) => {
              try {
                await TC_API.addBeneficiary(b);
                setShowForm(false);
                benQ.refetch();
              } catch (e) {
                alert(`Add failed: ${e.message}`);
              }
            }}
          />
        )}

        {benQ.loading && !beneficiaries.length ? <div className="tc-card"><LoadingBlock label="Loading beneficiaries…" /></div> :
         benQ.error ? <ErrorBlock error={benQ.error} onRetry={benQ.refetch} label="Couldn't load beneficiaries" /> :
         <div className="tc-card" style={{ overflow: "auto" }}>
          <table className="tc-table">
            <thead>
              <tr>
                <th>Name</th>
                <th style={{width: 80}}>Country</th>
                <th style={{width: 80}}>Currency</th>
                <th>IBAN</th>
                <th style={{width: 110}}>Added</th>
                <th style={{width: 110}}>Last paid</th>
                <th style={{width: 140, textAlign: "right"}}>Total paid</th>
                <th style={{width: 150}}>Status</th>
                <th style={{width: 170}}></th>
              </tr>
            </thead>
            <tbody>
              {beneficiaries.map(b => {
                const isPending = b.status === "pending_review" || b.status === "pending";
                const isBlocked = b.status === "blocked";
                return (
                  <tr key={b.id} className="tc-ben-row">
                    <td>
                      <div className="tc-counterparty">
                        <span className="tc-counterparty-name">{b.name || "—"}</span>
                        <span className="tc-counterparty-meta">{b.id}</span>
                      </div>
                    </td>
                    <td><Flag code={b.country} /></td>
                    <td className="is-mono">{b.currency}</td>
                    <td className="is-mono" style={{color: "var(--fg-3)"}}>{b.iban || "—"}</td>
                    <td className="tc-time">{fmtDate(b.addedAt)}</td>
                    <td className="tc-time">{b.lastPaidAt ? fmtDate(b.lastPaidAt) : "—"}</td>
                    <td className="is-num">{b.totalPaid > 0 ? fmtMoney(b.totalPaid, b.currency) : "—"}</td>
                    <td><StatusBadge status={b.status} /></td>
                    <td>
                      <div style={{display:"flex", gap: 6, justifyContent:"flex-end"}}>
                        {isPending && (
                          <button className="tc-btn tc-btn-accent tc-btn-sm" disabled={busyId === b.id} onClick={() => onApprove(b.id)}>
                            <CheckIcon /> Approve
                          </button>
                        )}
                        {!isBlocked && (
                          <button className="tc-btn tc-btn-danger tc-btn-sm" disabled={busyId === b.id} onClick={() => onBlock(b.id)}>
                            Block
                          </button>
                        )}
                      </div>
                    </td>
                  </tr>
                );
              })}
              {beneficiaries.length === 0 && (
                <tr><td colSpan="9" className="tc-empty">No beneficiaries yet. Add one to enable agent payments.</td></tr>
              )}
            </tbody>
          </table>
         </div>}

        <p style={{fontSize: 12, color: "var(--fg-4)", marginTop: 12, fontFamily: "var(--font-mono)", letterSpacing: "0.02em"}}>
          New beneficiaries enter <strong style={{color:"var(--warn)", fontWeight:500}}>pending review</strong> by default.
          Agents cannot transact to a beneficiary until a principal approves it.
        </p>
      </section>
    </div>
  );
}

// ── Client-side IBAN validation (ISO 7064 mod-97, no external API) ──────────
const IBAN_LENGTHS = {
  AL:28,AD:24,AT:20,AZ:28,BH:22,BE:16,BA:20,BR:29,BG:22,BY:28,CR:22,HR:21,
  CY:28,CZ:24,DK:18,DO:28,SV:28,EE:20,FO:18,FI:18,FR:27,GE:22,DE:22,GI:23,
  GR:27,GL:18,GT:28,HU:28,IS:26,IQ:23,IE:22,IL:23,IT:27,JO:30,KZ:20,XK:20,
  KW:30,LV:21,LB:28,LI:21,LT:20,LU:20,MK:19,MT:31,MR:27,MU:30,MC:27,MD:24,
  ME:22,NL:18,NO:15,PK:24,PS:29,PL:28,PT:25,QA:29,RO:24,SM:27,SA:24,RS:22,
  SC:31,SK:24,SI:19,ES:24,SE:24,CH:21,TN:24,TR:26,AE:23,GB:22,VA:22,VG:24,
};
const IBAN_COUNTRY_NAMES = {
  AL:"Albania",AD:"Andorra",AT:"Austria",AZ:"Azerbaijan",BH:"Bahrain",BE:"Belgium",
  BA:"Bosnia",BR:"Brazil",BG:"Bulgaria",BY:"Belarus",CR:"Costa Rica",HR:"Croatia",
  CY:"Cyprus",CZ:"Czech Republic",DK:"Denmark",DO:"Dominican Republic",SV:"El Salvador",
  EE:"Estonia",FO:"Faroe Islands",FI:"Finland",FR:"France",GE:"Georgia",DE:"Germany",
  GI:"Gibraltar",GR:"Greece",GL:"Greenland",GT:"Guatemala",HU:"Hungary",IS:"Iceland",
  IQ:"Iraq",IE:"Ireland",IL:"Israel",IT:"Italy",JO:"Jordan",KZ:"Kazakhstan",XK:"Kosovo",
  KW:"Kuwait",LV:"Latvia",LB:"Lebanon",LI:"Liechtenstein",LT:"Lithuania",LU:"Luxembourg",
  MK:"North Macedonia",MT:"Malta",MR:"Mauritania",MU:"Mauritius",MC:"Monaco",MD:"Moldova",
  ME:"Montenegro",NL:"Netherlands",NO:"Norway",PK:"Pakistan",PS:"Palestine",PL:"Poland",
  PT:"Portugal",QA:"Qatar",RO:"Romania",SM:"San Marino",SA:"Saudi Arabia",RS:"Serbia",
  SC:"Seychelles",SK:"Slovakia",SI:"Slovenia",ES:"Spain",SE:"Sweden",CH:"Switzerland",
  TN:"Tunisia",TR:"Turkey",AE:"UAE",GB:"United Kingdom",VA:"Vatican City",VG:"British Virgin Islands",
};

function validateIban(raw) {
  if (!raw || !raw.trim()) return { valid: false, error: null }; // empty = no error shown
  const norm = raw.replace(/[\s\-]/g, "").toUpperCase();
  if (norm.length < 5) return { valid: false, error: "Too short" };
  const cc = norm.slice(0, 2);
  if (!/^[A-Z]{2}$/.test(cc)) return { valid: false, error: "Must start with a 2-letter country code" };
  if (!/^\d{2}/.test(norm.slice(2))) return { valid: false, error: "Positions 3–4 must be digits" };
  const expected = IBAN_LENGTHS[cc];
  if (expected && norm.length !== expected) return { valid: false, error: `${cc} IBANs must be ${expected} characters (got ${norm.length})` };
  // Mod-97
  const rearranged = norm.slice(4) + norm.slice(0, 4);
  const digits = rearranged.split("").map(c => /[A-Z]/.test(c) ? String(c.charCodeAt(0) - 55) : c).join("");
  let remainder = 0;
  for (const chunk of digits.match(/.{1,9}/g) || []) {
    remainder = Number(String(remainder) + chunk) % 97;
  }
  if (remainder !== 1) return { valid: false, error: "Check digits are incorrect — please re-check the IBAN" };
  return { valid: true, country: cc, countryName: IBAN_COUNTRY_NAMES[cc] || cc, formatted: norm.match(/.{1,4}/g).join(" ") };
}

function AddBeneficiaryForm({ onCancel, onSubmit }) {
  const [name, setName] = useState("");
  const [country, setCountry] = useState("");
  const [currency, setCurrency] = useState("GBP");
  const [iban, setIban] = useState("");
  const [ibanTouched, setIbanTouched] = useState(false);
  const [submitting, setSubmitting] = useState(false);

  const ibanValidation = validateIban(iban);

  const submit = async (e) => {
    e.preventDefault();
    if (!name.trim()) return;
    if (iban.trim() && !ibanValidation.valid) return;
    setSubmitting(true);
    await onSubmit({
      name: name.trim(),
      country: country.trim().toUpperCase(),
      currency: currency.trim().toUpperCase(),
      iban: iban.trim().replace(/\s+/g, ""),
    });
    setSubmitting(false);
  };

  const ibanNorm = iban.replace(/[\s\-]/g, "").toUpperCase();
  const showIbanError  = ibanTouched && ibanNorm.length > 4 && !ibanValidation.valid;
  const showIbanOk     = ibanNorm.length > 4 && ibanValidation.valid;

  return (
    <form className="tc-rule-form" onSubmit={submit} style={{marginBottom: 16}}>
      <div className="tc-rule-form-h">
        <h3>Add beneficiary</h3>
        <button type="button" className="tc-btn tc-btn-ghost tc-btn-sm" onClick={onCancel}><XIcon /></button>
      </div>
      <div className="tc-rule-form-row row-2">
        <div className="tc-field">
          <span className="tc-field-l">Name</span>
          <input value={name} onChange={e => setName(e.target.value)} placeholder="e.g. EMEA Logistics GmbH" required />
        </div>
        <div className="tc-field">
          <span className="tc-field-l">Country (ISO-2/3)</span>
          <input value={country} onChange={e => setCountry(e.target.value)} placeholder="DE" />
        </div>
      </div>
      <div className="tc-rule-form-row row-2">
        <div className="tc-field">
          <span className="tc-field-l">Currency</span>
          <select className="tc-select" value={currency} onChange={e => setCurrency(e.target.value)}>
            <option>GBP</option><option>EUR</option><option>USD</option>
            <option>CAD</option><option>AUD</option><option>JPY</option><option>CHF</option>
          </select>
        </div>
        <div className="tc-field">
          <span className="tc-field-l">IBAN / account number</span>
          <div style={{position:"relative"}}>
            <input
              value={iban}
              onChange={e => setIban(e.target.value)}
              onBlur={() => setIbanTouched(true)}
              placeholder="DE89 3704 0044 0532 0130 00"
              style={{
                paddingRight: 28,
                borderColor: showIbanError ? "var(--red,#ef4444)" : showIbanOk ? "var(--green,#22c55e)" : undefined,
                outline: showIbanError ? "1px solid var(--red,#ef4444)" : showIbanOk ? "1px solid var(--green,#22c55e)" : undefined,
              }}
            />
            {showIbanOk && (
              <span style={{position:"absolute",right:8,top:"50%",transform:"translateY(-50%)",color:"var(--green,#22c55e)",fontSize:16,pointerEvents:"none"}}>✓</span>
            )}
          </div>
          {showIbanOk && (
            <div style={{marginTop:4,fontSize:12,color:"var(--green,#22c55e)",display:"flex",alignItems:"center",gap:4}}>
              <span>✓</span>
              <span>
                {ibanValidation.countryName ? `${ibanValidation.countryName} · ` : ""}
                {ibanValidation.formatted}
              </span>
            </div>
          )}
          {showIbanError && (
            <div style={{marginTop:4,fontSize:12,color:"var(--red,#ef4444)"}}>
              {ibanValidation.error}
            </div>
          )}
        </div>
      </div>
      <div className="tc-rule-form-actions">
        <button type="button" className="tc-btn tc-btn-ghost" onClick={onCancel}>Cancel</button>
        <button type="submit" className="tc-btn tc-btn-accent" disabled={submitting || !name.trim() || (ibanNorm.length > 4 && !ibanValidation.valid)}>
          {submitting ? <Spinner size={12} /> : <CheckIcon />} Add
        </button>
      </div>
    </form>
  );
}

// ────────────────────────────────────────────────────────────
// DOCUMENTS PAGE
// ────────────────────────────────────────────────────────────

const DOC_TYPES = [
  "Certificate of Incorporation",
  "Articles of Association",
  "Proof of Address",
  "UBO Declaration",
  "Director ID",
  "Audited Financials",
  "Bank Statement",
  "Source of Funds Declaration",
  "KYC Document",
  "Other",
];
const DOC_CATEGORIES = ["corporate","financial","identity","regulatory","operational","compliance","correspondence"];

function DocumentUploadForm({ onCancel, onUploaded }) {
  const [file, setFile]   = useState(null);
  const [docType, setType] = useState(DOC_TYPES[0]);
  const [category, setCat] = useState("corporate");
  const [progress, setP]   = useState(null);
  const [error, setError]  = useState("");

  const submit = async (e) => {
    e.preventDefault();
    if (!file) { setError("Select a file first."); return; }
    setP("uploading"); setError("");
    try {
      const result = await TC_API.uploadDocument(file, docType, category, null, "");
      setP("done");
      setTimeout(() => onUploaded(result), 1200);
    } catch (err) {
      setP("error");
      setError(err.message || String(err));
    }
  };

  return (
    <form className="tc-rule-form" onSubmit={submit}>
      <div className="tc-rule-form-h">
        <h3>Upload document</h3>
        <button type="button" className="tc-btn tc-btn-ghost tc-btn-sm" onClick={onCancel}><XIcon /></button>
      </div>
      <div className="tc-rule-form-row row-2">
        <div className="tc-field">
          <span className="tc-field-l">Document type</span>
          <select className="tc-select" value={docType} onChange={e => setType(e.target.value)}>
            {DOC_TYPES.map(t => <option key={t}>{t}</option>)}
          </select>
        </div>
        <div className="tc-field">
          <span className="tc-field-l">Category</span>
          <select className="tc-select" value={category} onChange={e => setCat(e.target.value)}>
            {DOC_CATEGORIES.map(c => <option key={c}>{c}</option>)}
          </select>
        </div>
      </div>
      <div className="tc-field">
        <span className="tc-field-l">File</span>
        <input
          type="file"
          onChange={e => { setFile(e.target.files[0] || null); setError(""); }}
          accept=".pdf,.png,.jpg,.jpeg,.gif,.webp,.doc,.docx,.xls,.xlsx,.txt,.csv"
        />
        {file && <span style={{fontSize:11.5,color:"var(--fg-3)",marginTop:4,display:"block"}}>{file.name} · {(file.size/1024).toFixed(1)} KB</span>}
      </div>
      {error && <p style={{margin:0,fontSize:12.5,color:"#963c2c"}}>{error}</p>}
      {progress === "uploading" && <p style={{margin:0,fontSize:12.5,color:"var(--fg-3)"}}>Uploading…</p>}
      {progress === "done" && <p style={{margin:0,fontSize:12.5,color:"var(--good)"}}>Document received and verified ✓</p>}
      <div className="tc-rule-form-actions">
        <button type="button" className="tc-btn tc-btn-ghost" onClick={onCancel}>Cancel</button>
        <button type="submit" className="tc-btn tc-btn-accent" disabled={progress === "uploading" || progress === "done"}>
          {progress === "uploading" ? <Spinner size={12} /> : <CheckIcon />} Upload
        </button>
      </div>
    </form>
  );
}

function DocumentsPage() {
  const docsQ = useFetch(() => TC_API.getDocuments(), []);
  const [showUpload, setShowUpload] = useState(false);
  const docs = useMemo(() => docsQ.data || [], [docsQ.data]);

  const fmtSize = (bytes) => {
    if (!bytes) return "—";
    if (bytes < 1024) return `${bytes} B`;
    if (bytes < 1048576) return `${(bytes/1024).toFixed(1)} KB`;
    return `${(bytes/1048576).toFixed(1)} MB`;
  };

  return (
    <div className="tc-page">
      <section>
        <div className="tc-block-h">
          <h2>Documents on file</h2>
          <span className="tc-block-h-meta">{docs.length} document{docs.length !== 1 ? "s" : ""}</span>
        </div>

        {!showUpload && (
          <button className="tc-btn tc-btn-ghost tc-rule-add-btn" style={{marginBottom:14}} onClick={() => setShowUpload(true)}>
            <PlusIcon /> Upload document
          </button>
        )}
        {showUpload && (
          <DocumentUploadForm
            onCancel={() => setShowUpload(false)}
            onUploaded={() => { setShowUpload(false); docsQ.refetch(); }}
          />
        )}

        {docsQ.loading && !docs.length
          ? <LoadingBlock label="Loading documents…" />
          : docsQ.error
          ? <ErrorBlock error={docsQ.error} onRetry={docsQ.refetch} label="Couldn't load documents" />
          : docs.length === 0
          ? <div className="tc-card tc-empty">No documents on file. Upload your first document above.</div>
          : (
            <div className="tc-card" style={{overflow:"auto"}}>
              <table className="tc-table">
                <thead>
                  <tr>
                    <th>Document</th>
                    <th style={{width:110}}>Category</th>
                    <th style={{width:100}}>Uploaded</th>
                    <th style={{width:130}}>By</th>
                    <th style={{width:80,textAlign:"right"}}>Size</th>
                    <th style={{width:90}}></th>
                  </tr>
                </thead>
                <tbody>
                  {docs.map(d => (
                    <tr key={d.doc_id} style={{opacity:d.superseded_by?0.45:1}}>
                      <td>
                        <div style={{display:"flex",flexDirection:"column",gap:2}}>
                          <span style={{fontWeight:450}}>{d.doc_type || "Document"}</span>
                          <span style={{fontSize:11,color:"var(--fg-4)",fontFamily:"var(--font-mono)"}}>{d.file_name}</span>
                        </div>
                      </td>
                      <td style={{fontSize:11.5,fontFamily:"var(--font-mono)",color:"var(--fg-3)",textTransform:"uppercase",letterSpacing:"0.04em"}}>{d.category}</td>
                      <td style={{fontFamily:"var(--font-mono)",fontSize:12}}>{fmtDate(d.uploaded_at)}</td>
                      <td style={{fontFamily:"var(--font-mono)",fontSize:12,color:"var(--fg-3)"}}>{d.uploaded_by || "—"}</td>
                      <td style={{textAlign:"right",fontFamily:"var(--font-mono)",fontSize:12,color:"var(--fg-3)"}}>{fmtSize(d.file_size)}</td>
                      <td style={{textAlign:"right"}}>
                        {d.has_file && (
                          <a
                            href={TC_API.downloadDocumentUrl(d.doc_id)}
                            className="tc-btn tc-btn-ghost tc-btn-sm"
                            target="_blank"
                            rel="noreferrer"
                            style={{fontSize:12}}
                          >
                            Download
                          </a>
                        )}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )
        }

        {docs.some(d => d.extracted_data && Object.keys(d.extracted_data).length > 0) && (
          <div style={{marginTop:24}}>
            <div className="tc-block-h" style={{marginBottom:12}}>
              <h2>Extracted data</h2>
              <span className="tc-block-h-meta">structured data from uploaded documents</span>
            </div>
            {docs.filter(d => d.extracted_data && Object.keys(d.extracted_data).length > 0).map(d => (
              <div key={d.doc_id} className="tc-card" style={{marginBottom:10}}>
                <div className="tc-card-pad">
                  <div style={{fontSize:12.5,fontWeight:500,marginBottom:8}}>
                    {d.doc_type}
                    <span style={{fontFamily:"var(--font-mono)",fontSize:11,color:"var(--fg-4)",marginLeft:8}}>{d.file_name}</span>
                  </div>
                  <div style={{display:"flex",flexWrap:"wrap",gap:"4px 20px"}}>
                    {Object.entries(d.extracted_data).slice(0,12).map(([k,v]) => (
                      <div key={k} style={{display:"flex",gap:6,fontSize:12,alignItems:"baseline"}}>
                        <span style={{color:"var(--fg-4)",fontFamily:"var(--font-mono)",fontSize:10.5,letterSpacing:"0.05em",textTransform:"uppercase"}}>{k.replace(/_/g," ")}</span>
                        <span style={{color:"var(--fg-2)"}}>{String(v).slice(0,80)}</span>
                      </div>
                    ))}
                  </div>
                </div>
              </div>
            ))}
          </div>
        )}
      </section>
    </div>
  );
}

window.TC_PAGES_A = { OverviewPage, TransactionsPage, BeneficiariesPage, DocumentsPage };
