/* Dépenses & Impôts — Québec (TPS 5% + TVQ 9.975%)
 * - Saisie dépense récurrente (mensuelle/annuelle) ou unique
 * - Photo de facture stockée en base64 dans D1 (receipts table)
 * - Répartition par associé (Clarens / Kevin / Carly)
 * - Calcul automatique TPS/TVQ remboursables (CTI/RTI)
 * - Catégories de déduction fiscale (T2125 / TP-80)
 * - Totaux mensuels, annuels, projection
 */

const TPS_RATE = 0.05;
const TVQ_RATE = 0.09975;

// Catégories T2125 (Canada) / TP-80 (Québec) — dépenses d'entreprise déductibles
const TAX_CATEGORIES = [
  { id: "outils-logiciels", label: "Outils & logiciels (SaaS)",     line: "T2125 8760 / TP-80 240" },
  { id: "telecom",          label: "Télécommunications",            line: "T2125 9220 / TP-80 220" },
  { id: "bureau",           label: "Fournitures de bureau",         line: "T2125 8810 / TP-80 230" },
  { id: "marketing",        label: "Publicité & marketing (PPC)",   line: "T2125 8521 / TP-80 200" },
  { id: "frais-bancaires",  label: "Frais bancaires & intérêts",    line: "T2125 8710 / TP-80 218" },
  { id: "consultants",      label: "Honoraires (comptable/légal)",  line: "T2125 8860 / TP-80 222" },
  { id: "shipping",         label: "Expédition & livraison",        line: "T2125 9275" },
  { id: "fba-fees",         label: "Frais Amazon FBA",              line: "T2125 9275" },
  { id: "echantillons",     label: "Échantillons & inventaire",     line: "T2125 8320 (CMV)" },
  { id: "deplacement",      label: "Déplacements & repas",          line: "T2125 8810 / TP-80 232" },
  { id: "formation",        label: "Formation & abonnements pro",   line: "T2125 8760" },
  { id: "autre",            label: "Autre",                         line: "—" },
];

const RECURRENCE = [
  { id: "monthly",  label: "Mensuel",      mult: 12 },
  { id: "yearly",   label: "Annuel",       mult: 1 },
  { id: "quarterly",label: "Trimestriel",  mult: 4 },
  { id: "once",     label: "Une seule fois", mult: 0 },
];

// Pré-remplissage avec les vraies dépenses KCC (du message Clarens)
const SEED_EXPENSES = [
  { id: "exp-keepa",     vendor: "Keepa",            cat: "outils-logiciels", recurrence: "monthly", amount_pretax: 47.81, currency: "CAD", taxable: false,  splits: { clarens: 33.34, kevin: 33.33, carly: 33.33 }, note: "Convertit de 29€/mois", paidBy: "" },
  { id: "exp-azinsight", vendor: "Az Insight (Asinzen)", cat: "outils-logiciels", recurrence: "yearly", amount_pretax: 164.07, currency: "CAD", taxable: false, splits: { clarens: 33.34, kevin: 33.33, carly: 33.33 }, note: "Abonnement annuel", paidBy: "" },
  { id: "exp-claude",    vendor: "Claude AI (Anthropic)", cat: "outils-logiciels", recurrence: "monthly", amount_pretax: 32.19, currency: "CAD", taxable: true,  splits: { clarens: 100, kevin: 0, carly: 0 }, note: "Payé par Clarens", paidBy: "clarens" },
  { id: "exp-gemini",    vendor: "Google Gemini",     cat: "outils-logiciels", recurrence: "monthly", amount_pretax: 25.00, currency: "CAD", taxable: true,  splits: { clarens: 33.34, kevin: 33.33, carly: 33.33 }, note: "4.59$ les 3 premiers mois puis 25$", paidBy: "" },
  { id: "exp-teams",     vendor: "Microsoft Teams",   cat: "telecom",          recurrence: "yearly",  amount_pretax: 145.00, currency: "CAD", taxable: true,  splits: { clarens: 33.34, kevin: 33.33, carly: 33.33 }, note: "166.71$ TTC", paidBy: "" },
];

function calcTax(pretax, taxable) {
  if (!taxable) return { tps: 0, tvq: 0, total: pretax };
  const tps = +(pretax * TPS_RATE).toFixed(2);
  const tvq = +(pretax * TVQ_RATE).toFixed(2);
  return { tps, tvq, total: +(pretax + tps + tvq).toFixed(2) };
}

function annualize(amount, recurrence) {
  const r = RECURRENCE.find((x) => x.id === recurrence);
  if (!r) return 0;
  if (r.id === "monthly")   return amount * 12;
  if (r.id === "yearly")    return amount;
  if (r.id === "quarterly") return amount * 4;
  return amount; // once
}

const Expenses = () => {
  const { useState, useEffect } = React;
  const [expenses, setExpenses] = useState([]);
  const [receipts, setReceipts] = useState({}); // { receiptId: dataUrl }
  const [editing, setEditing] = useState(null);
  const [photoModal, setPhotoModal] = useState(null);
  const [filter, setFilter] = useState({ cat: "all", recurrence: "all", paidBy: "all" });
  const [loaded, setLoaded] = useState(false);

  // Load from D1
  useEffect(() => {
    (async () => {
      try {
        const r = await fetch("/api/sync?col=expenses", { cache: "no-store" });
        const j = await r.json();
        if (Array.isArray(j.items) && j.items.length) {
          setExpenses(j.items);
        } else {
          // First run: seed with KCC real expenses
          setExpenses(SEED_EXPENSES.map((e) => ({ ...e, created_at: Date.now() })));
          fetch("/api/sync", {
            method: "PUT",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ col: "expenses", items: SEED_EXPENSES.map((e) => ({ ...e, created_at: Date.now() })) }),
          }).catch(() => {});
        }
      } catch (_) {
        setExpenses(SEED_EXPENSES);
      }
      // Load receipts (just metadata; photos fetched on-demand)
      try {
        const r = await fetch("/api/sync?col=receipts", { cache: "no-store" });
        const j = await r.json();
        if (Array.isArray(j.items)) {
          const map = {};
          j.items.forEach((rec) => { if (rec.id) map[rec.id] = rec.photo || ""; });
          setReceipts(map);
        }
      } catch (_) {}
      setLoaded(true);
    })();
  }, []);

  const persist = async (next) => {
    setExpenses(next);
    window.KCC_EXPENSES = next; // expose to JARVIS for queries
    try {
      await fetch("/api/sync", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ col: "expenses", items: next }),
      });
    } catch (_) {}
  };

  // Sync KCC_EXPENSES whenever loaded
  useEffect(() => {
    window.KCC_EXPENSES = expenses;
  }, [expenses]);

  const upsertExpense = (exp) => {
    const next = exp.id && expenses.find((e) => e.id === exp.id)
      ? expenses.map((e) => (e.id === exp.id ? exp : e))
      : [...expenses, { ...exp, id: exp.id || `exp-${Date.now()}`, created_at: Date.now() }];
    persist(next);
    setEditing(null);
  };

  const deleteExpense = async (id) => {
    const exp = expenses.find((e) => e.id === id);
    if (!exp) return;
    if (!confirm(`Mettre la dépense "${exp.vendor}" à la corbeille ?`)) return;
    const trashHook = window.KCCTrash;
    if (trashHook?.send) {
      try { await trashHook.send("expenses", exp); } catch (_) {}
    }
    persist(expenses.filter((e) => e.id !== id));
    fetch(`/api/sync?col=expenses&id=${encodeURIComponent(id)}`, { method: "DELETE" }).catch(() => {});
    const toast = window.useToast ? null : null; // toast is not in scope here
    if (window.__kccToast) window.__kccToast({ message: `"${exp.vendor}" → corbeille`, tone: "muted" });
  };

  const attachPhoto = async (expenseId, file) => {
    if (!file) return;
    if (file.size > 5 * 1024 * 1024) {
      alert("Photo trop lourde (max 5 MB). Compresse-la d'abord.");
      return;
    }
    const reader = new FileReader();
    reader.onload = async () => {
      const dataUrl = reader.result;
      const receiptId = `rcp-${expenseId}-${Date.now()}`;
      const rec = { id: receiptId, expenseId, photo: dataUrl, filename: file.name, size: file.size, type: file.type };
      setReceipts((m) => ({ ...m, [receiptId]: dataUrl }));

      // Attach receiptId to the expense
      const exp = expenses.find((e) => e.id === expenseId);
      let workingExp = exp ? { ...exp, receiptIds: [...(exp.receiptIds || []), receiptId] } : null;
      if (workingExp) {
        persist(expenses.map((e) => (e.id === expenseId ? workingExp : e)));
      }

      // Persist the receipt
      await fetch("/api/sync", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ col: "receipts", items: [rec] }),
      }).catch(() => {});

      // OCR Gemini — auto-fill champs manquants si image (skip PDF)
      if (workingExp && file.type && file.type.startsWith("image/")) {
        try {
          const ocrRes = await fetch("/api/receipt-ocr", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ imageBase64: dataUrl, mimeType: file.type }),
          });
          if (ocrRes.ok) {
            const ocr = await ocrRes.json();
            const patch = {};
            if (ocr.vendor && !workingExp.vendor) patch.vendor = ocr.vendor;
            if (ocr.amount && !(+workingExp.amount_pretax)) {
              // Si TPS/TVQ détectées, déduire le HT; sinon utiliser le total tel quel
              const tps = +ocr.tax_tps || 0;
              const tvq = +ocr.tax_tvq || 0;
              const pretax = ocr.subtotal ? +ocr.subtotal : (tps || tvq) ? (+ocr.amount - tps - tvq) : +ocr.amount;
              patch.amount_pretax = Math.round(pretax * 100) / 100;
              if (tps || tvq) patch.taxable = true;
            }
            if (ocr.date && !workingExp.date) patch.date = ocr.date;
            if (ocr.category && !workingExp.cat) patch.cat = ocr.category;
            if (ocr.notes && !workingExp.notes) patch.notes = ocr.notes;
            if (ocr.payment_method && !workingExp.paidBy) patch.paidBy = ocr.payment_method;

            if (Object.keys(patch).length) {
              const merged = { ...workingExp, ...patch };
              persist(expenses.map((e) => (e.id === expenseId ? merged : e)));
            }
          }
        } catch (_) {
          // OCR optionnel — ignore l'erreur silencieusement
        }
      }
    };
    reader.readAsDataURL(file);
  };

  // Filtered list
  const visible = expenses.filter((e) => {
    if (filter.cat !== "all" && e.cat !== filter.cat) return false;
    if (filter.recurrence !== "all" && e.recurrence !== filter.recurrence) return false;
    if (filter.paidBy !== "all" && e.paidBy !== filter.paidBy) return false;
    return true;
  });

  // Totals
  const annualSubtotal = visible.reduce((a, e) => a + annualize(+e.amount_pretax || 0, e.recurrence), 0);
  const annualTPS = visible.reduce((a, e) => a + (e.taxable ? annualize(+e.amount_pretax || 0, e.recurrence) * TPS_RATE : 0), 0);
  const annualTVQ = visible.reduce((a, e) => a + (e.taxable ? annualize(+e.amount_pretax || 0, e.recurrence) * TVQ_RATE : 0), 0);
  const annualTTC = annualSubtotal + annualTPS + annualTVQ;
  const monthlyTTC = annualTTC / 12;

  // Per-person totals
  const perPerson = { clarens: 0, kevin: 0, carly: 0 };
  visible.forEach((e) => {
    const ttc = annualize(+e.amount_pretax || 0, e.recurrence) * (1 + (e.taxable ? TPS_RATE + TVQ_RATE : 0));
    Object.entries(e.splits || {}).forEach(([k, pct]) => {
      if (perPerson[k] != null) perPerson[k] += ttc * (pct / 100);
    });
  });

  // Per-category totals (annualisé TTC)
  const byCat = {};
  visible.forEach((e) => {
    const ttc = annualize(+e.amount_pretax || 0, e.recurrence) * (1 + (e.taxable ? TPS_RATE + TVQ_RATE : 0));
    byCat[e.cat] = (byCat[e.cat] || 0) + ttc;
  });
  const catRows = Object.entries(byCat).map(([id, total]) => ({
    id, total, label: TAX_CATEGORIES.find((c) => c.id === id)?.label || id,
    line: TAX_CATEGORIES.find((c) => c.id === id)?.line || "—",
  })).sort((a, b) => b.total - a.total);

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <div className="page-title">Dépenses & Impôts</div>
          <div className="page-sub">Québec · TPS 5% + TVQ 9.975% · KCC Holdings (T2125 / TP-80) · {expenses.length} dépense{expenses.length > 1 ? "s" : ""}</div>
        </div>
        <div className="row">
          <button className="btn" data-variant="ghost" onClick={() => exportCSV(visible)}>
            <Icon name="download" size={13} /> Export comptable (CSV)
          </button>
          <button className="btn" data-variant="primary" onClick={() => setEditing({ recurrence: "monthly", currency: "CAD", taxable: true, splits: { clarens: 33.34, kevin: 33.33, carly: 33.33 } })}>
            <Icon name="plus" size={13} /> Nouvelle dépense
          </button>
        </div>
      </div>

      {/* KPI cards */}
      <div className="grid" style={{ gridTemplateColumns: "repeat(4, 1fr)", gap: 12 }}>
        <KpiCard label="Coûts mensuels (TTC)" prefix="$" value={fmtMoney(Math.round(monthlyTTC))} />
        <KpiCard label="Coûts annualisés (TTC)" prefix="$" value={fmtMoney(Math.round(annualTTC))} />
        <KpiCard label="TPS remboursable (CTI)" prefix="$" value={fmtMoney(Math.round(annualTPS))} muted />
        <KpiCard label="TVQ remboursable (RTI)" prefix="$" value={fmtMoney(Math.round(annualTVQ))} muted />
      </div>

      {/* Filters */}
      <div className="card" style={{ marginTop: 14, padding: 14 }}>
        <div className="row" style={{ gap: 12, flexWrap: "wrap" }}>
          <select className="select" value={filter.cat} onChange={(e) => setFilter({ ...filter, cat: e.target.value })}>
            <option value="all">Toutes catégories</option>
            {TAX_CATEGORIES.map((c) => <option key={c.id} value={c.id}>{c.label}</option>)}
          </select>
          <select className="select" value={filter.recurrence} onChange={(e) => setFilter({ ...filter, recurrence: e.target.value })}>
            <option value="all">Toutes récurrences</option>
            {RECURRENCE.map((r) => <option key={r.id} value={r.id}>{r.label}</option>)}
          </select>
          <select className="select" value={filter.paidBy} onChange={(e) => setFilter({ ...filter, paidBy: e.target.value })}>
            <option value="all">Tous payeurs</option>
            <option value="">Partagé (3 associés)</option>
            <option value="clarens">Clarens uniquement</option>
            <option value="kevin">Kevin uniquement</option>
            <option value="carly">Carly uniquement</option>
          </select>
          <div style={{ marginLeft: "auto", fontSize: 11, color: "var(--text-faint)" }}>
            {visible.length} sur {expenses.length} dépenses · annualisé TTC: <strong style={{ color: "var(--text)" }}>${fmtMoney(Math.round(annualTTC))}</strong>
          </div>
        </div>
      </div>

      {/* Expenses table */}
      <div className="card" style={{ marginTop: 14, padding: 0, overflow: "hidden" }}>
        <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 12.5 }}>
          <thead>
            <tr style={{ background: "var(--bg-1)", textAlign: "left", borderBottom: "1px solid var(--border-subtle)" }}>
              <th style={th}>Fournisseur</th>
              <th style={th}>Catégorie</th>
              <th style={th}>Récurrence</th>
              <th style={{ ...th, textAlign: "right" }}>Montant HT</th>
              <th style={{ ...th, textAlign: "right" }}>TPS</th>
              <th style={{ ...th, textAlign: "right" }}>TVQ</th>
              <th style={{ ...th, textAlign: "right" }}>TTC / période</th>
              <th style={{ ...th, textAlign: "right" }}>Annualisé</th>
              <th style={th}>Payé par</th>
              <th style={th}>Facture</th>
              <th style={th}></th>
            </tr>
          </thead>
          <tbody>
            {visible.map((e) => {
              const tax = calcTax(+e.amount_pretax || 0, e.taxable);
              const ann = annualize(tax.total, e.recurrence);
              const cat = TAX_CATEGORIES.find((c) => c.id === e.cat);
              const rec = RECURRENCE.find((r) => r.id === e.recurrence);
              const hasReceipt = (e.receiptIds || []).length > 0;
              return (
                <tr key={e.id} style={{ borderBottom: "1px solid var(--border-subtle)" }}>
                  <td style={td}>
                    <div style={{ fontWeight: 550 }}>{e.vendor}</div>
                    {e.note && <div style={{ fontSize: 10.5, color: "var(--text-faint)" }}>{e.note}</div>}
                  </td>
                  <td style={td}>
                    <div>{cat?.label || e.cat}</div>
                    <div className="mono" style={{ fontSize: 10, color: "var(--text-faint)" }}>{cat?.line || ""}</div>
                  </td>
                  <td style={td}>{rec?.label || e.recurrence}</td>
                  <td style={{ ...td, textAlign: "right" }} className="mono">${(+e.amount_pretax || 0).toFixed(2)}</td>
                  <td style={{ ...td, textAlign: "right", color: e.taxable ? "var(--text)" : "var(--text-faint)" }} className="mono">${tax.tps.toFixed(2)}</td>
                  <td style={{ ...td, textAlign: "right", color: e.taxable ? "var(--text)" : "var(--text-faint)" }} className="mono">${tax.tvq.toFixed(2)}</td>
                  <td style={{ ...td, textAlign: "right", fontWeight: 600 }} className="mono">${tax.total.toFixed(2)}</td>
                  <td style={{ ...td, textAlign: "right" }} className="mono">${fmtMoney(Math.round(ann))}</td>
                  <td style={td}>
                    {e.paidBy ? (
                      <span className="badge">{e.paidBy === "clarens" ? "Clarens" : e.paidBy === "kevin" ? "Kevin" : "Carly"}</span>
                    ) : (
                      <span style={{ fontSize: 11, color: "var(--text-faint)" }}>3 associés</span>
                    )}
                  </td>
                  <td style={td}>
                    {hasReceipt ? (
                      <button className="btn" data-variant="ghost" data-size="sm" onClick={() => setPhotoModal(e.receiptIds[0])}>
                        <Icon name="image" size={11} /> Voir
                      </button>
                    ) : (
                      <label className="btn" data-variant="ghost" data-size="sm" style={{ cursor: "pointer" }}>
                        <Icon name="upload" size={11} /> Photo
                        <input type="file" accept="image/*,application/pdf" style={{ display: "none" }} onChange={(ev) => attachPhoto(e.id, ev.target.files[0])} />
                      </label>
                    )}
                  </td>
                  <td style={td}>
                    <button className="btn" data-variant="ghost" data-size="sm" onClick={() => setEditing(e)}><Icon name="edit" size={11} /></button>
                    <button className="btn" data-variant="ghost" data-size="sm" onClick={() => deleteExpense(e.id)}><Icon name="trash" size={11} /></button>
                  </td>
                </tr>
              );
            })}
            {visible.length === 0 && (
              <tr><td colSpan="11" style={{ ...td, textAlign: "center", color: "var(--text-faint)", padding: 30 }}>
                {loaded ? "Aucune dépense. Clique + Nouvelle dépense." : "Chargement…"}
              </td></tr>
            )}
          </tbody>
        </table>
      </div>

      {/* Per-person + per-category breakdown */}
      <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 14, marginTop: 14 }}>
        <div className="card" style={{ padding: 16 }}>
          <div style={{ fontSize: 12.5, fontWeight: 600, marginBottom: 12 }}>Coût annuel par associé (TTC)</div>
          {["clarens", "kevin", "carly"].map((u) => (
            <div key={u} style={{ display: "flex", justifyContent: "space-between", padding: "8px 0", borderTop: "1px solid var(--border-subtle)" }}>
              <span style={{ textTransform: "capitalize" }}>{u}</span>
              <span className="mono" style={{ fontWeight: 600 }}>${fmtMoney(Math.round(perPerson[u]))}/an</span>
            </div>
          ))}
        </div>
        <div className="card" style={{ padding: 16 }}>
          <div style={{ fontSize: 12.5, fontWeight: 600, marginBottom: 12 }}>Total par ligne T2125 / TP-80</div>
          {catRows.map((c) => (
            <div key={c.id} style={{ display: "flex", justifyContent: "space-between", padding: "8px 0", borderTop: "1px solid var(--border-subtle)" }}>
              <div>
                <div>{c.label}</div>
                <div className="mono" style={{ fontSize: 10, color: "var(--text-faint)" }}>{c.line}</div>
              </div>
              <span className="mono" style={{ fontWeight: 600 }}>${fmtMoney(Math.round(c.total))}</span>
            </div>
          ))}
          {catRows.length === 0 && <div style={{ color: "var(--text-faint)", fontSize: 11.5 }}>Aucune dépense.</div>}
        </div>
      </div>

      {/* Edit modal */}
      {editing && <ExpenseModal expense={editing} onSave={upsertExpense} onClose={() => setEditing(null)} />}

      {/* Photo viewer */}
      {photoModal && (
        <ReceiptModal receiptId={photoModal} photo={receipts[photoModal]} onClose={() => setPhotoModal(null)} />
      )}
    </div>
  );
};

// ── Cell styles ──
const th = { padding: "10px 14px", fontSize: 11, fontWeight: 600, color: "var(--text-faint)", textTransform: "uppercase", letterSpacing: ".06em" };
const td = { padding: "10px 14px", verticalAlign: "top" };

// ── Edit modal ──
const ExpenseModal = ({ expense, onSave, onClose }) => {
  const { useState } = React;
  const [form, setForm] = useState({ ...expense });
  const tax = calcTax(+form.amount_pretax || 0, form.taxable);

  const setSplit = (who, val) => {
    setForm({ ...form, splits: { ...form.splits, [who]: +val || 0 } });
  };

  const splitTotal = (form.splits?.clarens || 0) + (form.splits?.kevin || 0) + (form.splits?.carly || 0);

  return (
    <div style={modalBg} onClick={onClose}>
      <div className="card" style={modalCard} onClick={(e) => e.stopPropagation()}>
        <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 14 }}>
          {expense.id ? "Modifier" : "Nouvelle"} dépense
        </div>

        <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 10 }}>
          <Field label="Fournisseur">
            <input className="input" value={form.vendor || ""} onChange={(e) => setForm({ ...form, vendor: e.target.value })} placeholder="Keepa, Microsoft Teams…" />
          </Field>
          <Field label="Catégorie fiscale">
            <select className="select" value={form.cat || ""} onChange={(e) => setForm({ ...form, cat: e.target.value })}>
              <option value="">— choisir —</option>
              {TAX_CATEGORIES.map((c) => <option key={c.id} value={c.id}>{c.label}</option>)}
            </select>
          </Field>
          <Field label="Récurrence">
            <select className="select" value={form.recurrence} onChange={(e) => setForm({ ...form, recurrence: e.target.value })}>
              {RECURRENCE.map((r) => <option key={r.id} value={r.id}>{r.label}</option>)}
            </select>
          </Field>
          <Field label="Montant HT (par période)">
            <input className="input" type="number" step="0.01" value={form.amount_pretax || ""} onChange={(e) => setForm({ ...form, amount_pretax: e.target.value })} />
          </Field>
          <Field label="Taxes applicables (TPS+TVQ)">
            <label style={{ display: "flex", alignItems: "center", gap: 8 }}>
              <input type="checkbox" checked={!!form.taxable} onChange={(e) => setForm({ ...form, taxable: e.target.checked })} />
              <span style={{ fontSize: 11.5 }}>Vendeur québécois inscrit · taxes facturées</span>
            </label>
          </Field>
          <Field label="Payé par">
            <select className="select" value={form.paidBy || ""} onChange={(e) => setForm({ ...form, paidBy: e.target.value })}>
              <option value="">Partagé (3 associés)</option>
              <option value="clarens">Clarens</option>
              <option value="kevin">Kevin</option>
              <option value="carly">Carly</option>
            </select>
          </Field>
        </div>

        <div style={{ marginTop: 14 }}>
          <Field label={`Répartition % (total: ${splitTotal.toFixed(2)}%)`}>
            <div className="row" style={{ gap: 8 }}>
              {["clarens", "kevin", "carly"].map((u) => (
                <label key={u} style={{ flex: 1, fontSize: 11 }}>
                  <div style={{ textTransform: "capitalize", marginBottom: 4 }}>{u}</div>
                  <input className="input" type="number" step="0.01" value={form.splits?.[u] || 0} onChange={(e) => setSplit(u, e.target.value)} />
                </label>
              ))}
            </div>
            {Math.abs(splitTotal - 100) > 0.5 && <div style={{ fontSize: 11, color: "var(--amber)", marginTop: 4 }}>⚠ Le total doit faire 100%</div>}
          </Field>
        </div>

        <Field label="Note">
          <input className="input" value={form.note || ""} onChange={(e) => setForm({ ...form, note: e.target.value })} placeholder="Optionnel (n° facture, justification…)" />
        </Field>

        <div style={{ marginTop: 14, padding: 12, background: "var(--bg-1)", borderRadius: 8, fontSize: 12 }}>
          <div style={{ display: "flex", justifyContent: "space-between" }}><span>Montant HT</span><span className="mono">${(+form.amount_pretax || 0).toFixed(2)}</span></div>
          <div style={{ display: "flex", justifyContent: "space-between" }}><span>+ TPS 5%</span><span className="mono">${tax.tps.toFixed(2)}</span></div>
          <div style={{ display: "flex", justifyContent: "space-between" }}><span>+ TVQ 9.975%</span><span className="mono">${tax.tvq.toFixed(2)}</span></div>
          <div style={{ display: "flex", justifyContent: "space-between", fontWeight: 600, marginTop: 6, paddingTop: 6, borderTop: "1px solid var(--border-subtle)" }}><span>Total TTC / période</span><span className="mono">${tax.total.toFixed(2)}</span></div>
          <div style={{ display: "flex", justifyContent: "space-between", fontSize: 11, color: "var(--text-faint)", marginTop: 4 }}><span>Annualisé</span><span className="mono">${fmtMoney(Math.round(annualize(tax.total, form.recurrence)))}</span></div>
        </div>

        <div className="row" style={{ marginTop: 16, justifyContent: "flex-end", gap: 8 }}>
          <button className="btn" data-variant="ghost" onClick={onClose}>Annuler</button>
          <button className="btn" data-variant="primary" onClick={() => onSave(form)} disabled={!form.vendor || !form.cat}>
            <Icon name="check" size={12} /> Enregistrer
          </button>
        </div>
      </div>
    </div>
  );
};

const ReceiptModal = ({ receiptId, photo, onClose }) => {
  const { useState, useEffect } = React;
  const [src, setSrc] = useState(photo);
  useEffect(() => {
    if (!src) {
      // Lazy fetch full receipt photo from D1
      fetch(`/api/sync?col=receipts`).then((r) => r.json()).then((j) => {
        const rec = (j.items || []).find((r) => r.id === receiptId);
        if (rec?.photo) setSrc(rec.photo);
      }).catch(() => {});
    }
  }, [receiptId]);
  return (
    <div style={modalBg} onClick={onClose}>
      <div className="card" style={{ ...modalCard, maxWidth: 700 }} onClick={(e) => e.stopPropagation()}>
        <div style={{ fontSize: 12, color: "var(--text-faint)", marginBottom: 10 }}>Facture {receiptId}</div>
        {src ? (
          src.startsWith("data:application/pdf") || src.includes("pdf")
            ? <embed src={src} type="application/pdf" width="100%" height="500" />
            : <img src={src} alt="receipt" style={{ width: "100%", maxHeight: 500, objectFit: "contain", background: "var(--bg-2)" }} />
        ) : <div style={{ color: "var(--text-faint)", padding: 30, textAlign: "center" }}>Chargement…</div>}
        <div className="row" style={{ marginTop: 12, justifyContent: "flex-end" }}>
          <button className="btn" onClick={onClose}>Fermer</button>
        </div>
      </div>
    </div>
  );
};

const Field = ({ label, children }) => (
  <label style={{ display: "flex", flexDirection: "column", gap: 4, marginTop: 8 }}>
    <span style={{ fontSize: 11, color: "var(--text-faint)", fontWeight: 500 }}>{label}</span>
    {children}
  </label>
);

const modalBg = {
  position: "fixed", inset: 0, background: "rgba(0,0,0,.6)", display: "flex",
  alignItems: "center", justifyContent: "center", zIndex: 1000, padding: 20,
};
const modalCard = {
  width: "100%", maxWidth: 560, maxHeight: "90vh", overflowY: "auto", padding: 22,
};

// CSV export
function exportCSV(expenses) {
  const headers = ["vendor", "cat", "recurrence", "amount_pretax", "tps", "tvq", "total_ttc", "annualized_ttc", "paidBy", "note"];
  const rows = expenses.map((e) => {
    const tax = calcTax(+e.amount_pretax || 0, e.taxable);
    const ann = annualize(tax.total, e.recurrence);
    return [e.vendor, e.cat, e.recurrence, e.amount_pretax, tax.tps, tax.tvq, tax.total, ann.toFixed(2), e.paidBy || "shared", (e.note || "").replace(/[",\n]/g, " ")];
  });
  const csv = [headers.join(","), ...rows.map((r) => r.map((c) => `"${c}"`).join(","))].join("\n");
  const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = `kcc-depenses-${new Date().toISOString().slice(0, 10)}.csv`;
  a.click();
  URL.revokeObjectURL(url);
}

window.Expenses = Expenses;
