/* ============================================================
   IMTRACK — Reports module
   ============================================================ */
(function () {
  const E = window.IMTRACK_ENGINE;
  const { useState, useMemo } = React;

  function reportYears(store) {
    const years = new Set([E.CY]);
    (store.wpbItems || []).forEach((w) => w.year && years.add(w.year));
    (store.poLines || []).forEach((p) => p.year && years.add(p.year));
    (store.acRecords || []).forEach((a) => a.year && years.add(a.year));
    return [...years].filter(Boolean).sort((a, b) => a - b);
  }

  function acConsumesBudget(store, ac) {
    const st = E.lk(store, 'acStatus', ac.status);
    return st ? !!st.consumes_budget : ac.status === 's05';
  }

  function ReportsModule() {
    const ctx = window.useStore();
    const { store } = ctx;
    const toast = window.useToast();
    const [rep, setRep] = useState('bsline');
    const [year, setYear] = useState(E.CY);
    const years = useMemo(() => reportYears(store), [store]);

    const exportBs = () => {
      const tree = E.waterfallTree(store, year);
      const out = [];
      tree.forEach((s) => {
        out.push([s.schedule.code + ' — ' + s.schedule.name, '', '', E.fmtUSD0(s.totals.approved), E.fmtUSD0(s.totals.totalAfop), E.fmtUSD0(s.totals.poCommitted), E.fmtUSD0(s.totals.acConsumed), E.fmtUSD0(s.totals.approved - s.totals.acConsumed), E.fmtPct(s.totals.pct)]);
        s.lines.forEach((l) => l.rows.forEach((r) => {
          out.push([s.schedule.code, 'Line ' + l.line.line, r.item.name, r.item.approved, r.totalAfop, r.poCommitted, r.acConsumed, r.item.approved - r.acConsumed, r.pct.toFixed(1)]);
        }));
      });
      window.exportCsv('report_bs_line_utilization_' + year + '.csv', ['BS Schedule', 'BS Line', 'WP&B Item', 'Approved', 'AFOP Allocated', 'PO Committed', 'AC Consumed', 'Remaining', '% Used'], out);
      toast('BS Line Utilization exported', 'good');
    };

    const exportContracts = () => {
      const out = [];
      const groups = {};
      store.contracts.forEach((c) => (groups[c.status] = groups[c.status] || []).push(c));
      Object.keys(groups).sort().forEach((st) => {
        groups[st].forEach((c) => out.push([E.lkLabel(store, 'contractStatus', st), (c.operationalFlags || []).map((f) => E.lkLabel(store, 'operationalFlags', f)).join('; '), c.no, c.vendor, c.title, c.cur, c.current, c.start, c.end, E.contractRuleFlag(store, c, 'suppresses_expiry_action') ? '' : E.daysUntil(c.end)]));
      });
      window.exportCsv('report_contract_status_' + E.fmtDate(E.TODAY).replace(/-/g, '') + '.csv', ['Lifecycle Status', 'Operational Flags', 'Contract No', 'Vendor', 'Title', 'Currency', 'Current Value', 'Start Date', 'End Date', 'Days to Expiry'], out);
      toast('Contract Status report exported', 'good');
    };

    const exportAc = () => {
      const out = [];
      const groups = {};
      store.acRecords.filter((a) => !a.deletedAt).forEach((a) => (groups[a.cashCallPeriod] = groups[a.cashCallPeriod] || []).push(a));
      Object.keys(groups).sort().forEach((cp) => {
        const g = groups[cp];
        const subtotalSub = g.reduce((s, a) => s + a.valueSubmitted, 0);
        const subtotalErp = g.reduce((s, a) => s + (a.erpAmount || 0), 0);
        const subtotalConsumed = g.reduce((s, a) => s + (acConsumesBudget(store, a) ? (a.erpAmount || 0) : 0), 0);
        g.forEach((a) => {
          const docCount = (store.documentReferences || []).filter((r) => r.entityType === 'ac_record' && r.entityId === a.id).length;
          out.push([E.cashLabel(cp), a.contractNo, a.vendor, a.acNumber, E.lkLabel(store, 'acStatus', a.status), (a.acStatusHistory || []).length, docCount, a.cur, a.valueSubmitted, a.erpAmount || '', acConsumesBudget(store, a) ? (a.erpAmount || 0) : 0]);
        });
        out.push([E.cashLabel(cp) + ' SUBTOTAL', '', '', '', '', '', '', '', subtotalSub, subtotalErp, subtotalConsumed]);
      });
      window.exportCsv('report_ac_status_' + E.fmtDate(E.TODAY).replace(/-/g, '') + '.csv', ['Cash Call Period', 'Contract No', 'Vendor', 'AC Number', 'Status', 'Status Changes', 'Document Links', 'Currency', 'AC Submitted', 'ERP Amount', 'Budget Consumed'], out);
      toast('AC Status report exported', 'good');
    };

    return (
      <div className="page page-wide">
        <PageHeader title="Reports" subtitle="Operational reporting · reads from live module data">
          {rep === 'bsline' && <button className="btn btn-secondary" onClick={exportBs}><Icon name="download" size={16} />Export CSV</button>}
          {rep === 'contract' && <button className="btn btn-secondary" onClick={exportContracts}><Icon name="download" size={16} />Export CSV</button>}
          {rep === 'ac' && <button className="btn btn-secondary" onClick={exportAc}><Icon name="download" size={16} />Export CSV</button>}
        </PageHeader>
        <div className="filterbar" style={{ position: 'sticky', top: 0, zIndex: 10, background: 'var(--bg-page)', paddingBottom: 8 }}>
          <div className="subtabs">
            <button className={'subtab' + (rep === 'bsline' ? ' active' : '')} onClick={() => setRep('bsline')}>BS Line Utilization</button>
            <button className={'subtab' + (rep === 'contract' ? ' active' : '')} onClick={() => setRep('contract')}>Contract Status</button>
            <button className={'subtab' + (rep === 'ac' ? ' active' : '')} onClick={() => setRep('ac')}>AC Status</button>
          </div>
          <div className="spacer" />
          {rep === 'bsline' && <select className="select" value={String(year)} onChange={(e) => setYear(Number(e.target.value))}>{years.map((y) => <option key={y} value={String(y)}>FY{y}</option>)}</select>}
        </div>
        {rep === 'bsline' && <BsLineReport store={store} year={year} />}
        {rep === 'contract' && <ContractStatusReport store={store} />}
        {rep === 'ac' && <AcStatusReport store={store} />}
      </div>
    );
  }

  function BsLineReport({ store, year }) {
    const tree = useMemo(() => E.waterfallTree(store, year), [store, year]);
    return (
      <div className="card" style={{ overflow: 'hidden' }}>
        <div className="tbl-wrap"><table className="tbl">
          <thead style="position: sticky; top: 0; z-index: 1; background: var(--bg-default)"><tr>
            <th>BS Schedule / Line / Item</th>
            <th className="num-col">Approved</th><th className="num-col">AFOP Alloc</th>
            <th className="num-col">PO Committed</th><th className="num-col">AC Consumed</th>
            <th className="num-col">Remaining</th><th className="num-col">% Used</th>
            <th style={{ textAlign: 'center', width: 56 }}>Status</th>
          </tr></thead>
          <tbody>{tree.map((s) => (
            <React.Fragment key={s.schedule.code}>
              <tr className="wf-schedule">
                <td className="mono">{s.schedule.code} · {s.schedule.name}</td>
                <td className="num-col">{E.fmtUSD0(s.totals.approved)}</td>
                <td className="num-col">{E.fmtUSD0(s.totals.totalAfop)}</td>
                <td className="num-col">{E.fmtUSD0(s.totals.poCommitted)}</td>
                <td className="num-col">{E.fmtUSD0(s.totals.acConsumed)}</td>
                <td className="num-col">{E.fmtUSD0(s.totals.approved - s.totals.acConsumed)}</td>
                <td className="num-col tnum">{E.fmtPct(s.totals.pct)}</td>
                <td></td>
              </tr>
              {s.lines.map((l) => l.rows.map((r) => (
                <tr key={r.item.id} className="wf-item">
                  <td style={{ paddingLeft: 28 }}><span className="muted mono" style={{ fontSize: 11 }}>L{l.line.line}</span> {r.item.name}</td>
                  <td className="num-col"><Money v={r.item.approved} /></td>
                  <td className="num-col"><Money v={r.totalAfop} /></td>
                  <td className="num-col"><Money v={r.poCommitted} /></td>
                  <td className="num-col"><Money v={r.acConsumed} dash /></td>
                  <td className="num-col"><Money v={r.item.approved - r.acConsumed} /></td>
                  <td className="num-col tnum">{E.fmtPct(r.pct)}</td>
                  <td style={{ textAlign: 'center' }}><TrafficLight light={r.light} label={false} /></td>
                </tr>
              )))}
            </React.Fragment>
          ))}</tbody>
        </table></div>
      </div>
    );
  }

  function ContractStatusReport({ store }) {
    const groups = useMemo(() => {
      const g = {};
      store.contracts.forEach((c) => (g[c.status] = g[c.status] || []).push(c));
      return Object.keys(g).map((k) => {
        const currencies = [...new Set(g[k].map((c) => c.cur))];
        return { status: k, rows: g[k], currencies, total: g[k].reduce((s, c) => s + (c.cur === 'USD' ? c.current : 0), 0) };
      });
    }, [store]);
    return (
      <div className="card" style={{ overflow: 'hidden' }}><div className="tbl-wrap"><table className="tbl tbl-compact">
        <thead style="position: sticky; top: 0; z-index: 1; background: var(--bg-default)"><tr><th>Contract No</th><th>Vendor</th><th>Title</th><th>Operational Flags</th><th>Cur</th><th className="num-col">Current Value</th><th>Start</th><th>End</th><th className="num-col">Days to Expiry</th></tr></thead>
        <tbody>{groups.map((g) => (
          <React.Fragment key={g.status}>
            <tr style={{ background: 'var(--color-slate-100)' }}>
              <td colSpan={4} style={{ fontWeight: 600 }}>
                <StatusBadge store={store} list="contractStatus" id={g.status} dot />
                <span className="muted" style={{ marginLeft: 6, fontWeight: 400 }}>{g.rows.length} contracts</span>
              </td>
              <td></td>
              <td className="num-col" style={{ fontWeight: 600 }}>{g.currencies.length === 1 && g.currencies[0] === 'USD' ? 'USD ' + E.fmtUSD0(g.total) : 'Mixed currencies'}</td>
              <td colSpan={3}></td>
            </tr>
            {g.rows.map((c) => {
              const suppressExpiry = E.contractRuleFlag(store, c, 'suppresses_expiry_action');
              return (
              <tr key={c.id}>
                <td className="mono">{c.no}</td><td>{c.vendor}</td>
                <td style={{ maxWidth: 220, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{c.title}</td>
                <td>{(c.operationalFlags || []).length > 0 ? <div className="row" style={{ gap: 4, flexWrap: 'wrap' }}>{(c.operationalFlags || []).map((f) => <StatusBadge key={f} store={store} list="operationalFlags" id={f} />)}</div> : <span className="dash">—</span>}</td>
                <td>{c.cur}</td>
                <td className="num-col"><Money v={c.current} cur={c.cur} /></td>
                <td className="num">{c.start}</td><td className="num">{c.end}</td>
                <td className="num-col">{suppressExpiry ? <span className="dash">—</span> : window._ctrDays ? <window._ctrDays end={c.end} status={c.status} /> : E.daysUntil(c.end)}</td>
              </tr>
            );})}
          </React.Fragment>
        ))}</tbody>
      </table></div></div>
    );
  }

  function AcStatusReport({ store }) {
    const groups = useMemo(() => {
      const g = {};
      store.acRecords.filter((a) => !a.deletedAt).forEach((a) => (g[a.cashCallPeriod] = g[a.cashCallPeriod] || []).push(a));
      return Object.keys(g).sort().map((cp) => ({
        cp,
        rows: g[cp],
        sub: g[cp].reduce((s, a) => s + a.valueSubmitted, 0),
        erp: g[cp].reduce((s, a) => s + (a.erpAmount || 0), 0),
        consumed: g[cp].reduce((s, a) => s + (acConsumesBudget(store, a) ? (a.erpAmount || 0) : 0), 0),
        byStatus: g[cp].reduce((acc, a) => { acc[a.status] = (acc[a.status] || 0) + 1; return acc; }, {}),
      }));
    }, [store]);
    return (
      <div className="card" style={{ overflow: 'hidden' }}><div className="tbl-wrap"><table className="tbl tbl-compact">
        <thead style="position: sticky; top: 0; z-index: 1; background: var(--bg-default)"><tr>
          <th>Cash Call Period</th><th>Contract</th><th>Vendor</th><th>AC No</th>
          <th>Status</th><th>Status History</th><th>Doc Links</th><th>Cur</th>
          <th className="num-col">AC Submitted</th><th className="num-col">ERP Amount</th><th className="num-col">Gap</th><th className="num-col">Budget Consumed</th>
        </tr></thead>
        <tbody>{groups.map((g) => {
          const groupGapTotal = g.erp - g.sub;
          return (
          <React.Fragment key={g.cp}>
            <tr style={{ background: 'var(--color-navy-800)' }}>
              <td style={{ color: '#fff', fontWeight: 600 }}>{E.cashLabel(g.cp)}</td>
              <td colSpan={4} style={{ color: '#94a3b8' }}>
                {g.rows.length} records ·{' '}
                {Object.entries(g.byStatus).slice(0, 3).map(([st, n]) => `${n} x ${E.lkLabel(store, 'acStatus', st)}`).join(', ')}
              </td>
              <td colSpan={3}></td>
              <td className="num-col" style={{ color: '#fff' }}><span className="num">{E.fmtUSD2(g.sub)}</span></td>
              <td className="num-col" style={{ color: '#fff' }}><span className="num">{E.fmtUSD2(g.erp)}</span></td>
              <td className="num-col" style={{ color: '#fff' }}><span className="num">{E.fmtUSD2(groupGapTotal)}</span></td>
              <td className="num-col" style={{ color: '#fff' }}><span className="num">{E.fmtUSD2(g.consumed)}</span></td>
            </tr>
            {g.rows.map((a) => {
              const docCount = (store.documentReferences || []).filter((r) => r.entityType === 'ac_record' && r.entityId === a.id).length;
              const historyCount = (a.acStatusHistory || []).length;
              const gap = (a.erpAmount || 0) - (a.valueSubmitted || 0);
              const hasErp = !!a.erpAmount;
              return (
              <tr key={a.id}>
                <td></td>
                <td className="mono">{a.contractNo}</td>
                <td style={{ fontSize: 12 }}>{a.vendor}</td>
                <td className="mono">{a.acNumber}</td>
                <td><StatusBadge store={store} list="acStatus" id={a.status} /></td>
                <td style={{ fontSize: 11 }}>{historyCount ? historyCount + ' change' + (historyCount > 1 ? 's' : '') : <span className="dash">—</span>}</td>
                <td style={{ fontSize: 11 }}>{docCount ? docCount + ' link' + (docCount > 1 ? 's' : '') : <span className="dash">—</span>}</td>
                <td>{a.cur}</td>
                <td className="num-col"><Money v={a.valueSubmitted} dec={2} /></td>
                <td className="num-col"><Money v={a.erpAmount} dec={2} dash /></td>
                <td className="num-col">
                  {hasErp
                    ? <span className={gap >= 0 ? 'gap-positive' : 'gap-negative'}>{gap >= 0 ? '+' : ''}{E.fmtMoney(gap, a.cur, 2)}</span>
                    : <span className="dash">—</span>}
                </td>
                <td className="num-col"><Money v={acConsumesBudget(store, a) ? (a.erpAmount || 0) : 0} dec={2} dash /></td>
              </tr>
            );})}
          </React.Fragment>
        );})}</tbody>
      </table></div></div>
    );
  }

  window.ReportsModule = ReportsModule;
})();
