/* ============================================================
   ELECTROMED — Deep Reports (filter-driven, server-side)
   Registered as the "Deep Reports" tab inside Reports (reports.jsx).
   All data via api.deepReport(path, filters); exports via ExportKit.
   ============================================================ */

/* ── Report catalogue: path + column spec (drives table + exports) ── */
const money = { type: 'currency', align: 'right' };
const numc  = { type: 'number', align: 'right' };

const DEEP_REPORTS = {
  Ledgers: [
    { id: 'ledger/general', name: 'General Ledger', needs: [], cols: [
      { key: 'date', label: 'Date', type: 'date' }, { key: 'entry_number', label: 'Entry' },
      { key: 'account_code', label: 'Acct' }, { key: 'account_name', label: 'Account' },
      { key: 'memo', label: 'Narration' },
      { key: 'debit', label: 'Debit', ...money }, { key: 'credit', label: 'Credit', ...money },
      { key: 'balance', label: 'Balance', ...money },
    ], totalsCols: { debit: 'debit', credit: 'credit' } },
    { id: 'ledger/trial-balance', name: 'Trial Balance', flat: true, cols: [
      { key: 'code', label: 'Code' }, { key: 'name', label: 'Account' }, { key: 'type', label: 'Type' },
      { key: 'debit', label: 'Total Debit', ...money }, { key: 'credit', label: 'Total Credit', ...money },
      { key: 'closing_debit', label: 'Closing Dr', ...money }, { key: 'closing_credit', label: 'Closing Cr', ...money },
    ], totalsCols: { debit: 'debit', credit: 'credit', closing_debit: 'closing_debit', closing_credit: 'closing_credit' } },
    { id: 'ledger/customer', name: 'Customer Ledger', requires: 'customer_id', cols: [
      { key: 'date', label: 'Date', type: 'date' }, { key: 'type', label: 'Type' }, { key: 'no', label: 'Ref' },
      { key: 'detail', label: 'Detail' }, { key: 'debit', label: 'Debit', ...money },
      { key: 'credit', label: 'Credit', ...money }, { key: 'balance', label: 'Balance', ...money },
    ], totalsCols: { debit: 'debit', credit: 'credit' } },
    { id: 'ledger/supplier', name: 'Supplier Ledger', requires: 'supplier_id', cols: [
      { key: 'date', label: 'Date', type: 'date' }, { key: 'type', label: 'Type' }, { key: 'no', label: 'Ref' },
      { key: 'credit', label: 'Bill', ...money }, { key: 'debit', label: 'Paid', ...money }, { key: 'balance', label: 'Balance', ...money },
    ], totalsCols: { credit: 'credit', debit: 'debit' } },
    { id: 'ledger/cash-bank', name: 'Cash / Bank Book', account: true, cols: [
      { key: 'date', label: 'Date', type: 'date' }, { key: 'entry_number', label: 'Entry' },
      { key: 'memo', label: 'Narration' }, { key: 'debit', label: 'In', ...money },
      { key: 'credit', label: 'Out', ...money }, { key: 'balance', label: 'Balance', ...money },
    ], totalsCols: { debit: 'debit', credit: 'credit' } },
    { id: 'ledger/daybook', name: 'Day Book', cols: [
      { key: 'date', label: 'Date', type: 'date' }, { key: 'entry_number', label: 'Entry' },
      { key: 'account_name', label: 'Account' }, { key: 'memo', label: 'Narration' },
      { key: 'debit', label: 'Debit', ...money }, { key: 'credit', label: 'Credit', ...money },
    ], totalsCols: { debit: 'debit', credit: 'credit' } },
    { id: 'ar-aging', name: 'AR Aging', asOf: true, cols: [
      { key: 'customer_name', label: 'Customer' }, { key: 'current', label: '0–30', ...money },
      { key: 'd31_60', label: '31–60', ...money }, { key: 'd61_90', label: '61–90', ...money },
      { key: 'd90_plus', label: '90+', ...money }, { key: 'total', label: 'Total', ...money },
    ], totalsCols: { current: 'current', d31_60: 'd31_60', d61_90: 'd61_90', d90_plus: 'd90_plus', total: 'total' } },
    { id: 'ap-aging', name: 'AP Aging', asOf: true, cols: [
      { key: 'supplier_name', label: 'Supplier' }, { key: 'current', label: '0–30', ...money },
      { key: 'd31_60', label: '31–60', ...money }, { key: 'd61_90', label: '61–90', ...money },
      { key: 'd90_plus', label: '90+', ...money }, { key: 'total', label: 'Total', ...money },
    ], totalsCols: { current: 'current', d31_60: 'd31_60', d61_90: 'd61_90', d90_plus: 'd90_plus', total: 'total' } },
  ],
  Sales: [
    { id: 'sales/register', name: 'Sales Register', status: 'invoice', cols: [
      { key: 'date', label: 'Date', type: 'date' }, { key: 'invoice_number', label: 'Invoice' },
      { key: 'customer_name', label: 'Customer' }, { key: 'device', label: 'Item' },
      { key: 'rep', label: 'Rep' }, { key: 'amount', label: 'Amount', ...money },
      { key: 'received', label: 'Received', ...money }, { key: 'balance', label: 'Balance', ...money },
      { key: 'status', label: 'Status' },
    ], totalsCols: { amount: 'amount', received: 'received', balance: 'balance' } },
    { id: 'sales/by-customer', name: 'Sales by Customer', cols: [
      { key: 'label', label: 'Customer' }, { key: 'invoices', label: 'Invoices', ...numc },
      { key: 'amount', label: 'Amount', ...money }, { key: 'received', label: 'Received', ...money }, { key: 'balance', label: 'Balance', ...money },
    ], totalsCols: { invoices: 'invoices', amount: 'amount', received: 'received', balance: 'balance' } },
    { id: 'sales/by-salesperson', name: 'Sales by Salesperson', cols: [
      { key: 'label', label: 'Salesperson' }, { key: 'invoices', label: 'Deals', ...numc },
      { key: 'amount', label: 'Amount', ...money }, { key: 'received', label: 'Received', ...money }, { key: 'balance', label: 'Balance', ...money },
    ], totalsCols: { invoices: 'invoices', amount: 'amount', received: 'received', balance: 'balance' } },
    { id: 'sales/by-product', name: 'Sales by Product', cols: [
      { key: 'label', label: 'Product' }, { key: 'qty', label: 'Qty', ...numc },
      { key: 'orders', label: 'Orders', ...numc }, { key: 'value', label: 'Value', ...money },
    ], totalsCols: { qty: 'qty', value: 'value' } },
    { id: 'sales/by-category', name: 'Sales by Category', cols: [
      { key: 'label', label: 'Category' }, { key: 'qty', label: 'Qty', ...numc },
      { key: 'orders', label: 'Orders', ...numc }, { key: 'value', label: 'Value', ...money },
    ], totalsCols: { qty: 'qty', value: 'value' } },
    { id: 'sales/returns', name: 'Sales Returns', cols: [
      { key: 'date', label: 'Date', type: 'date' }, { key: 'return_number', label: 'Return #' },
      { key: 'customer_name', label: 'Customer' }, { key: 'reason', label: 'Reason' },
      { key: 'amount', label: 'Amount', ...money },
    ], totalsCols: { amount: 'amount' } },
  ],
  Inventory: [
    { id: 'inventory/stock', name: 'Stock + Valuation', category: true, cols: [
      { key: 'sku', label: 'SKU' }, { key: 'name', label: 'Item' }, { key: 'category', label: 'Category' },
      { key: 'stock', label: 'Qty', ...numc }, { key: 'cost_price', label: 'Cost', ...money },
      { key: 'cost_value', label: 'Cost Value', ...money }, { key: 'retail_value', label: 'Retail Value', ...money },
    ], totalsCols: { cost_value: 'cost_value', retail_value: 'retail_value' } },
    { id: 'inventory/movement', name: 'Stock Movement', cols: [
      { key: 'date', label: 'Date', type: 'date' }, { key: 'move_number', label: 'Move #' },
      { key: 'item', label: 'Item' }, { key: 'type', label: 'Type' }, { key: 'qty', label: 'Qty', ...numc },
      { key: 'from_loc', label: 'From' }, { key: 'to_loc', label: 'To' }, { key: 'status', label: 'Status' },
    ] },
    { id: 'inventory/aging', name: 'Stock Aging', category: true, cols: [
      { key: 'sku', label: 'SKU' }, { key: 'name', label: 'Item' }, { key: 'stock', label: 'Qty', ...numc },
      { key: 'cost_value', label: 'Cost Value', ...money }, { key: 'last_movement', label: 'Last Move', type: 'date' },
      { key: 'idle_days', label: 'Idle Days', ...numc }, { key: 'bucket', label: 'Bucket' },
    ], totalsCols: { cost_value: 'cost_value' } },
    { id: 'purchases/register', name: 'Purchase Register', status: 'purchase', cols: [
      { key: 'date', label: 'Date', type: 'date' }, { key: 'purchase_number', label: 'Purchase #' },
      { key: 'supplier_name', label: 'Supplier' }, { key: 'amount', label: 'Amount', ...money },
      { key: 'paid', label: 'Paid', ...money }, { key: 'balance', label: 'Balance', ...money }, { key: 'status', label: 'Status' },
    ], totalsCols: { amount: 'amount', paid: 'paid', balance: 'balance' } },
  ],
  Customers: [
    { id: 'customers/master', name: 'Customer Master', cols: [
      { key: 'name', label: 'Name' }, { key: 'phone', label: 'Phone' }, { key: 'city', label: 'City' },
      { key: 'type', label: 'Type' }, { key: 'outstanding', label: 'Outstanding', ...money }, { key: 'status', label: 'Status' },
    ], totalsCols: { outstanding: 'outstanding' } },
    { id: 'customers/top', name: 'Top Customers', cols: [
      { key: 'customer_name', label: 'Customer' }, { key: 'invoices', label: 'Invoices', ...numc },
      { key: 'amount', label: 'Billed', ...money }, { key: 'received', label: 'Received', ...money }, { key: 'balance', label: 'Balance', ...money },
    ], totalsCols: { amount: 'amount' } },
    { id: 'customers/inactive', name: 'Inactive Customers', days: true, cols: [
      { key: 'name', label: 'Customer' }, { key: 'phone', label: 'Phone' }, { key: 'city', label: 'City' },
      { key: 'last_activity', label: 'Last Activity', type: 'date' }, { key: 'idle_days', label: 'Idle Days', ...numc },
      { key: 'outstanding', label: 'Outstanding', ...money },
    ], totalsCols: { outstanding: 'outstanding' } },
  ],
};

const PRESETS = [
  ['this_month', 'This Month'], ['today', 'Today'], ['this_week', 'This Week'],
  ['last_month', 'Last Month'], ['this_quarter', 'Quarter'], ['this_year', 'FY Year'],
  ['last_year', 'Last FY'], ['custom', 'Custom'], ['', 'All Time'],
];

function fmtCell(v, col, PKR) {
  if (v === null || v === undefined || v === '') return col.type === 'currency' || col.type === 'number' ? '—' : '';
  if (col.type === 'currency') return PKR(v);
  if (col.type === 'number')   return Number(v).toLocaleString('en-PK');
  return String(v);
}

/* ── Main component ─────────────────────────────────────────────── */
function DeepReports({ branch = 'All' }) {
  const { PKR } = window.DATA;
  const [group, setGroup]   = useState('Ledgers');
  const [repId, setRepId]   = useState('ledger/general');
  const report = useMemo(() => Object.values(DEEP_REPORTS).flat().find(r => r.id === repId), [repId]);

  const [preset, setPreset] = useState('this_month');
  const [from, setFrom]     = useState('');
  const [to, setTo]         = useState('');
  const [filters, setFilters] = useState({});   // customer_id, supplier_id, status[], min, max, q, account, category, days, as_of, sort_by, sort_dir
  const [page, setPage]     = useState(1);
  const [limit]             = useState(50);

  const [resp, setResp]     = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError]   = useState(null);
  const [meta, setMeta]     = useState({ reps: [], categories: [], accounts: [], suppliers: [], invoice_statuses: [], purchase_statuses: [] });
  const tableRef = useRef(null);

  const { data: customers } = useCustomers(branch !== 'All' ? { branch_id: branch } : {});

  // Load filter options once (branch-aware)
  useEffect(() => {
    api.getDeepMeta(branch !== 'All' ? { branch_id: branch } : {}).then(setMeta).catch(() => {});
  }, [branch]);

  // Reset page when the report or key filters change
  useEffect(() => { setPage(1); }, [repId, preset, from, to, JSON.stringify(filters)]);

  const buildQuery = (forExport) => {
    const q = { ...filters };
    if (preset === 'custom') { if (from) q.from = from; if (to) q.to = to; }
    else if (preset) q.preset = preset;
    if (branch !== 'All') q.branch_id = branch;
    if (Array.isArray(q.status)) q.status = q.status.join(',');
    if (forExport) q.limit = 'all'; else { q.page = page; q.limit = limit; }
    return q;
  };

  const missingReq = report.requires && !filters[report.requires];

  // Fetch on any change
  useEffect(() => {
    if (missingReq) { setResp(null); return; }
    let cancel = false;
    setLoading(true); setError(null);
    api.deepReport(report.id, buildQuery(false))
      .then(d => { if (!cancel) setResp(d); })
      .catch(e => { if (!cancel) setError(e.message || 'Failed to load'); })
      .finally(() => { if (!cancel) setLoading(false); });
    return () => { cancel = true; };
  }, [repId, page, preset, from, to, JSON.stringify(filters), branch]);

  const rows   = resp ? resp.rows : [];
  const totals = resp ? resp.totals : {};
  const pages  = resp ? resp.pages : 1;

  const patch = (k, v) => setFilters(f => ({ ...f, [k]: v }));
  const clearFilters = () => { setFilters({}); setPreset('this_month'); setFrom(''); setTo(''); };

  // ── Exports ──────────────────────────────────────────────────
  const activeFilterList = () => {
    const out = {};
    out.Report = report.name;
    out.Period = preset === 'custom' ? `${from || '…'} → ${to || '…'}` : (PRESETS.find(p => p[0] === preset) || [,'All Time'])[1];
    if (branch !== 'All') out.Branch = branch;
    Object.entries(filters).forEach(([k, v]) => { if (v !== '' && v != null && !(Array.isArray(v) && !v.length)) out[k] = Array.isArray(v) ? v.join(', ') : v; });
    return out;
  };

  const doExport = async (kind) => {
    try {
      let exportRows = rows;
      // Pull the full filtered set for file exports (respect filters, ignore paging)
      if (kind !== 'print' && pages > 1) {
        const full = await api.deepReport(report.id, buildQuery(true));
        exportRows = full.rows;
      }
      const totalsRow = report.totalsCols
        ? Object.fromEntries(Object.entries(report.totalsCols).map(([col, tk]) => [col, totals[tk]]))
        : null;
      const payload = {
        rows: exportRows, columns: report.cols, totals: totalsRow,
        reportName: report.name.replace(/[\/\s]+/g, '-'),
        from: exportPeriod().from, to: exportPeriod().to, filters: activeFilterList(),
      };
      if (kind === 'xlsx')  window.ExportKit.toXLSX(payload);
      else if (kind === 'csv') window.ExportKit.toCSV(payload);
      else window.ExportKit.printNode(tableRef.current, payload.reportName, payload.from, payload.to);
      window.toast && window.toast(`${report.name} exported`, 'ok');
    } catch (e) { window.toast && window.toast('Export failed: ' + e.message, 'error'); }
  };
  const exportPeriod = () => (preset === 'custom' ? { from, to } : { from: preset || 'All', to: '' });

  // ── Sort handler ─────────────────────────────────────────────
  const onSort = (col) => {
    if (col.type === 'currency' || col.type === 'number' || ['date','name','customer_name','supplier_name'].includes(col.key)) {
      const key = col.sortKey || col.key;
      setFilters(f => ({ ...f, sort_by: key, sort_dir: f.sort_by === key && f.sort_dir === 'desc' ? 'asc' : 'desc' }));
    }
  };

  const [showEntry, setShowEntry] = useState(null); // 'supplier' | 'purchase' | 'return'

  return (
    <div>
      {/* Report picker */}
      <div className="row no-print" style={{ gap: 8, marginBottom: 14, flexWrap: 'wrap' }}>
        {Object.keys(DEEP_REPORTS).map(g => (
          <button key={g} className={cls('tab', group === g && 'active')}
            onClick={() => { setGroup(g); const first = DEEP_REPORTS[g][0]; setRepId(first.id); }}>{g}</button>
        ))}
        <div className="grow" />
        <Btn variant="ghost" icon={<Icons.plus size={15} />} onClick={() => setShowEntry('menu')}>New Entry</Btn>
      </div>

      <div className="grid" style={{ gridTemplateColumns: '210px 1fr', gap: 16, alignItems: 'start' }}>
        {/* Report list */}
        <div className="card no-print" style={{ padding: 8, position: 'sticky', top: 0 }}>
          <div className="tiny muted" style={{ fontWeight: 700, padding: '8px 10px 6px' }}>{group.toUpperCase()}</div>
          {DEEP_REPORTS[group].map(r => (
            <button key={r.id} className="nav-item"
              style={{ fontWeight: repId === r.id ? 700 : 600, background: repId === r.id ? 'var(--surface-2)' : 'transparent', color: repId === r.id ? 'var(--ink)' : 'var(--ink-2)' }}
              onClick={() => setRepId(r.id)}>{r.name}</button>
          ))}
        </div>

        <div>
          {/* Filter bar */}
          <FilterBar report={report} preset={preset} setPreset={setPreset} from={from} to={to} setFrom={setFrom} setTo={setTo}
            filters={filters} patch={patch} clearFilters={clearFilters} meta={meta} customers={customers} PKR={PKR} />

          {/* Export bar */}
          <div className="row no-print" style={{ justifyContent: 'space-between', alignItems: 'center', margin: '12px 0' }}>
            <div className="tiny muted">{resp ? `${resp.count.toLocaleString()} record${resp.count === 1 ? '' : 's'}` : '—'}{loading ? ' · loading…' : ''}</div>
            <div className="row" style={{ gap: 8 }}>
              <Btn variant="ghost" icon={<Icons.download size={15} />} onClick={() => doExport('csv')} disabled={!rows.length}>CSV</Btn>
              <Btn variant="ghost" icon={<Icons.download size={15} />} onClick={() => doExport('xlsx')} disabled={!rows.length}>Excel</Btn>
              <Btn variant="ghost" icon={<Icons.print size={15} />} onClick={() => doExport('print')} disabled={!rows.length}>Print / PDF</Btn>
            </div>
          </div>

          {/* Results */}
          {missingReq ? (
            <div className="card card-pad tiny muted">Select a {report.requires === 'customer_id' ? 'customer' : 'supplier'} above to run this statement.</div>
          ) : error ? (
            <div className="card card-pad tiny" style={{ color: 'var(--bad)' }}>{error}</div>
          ) : (
            <ReportTable innerRef={tableRef} report={report} rows={rows} totals={totals} loading={loading}
              PKR={PKR} onSort={onSort} sortBy={filters.sort_by} sortDir={filters.sort_dir}
              meta={metaLine(report, preset, from, to, branch)} />
          )}

          {/* Pagination */}
          {pages > 1 && (
            <div className="row no-print" style={{ justifyContent: 'center', gap: 8, marginTop: 14 }}>
              <Btn variant="ghost" onClick={() => setPage(p => Math.max(1, p - 1))} disabled={page <= 1}>Prev</Btn>
              <span className="tiny muted" style={{ alignSelf: 'center' }}>Page {page} / {pages}</span>
              <Btn variant="ghost" onClick={() => setPage(p => Math.min(pages, p + 1))} disabled={page >= pages}>Next</Btn>
            </div>
          )}
        </div>
      </div>

      {showEntry === 'menu'     && <EntryMenu onPick={setShowEntry} onClose={() => setShowEntry(null)} />}
      {showEntry === 'supplier' && <SupplierModal branch={branch} onClose={() => setShowEntry(null)} onSaved={() => { setShowEntry(null); api.getDeepMeta({}).then(setMeta); }} />}
      {showEntry === 'purchase' && <PurchaseModal branch={branch} meta={meta} onClose={() => setShowEntry(null)} onSaved={() => { setShowEntry(null); setRepId('purchases/register'); setGroup('Inventory'); }} />}
      {showEntry === 'return'   && <ReturnModal branch={branch} customers={customers} onClose={() => setShowEntry(null)} onSaved={() => { setShowEntry(null); setGroup('Sales'); setRepId('sales/returns'); }} />}
    </div>
  );
}

function metaLine(report, preset, from, to, branch) {
  const period = preset === 'custom' ? `${from || '…'} → ${to || '…'}` : (PRESETS.find(p => p[0] === preset) || [, 'All Time'])[1];
  return `${period}${branch !== 'All' ? ' · branch-scoped' : ' · all branches'}`;
}

/* ── Filter bar ─────────────────────────────────────────────────── */
function FilterBar({ report, preset, setPreset, from, to, setFrom, setTo, filters, patch, clearFilters, meta, customers, PKR }) {
  const statusOpts = report.status === 'purchase' ? meta.purchase_statuses : report.status === 'invoice' ? meta.invoice_statuses : null;
  return (
    <div className="card card-pad no-print" style={{ display: 'grid', gap: 12 }}>
      {/* Date presets */}
      {!report.flat && (
        <div className="row" style={{ gap: 6, flexWrap: 'wrap' }}>
          {PRESETS.map(([v, l]) => (
            <button key={l} className={cls('chip', preset === v && 'chip-on')} onClick={() => setPreset(v)}>{l}</button>
          ))}
          {preset === 'custom' && (
            <span className="row" style={{ gap: 6 }}>
              <input className="input-block" type="date" value={from} onChange={e => setFrom(e.target.value)} style={{ width: 150 }} />
              <span className="tiny muted">→</span>
              <input className="input-block" type="date" value={to} onChange={e => setTo(e.target.value)} style={{ width: 150 }} />
            </span>
          )}
        </div>
      )}

      <div className="row" style={{ gap: 10, flexWrap: 'wrap', alignItems: 'flex-end' }}>
        {report.requires === 'customer_id' || report.id === 'sales/by-customer' ? (
          <Fld label="Customer" req={report.requires === 'customer_id'}>
            <select className="input-block" value={filters.customer_id || ''} onChange={e => patch('customer_id', e.target.value)} style={{ minWidth: 200 }}>
              <option value="">All customers</option>
              {customers.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
            </select>
          </Fld>
        ) : null}

        {report.requires === 'supplier_id' && (
          <Fld label="Supplier" req>
            <select className="input-block" value={filters.supplier_id || ''} onChange={e => patch('supplier_id', e.target.value)} style={{ minWidth: 200 }}>
              <option value="">Select supplier…</option>
              {meta.suppliers.map(s => <option key={s.id} value={s.id}>{s.name}</option>)}
            </select>
          </Fld>
        )}

        {report.account && (
          <Fld label="Account">
            <select className="input-block" value={filters.account || 'cash'} onChange={e => patch('account', e.target.value)}>
              <option value="cash">Cash in Hand</option>
              <option value="bank">Bank</option>
            </select>
          </Fld>
        )}

        {report.id === 'ledger/general' && (
          <Fld label="Account (optional)">
            <select className="input-block" value={filters.account || ''} onChange={e => patch('account', e.target.value)} style={{ minWidth: 180 }}>
              <option value="">All accounts</option>
              {meta.accounts.map(a => <option key={a.code} value={a.code}>{a.code} · {a.name}</option>)}
            </select>
          </Fld>
        )}

        {report.id === 'sales/by-salesperson' && (
          <Fld label="Salesperson">
            <select className="input-block" value={filters.rep || ''} onChange={e => patch('rep', e.target.value)}>
              <option value="">All reps</option>
              {meta.reps.map(r => <option key={r} value={r}>{r}</option>)}
            </select>
          </Fld>
        )}

        {report.category && (
          <Fld label="Category">
            <select className="input-block" value={filters.category || ''} onChange={e => patch('category', e.target.value)}>
              <option value="">All categories</option>
              {meta.categories.map(c => <option key={c} value={c}>{c}</option>)}
            </select>
          </Fld>
        )}

        {statusOpts && (
          <Fld label="Status">
            <select className="input-block" value={(filters.status && filters.status[0]) || ''} onChange={e => patch('status', e.target.value ? [e.target.value] : [])}>
              <option value="">Any status</option>
              {statusOpts.map(s => <option key={s} value={s}>{s}</option>)}
            </select>
          </Fld>
        )}

        {report.asOf && (
          <Fld label="As of">
            <input className="input-block" type="date" value={filters.as_of || ''} onChange={e => patch('as_of', e.target.value)} style={{ width: 150 }} />
          </Fld>
        )}

        {report.days && (
          <Fld label="Idle for (days)">
            <input className="input-block" type="number" value={filters.days || 90} onChange={e => patch('days', e.target.value)} style={{ width: 110 }} />
          </Fld>
        )}

        {/* Amount range — reports with a money total */}
        {report.totalsCols && (
          <Fld label="Amount range">
            <span className="row" style={{ gap: 6 }}>
              <input className="input-block" type="number" placeholder="min" value={filters.min ?? ''} onChange={e => patch('min', e.target.value)} style={{ width: 96 }} />
              <input className="input-block" type="number" placeholder="max" value={filters.max ?? ''} onChange={e => patch('max', e.target.value)} style={{ width: 96 }} />
            </span>
          </Fld>
        )}

        <Fld label="Search">
          <input className="input-block" placeholder="name, number…" value={filters.q || ''} onChange={e => patch('q', e.target.value)} style={{ minWidth: 160 }} />
        </Fld>

        <Btn variant="ghost" onClick={clearFilters}>Reset</Btn>
      </div>
    </div>
  );
}

function Fld({ label, req, children }) {
  return (
    <label className="fld" style={{ margin: 0 }}>
      <span>{label}{req && <b style={{ color: 'var(--bad)' }}> *</b>}</span>
      {children}
    </label>
  );
}

/* ── Results table (also the print/PDF surface) ─────────────────── */
function ReportTable({ innerRef, report, rows, totals, loading, PKR, onSort, sortBy, sortDir, meta }) {
  const { data: companies } = useCompanies();
  const co = (companies && companies[0]) || { name: 'Electromed Corporation', addr: '', ntn: '' };
  const cols = report.cols;
  const totalsRow = report.totalsCols;

  return (
    <div className="card" ref={innerRef} style={{ overflow: 'hidden' }}>
      {/* Print-only letterhead + applied filters */}
      <div className="print-only" style={{ padding: '14px 18px', borderBottom: '2px solid #111' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between' }}>
          <div><div style={{ fontWeight: 800 }}>{co.name}</div><div className="tiny muted">{co.addr} {co.ntn ? '· NTN ' + co.ntn : ''}</div></div>
          <div style={{ textAlign: 'right' }}><div style={{ fontWeight: 800 }}>{report.name}</div><div className="tiny muted">{meta}</div></div>
        </div>
      </div>

      <div style={{ overflowX: 'auto' }}>
        <table className="tbl" style={{ fontSize: 13 }}>
          <thead><tr>
            {cols.map(c => {
              const sortable = c.type === 'currency' || c.type === 'number' || ['date', 'name', 'customer_name', 'supplier_name'].includes(c.key);
              const active = sortBy === (c.sortKey || c.key);
              return (
                <th key={c.key} onClick={() => onSort(c)} style={{ textAlign: c.align || 'left', cursor: sortable ? 'pointer' : 'default', whiteSpace: 'nowrap' }}>
                  {c.label}{active ? (sortDir === 'asc' ? ' ▲' : ' ▼') : ''}
                </th>
              );
            })}
          </tr></thead>
          <tbody>
            {loading && !rows.length ? (
              <tr><td colSpan={cols.length} className="muted tiny" style={{ padding: 20, textAlign: 'center' }}>Loading…</td></tr>
            ) : !rows.length ? (
              <tr><td colSpan={cols.length} className="muted tiny" style={{ padding: 20, textAlign: 'center' }}>No records match these filters.</td></tr>
            ) : rows.map((r, ix) => (
              <tr key={ix}>
                {cols.map(c => (
                  <td key={c.key} className={c.type === 'currency' || c.type === 'number' ? 'mono' : ''} style={{ textAlign: c.align || 'left', whiteSpace: c.type === 'date' ? 'nowrap' : 'normal' }}>
                    {fmtCell(r[c.key], c, PKR)}
                  </td>
                ))}
              </tr>
            ))}
          </tbody>
          {totalsRow && rows.length > 0 && (
            <tfoot><tr style={{ borderTop: '2px solid var(--ink)', fontWeight: 800 }}>
              {cols.map((c, i) => {
                const tk = totalsRow[c.key];
                return (
                  <td key={c.key} className={c.type === 'currency' || c.type === 'number' ? 'mono' : ''} style={{ textAlign: c.align || 'left' }}>
                    {i === 0 ? 'TOTAL' : tk !== undefined ? fmtCell(totals[tk], c, PKR) : ''}
                  </td>
                );
              })}
            </tr></tfoot>
          )}
        </table>
      </div>
    </div>
  );
}

/* ── Entry modals: supplier / purchase / sales return ───────────── */
function EntryMenu({ onPick, onClose }) {
  return (
    <Modal title="New Entry" sub="Create a record that feeds the reports" onClose={onClose}>
      <div style={{ display: 'grid', gap: 10 }}>
        {[['supplier', 'Supplier', 'Add a vendor for purchases & payables'],
          ['purchase', 'Purchase (Stock In)', 'Record goods received — updates stock & AP'],
          ['return', 'Sales Return', 'Credit note against an invoice']].map(([k, t, d]) => (
          <button key={k} className="card card-pad" style={{ textAlign: 'left', cursor: 'pointer' }} onClick={() => onPick(k)}>
            <div style={{ fontWeight: 700 }}>{t}</div><div className="tiny muted">{d}</div>
          </button>
        ))}
      </div>
    </Modal>
  );
}

function SupplierModal({ branch, onClose, onSaved }) {
  const [f, setF] = useState({ name: '', phone: '', city: '', email: '', ntn: '', opening_balance: '' });
  const [busy, setBusy] = useState(false);
  const set = (k) => (e) => setF(s => ({ ...s, [k]: e.target.value }));
  const save = async () => {
    if (!f.name.trim()) return window.toast('Supplier name is required', 'warn');
    setBusy(true);
    try {
      await api.createSupplier({ ...f, opening_balance: Number(f.opening_balance) || 0, branch_id: branch !== 'All' ? branch : undefined });
      window.toast('Supplier added', 'ok'); onSaved();
    } catch (e) { window.toast(e.message, 'error'); } finally { setBusy(false); }
  };
  return (
    <Modal title="New Supplier" onClose={onClose}
      foot={<><Btn variant="ghost" onClick={onClose} disabled={busy}>Cancel</Btn><Btn variant="primary" onClick={save} disabled={busy}>{busy ? 'Saving…' : 'Save Supplier'}</Btn></>}>
      <div className="grid" style={{ gridTemplateColumns: '1fr 1fr', gap: 12 }}>
        <label className="fld" style={{ gridColumn: '1 / -1' }}><span>Name *</span><input className="input-block" value={f.name} onChange={set('name')} placeholder="e.g. Medisupply Pvt Ltd" /></label>
        <label className="fld"><span>Phone</span><input className="input-block" value={f.phone} onChange={set('phone')} /></label>
        <label className="fld"><span>City</span><input className="input-block" value={f.city} onChange={set('city')} /></label>
        <label className="fld"><span>Email</span><input className="input-block" value={f.email} onChange={set('email')} /></label>
        <label className="fld"><span>NTN</span><input className="input-block" value={f.ntn} onChange={set('ntn')} /></label>
        <label className="fld" style={{ gridColumn: '1 / -1' }}><span>Opening payable (Rs)</span><input className="input-block" type="number" value={f.opening_balance} onChange={set('opening_balance')} placeholder="0" /></label>
      </div>
    </Modal>
  );
}

function PurchaseModal({ branch, meta, onClose, onSaved }) {
  const [supplierId, setSupplierId] = useState('');
  const [gst, setGst] = useState(false);
  const [items, setItems] = useState([{ name: '', sku: '', qty: 1, rate: 0 }]);
  const [busy, setBusy] = useState(false);
  const setItem = (i, k) => (e) => setItems(a => a.map((it, ix) => ix === i ? { ...it, [k]: e.target.value } : it));
  const sub = items.reduce((s, it) => s + (Number(it.qty) || 0) * (Number(it.rate) || 0), 0);
  const tax = gst ? Math.round(sub * 0.17) : 0;
  const save = async () => {
    if (!supplierId) return window.toast('Select a supplier', 'warn');
    if (sub <= 0) return window.toast('Add at least one line item with a rate', 'warn');
    setBusy(true);
    try {
      await api.createPurchase({
        supplier_id: supplierId, gst: gst ? 1 : 0,
        amount: sub + tax, tax_amount: tax,
        items: items.filter(it => it.name || it.sku).map(it => ({ name: it.name, sku: it.sku, qty: Number(it.qty) || 0, rate: Number(it.rate) || 0 })),
        branch_id: branch !== 'All' ? branch : undefined,
      });
      window.toast('Purchase recorded — stock updated', 'ok'); onSaved();
    } catch (e) { window.toast(e.message, 'error'); } finally { setBusy(false); }
  };
  return (
    <Modal title="New Purchase (Stock In)" wide onClose={onClose}
      foot={<><Btn variant="ghost" onClick={onClose} disabled={busy}>Cancel</Btn><Btn variant="primary" onClick={save} disabled={busy}>{busy ? 'Saving…' : 'Record Purchase'}</Btn></>}>
      <label className="fld"><span>Supplier *</span>
        <select className="input-block" value={supplierId} onChange={e => setSupplierId(e.target.value)}>
          <option value="">Select supplier…</option>
          {meta.suppliers.map(s => <option key={s.id} value={s.id}>{s.name}</option>)}
        </select>
      </label>
      {!meta.suppliers.length && <div className="tiny" style={{ color: 'var(--warn)', marginBottom: 8 }}>No suppliers yet — add one first via New Entry → Supplier.</div>}
      <div className="tiny muted" style={{ margin: '10px 0 6px', fontWeight: 700 }}>LINE ITEMS (matched to inventory by SKU or name)</div>
      {items.map((it, i) => (
        <div key={i} className="row" style={{ gap: 6, marginBottom: 6 }}>
          <input className="input-block" placeholder="Item name" value={it.name} onChange={setItem(i, 'name')} style={{ flex: 2 }} />
          <input className="input-block" placeholder="SKU" value={it.sku} onChange={setItem(i, 'sku')} style={{ flex: 1 }} />
          <input className="input-block" type="number" placeholder="Qty" value={it.qty} onChange={setItem(i, 'qty')} style={{ width: 70 }} />
          <input className="input-block" type="number" placeholder="Rate" value={it.rate} onChange={setItem(i, 'rate')} style={{ width: 100 }} />
          {items.length > 1 && <button className="btn-icon" onClick={() => setItems(a => a.filter((_, ix) => ix !== i))}><Icons.x size={16} /></button>}
        </div>
      ))}
      <Btn variant="ghost" icon={<Icons.plus size={14} />} onClick={() => setItems(a => [...a, { name: '', sku: '', qty: 1, rate: 0 }])}>Add line</Btn>
      <div className="row" style={{ justifyContent: 'space-between', marginTop: 14, alignItems: 'center' }}>
        <label className="row" style={{ gap: 8, cursor: 'pointer' }}><input type="checkbox" checked={gst} onChange={e => setGst(e.target.checked)} /> <span className="tiny">GST 17%</span></label>
        <div className="mono" style={{ fontWeight: 800 }}>Total: Rs {(sub + tax).toLocaleString('en-PK')}</div>
      </div>
    </Modal>
  );
}

function ReturnModal({ branch, customers, onClose, onSaved }) {
  const [invoiceId, setInvoiceId] = useState('');
  const [custId, setCustId] = useState('');
  const [amount, setAmount] = useState('');
  const [reason, setReason] = useState('');
  const [restock, setRestock] = useState(false);
  const [busy, setBusy] = useState(false);
  const { data: invoices } = useInvoices(branch !== 'All' ? { branch_id: branch } : {});
  const save = async () => {
    if (!Number(amount)) return window.toast('Enter a return amount', 'warn');
    if (!invoiceId && !custId) return window.toast('Pick an invoice or customer', 'warn');
    setBusy(true);
    try {
      await api.createSalesReturn({ invoice_id: invoiceId || undefined, customer_id: custId || undefined, amount: Number(amount), reason, restock, branch_id: branch !== 'All' ? branch : undefined });
      window.toast('Sales return recorded', 'ok'); onSaved();
    } catch (e) { window.toast(e.message, 'error'); } finally { setBusy(false); }
  };
  return (
    <Modal title="New Sales Return" onClose={onClose}
      foot={<><Btn variant="ghost" onClick={onClose} disabled={busy}>Cancel</Btn><Btn variant="primary" onClick={save} disabled={busy}>{busy ? 'Saving…' : 'Record Return'}</Btn></>}>
      <label className="fld"><span>Against Invoice (optional)</span>
        <select className="input-block" value={invoiceId} onChange={e => { setInvoiceId(e.target.value); const iv = invoices.find(x => x.id === e.target.value); if (iv) setCustId(iv.customer_id || ''); }}>
          <option value="">— none —</option>
          {invoices.slice(0, 200).map(iv => <option key={iv.id} value={iv.id}>{iv.invoice_number} · {iv.customer_name} · Rs {Number(iv.amount).toLocaleString('en-PK')}</option>)}
        </select>
      </label>
      <label className="fld"><span>Customer</span>
        <select className="input-block" value={custId} onChange={e => setCustId(e.target.value)} disabled={!!invoiceId}>
          <option value="">Select customer…</option>
          {customers.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
        </select>
      </label>
      <div className="grid" style={{ gridTemplateColumns: '1fr 1fr', gap: 12 }}>
        <label className="fld"><span>Return amount (Rs) *</span><input className="input-block" type="number" value={amount} onChange={e => setAmount(e.target.value)} /></label>
        <label className="fld"><span>Reason</span><input className="input-block" value={reason} onChange={e => setReason(e.target.value)} placeholder="e.g. Defective unit" /></label>
      </div>
      <label className="row" style={{ gap: 8, cursor: 'pointer', marginTop: 6 }}><input type="checkbox" checked={restock} onChange={e => setRestock(e.target.checked)} /> <span className="tiny">Return items to stock</span></label>
    </Modal>
  );
}

window.DeepReports = DeepReports;
