/* ============================================================
   IMTRACK — Contract detail tabs
   DocumentsTab, AfopTab, ContractAcTab, AmendmentsTab, NewAmendmentButton
   ============================================================ */
(function () {
  const E = window.IMTRACK_ENGINE;
  const { useState, useEffect, useMemo } = React;
  const KV = ({ k, v, mono }) => <div className="kv"><span className="k">{k}</span><span className={'v' + (mono ? ' mono' : '')}>{v}</span></div>;
  const actorName = (ctx) => (ctx.currentUser && ctx.currentUser.name) || 'CBCC';
  const validDocUrl = (url) => /^https?:\/\//i.test(String(url || '').trim());

  function DocumentReferenceModal({ ctx, title, subtitle, entityType, entityId, contractNo, category, defaultDescription, fixedCategory, onClose }) {
    const { store } = ctx;
    const toast = window.useToast();
    const [f, setF] = useState({
      category: category || 'dc_agreement',
      description: defaultDescription || '',
      date: E.fmtDate(E.TODAY),
      url: '',
      notes: '',
    });
    const save = () => {
      if (!f.description || !f.url) { toast('Description and URL are required', 'warn'); return; }
      if (!validDocUrl(f.url)) { toast('Enter a valid SharePoint or DMS URL', 'warn'); return; }
      ctx.actions.addDocumentReference({
        id: 'dr' + Date.now(),
        entityType,
        entityId,
        contractNo,
        category: fixedCategory || f.category,
        description: f.description,
        date: f.date,
        uploadedBy: actorName(ctx),
        uploadedAt: new Date().toISOString(),
        url: f.url,
        notes: f.notes,
      });
      toast('Document reference added', 'good');
      onClose();
    };
    return (
      <Modal title={title} subtitle={subtitle} onClose={onClose}
        footer={<><button className="btn btn-secondary" onClick={onClose}>Cancel</button><button className="btn btn-primary" onClick={save}>Add reference</button></>}>
        <div className="form-grid">
          {!fixedCategory && (
            <Field label="Category" req>
              <Select value={f.category} onChange={(v) => setF({ ...f, category: v })} options={store.lookups.documentCategory.map((d) => ({ value: d.id, label: d.label }))} />
            </Field>
          )}
          {fixedCategory && <Field label="Category"><div className="field-readonly">{E.lkLabel(store, 'documentCategory', fixedCategory)}</div></Field>}
          <Field label="Date"><input type="date" className="input mono" value={f.date} onChange={(e) => setF({ ...f, date: e.target.value })} /></Field>
          <Field label="Description" req span><input className="input" value={f.description} onChange={(e) => setF({ ...f, description: e.target.value })} placeholder="Document title or reference" /></Field>
          <Field label="SharePoint / DMS URL" req span><input className="input mono" value={f.url} onChange={(e) => setF({ ...f, url: e.target.value })} placeholder="https://sharepoint.example.com/..." /></Field>
          <Field label="Linked By"><div className="field-readonly">{actorName(ctx)}</div></Field>
          <Field label="Notes"><input className="input" value={f.notes} onChange={(e) => setF({ ...f, notes: e.target.value })} placeholder="Optional notes" /></Field>
        </div>
      </Modal>
    );
  }

  /* ===================== DOCUMENTS ===================== */
  function DocumentsTab({ c, ctx }) {
    const { store, can, actions } = ctx;
    const toast = window.useToast();
    const [addOpen, setAddOpen] = useState(false);
    const [showRemoved, setShowRemoved] = useState(false);

    let docs = (store.documentReferences || []).filter((r) =>
      (r.entityType === 'contract' && r.entityId === c.id) ||
      (r.entityType === 'procurement_plan' && c.procPlan && r.entityId === c.procPlan)
    );
    const removed = docs.filter((d) => d.deletedAt);
    if (!showRemoved) docs = docs.filter((d) => !d.deletedAt);

    return (
      <div>
        <div className="card" style={{ overflow: 'hidden' }}>
          <div className="table-toolbar">
            <span className="card-title">Contract Documents</span>
            <span className="muted" style={{ fontSize: 'var(--text-xs)' }}>Links to SharePoint / DMS</span>
            {removed.length > 0 && (
              <label className="row muted" style={{ gap: 6, fontSize: 12, marginLeft: 12 }}>
                <input type="checkbox" checked={showRemoved} onChange={(e) => setShowRemoved(e.target.checked)} />
                Show removed ({removed.length})
              </label>
            )}
            <div className="spacer" />
            {can('contracts', 'edit') && <button className="btn btn-primary btn-sm" onClick={() => setAddOpen(true)}><Icon name="plus" size={14} />Add Document</button>}
          </div>
          {docs.length === 0 ? (
            <EmptyState icon="file-search" title="No documents linked" sub="Add SharePoint links for agreements, exhibits, amendments, and AC documentation."
              action={can('contracts', 'edit') ? <button className="btn btn-secondary btn-sm" onClick={() => setAddOpen(true)}><Icon name="plus" size={14} />Add Document</button> : null} />
          ) : (
            <div className="tbl-wrap">
              <table className="tbl tbl-compact">
                <thead><tr>
                  <th>Category</th><th>Description</th><th>Date</th><th>Linked By</th><th>Notes</th><th></th>
                </tr></thead>
                <tbody>
                  {docs.map((d) => {
                    const isRemoved = !!d.deletedAt;
                    return (
                    <tr key={d.id} style={{ opacity: isRemoved ? 0.55 : 1 }}>
                      <td><div className="row" style={{ gap: 6, alignItems: 'center' }}><StatusBadge store={store} list="documentCategory" id={d.category} />{d.entityType === 'procurement_plan' && <span className="badge" style={{ fontSize: 9, padding: '0 5px', height: 16, background: '#dcfce7', color: '#15803d', fontWeight: 600 }}>PP</span>}</div></td>
                      <td style={{ fontWeight: 500, textDecoration: isRemoved ? 'line-through' : 'none' }}>{d.description}</td>
                      <td className="num" style={{ fontSize: 12 }}>{d.date}</td>
                      <td className="muted" style={{ fontSize: 12 }}>{d.uploadedBy || '—'}</td>
                      <td className="muted" style={{ fontSize: 12 }}>{d.notes || '—'}</td>
                      <td>
                        <div className="cell-actions">
                          {isRemoved ? (
                            can('contracts', 'edit') && <button className="icon-btn" title="Restore" onClick={() => { actions.restoreDocumentReference(d.id); toast('Document restored', 'good'); }}><Icon name="rotate-ccw" size={14} /></button>
                          ) : (<>
                            <a className="icon-btn" href={d.url} target="_blank" rel="noopener noreferrer" title="Open in SharePoint"><Icon name="external-link" size={14} /></a>
                            {can('contracts', 'edit') && <button className="icon-btn danger" title="Remove reference" onClick={() => { actions.removeDocumentReference(d.id); toast('Document reference removed', 'good'); }}><Icon name="trash-2" size={14} /></button>}
                          </>)}
                        </div>
                      </td>
                    </tr>
                  );})}
                </tbody>
              </table>
            </div>
          )}
        </div>

        {addOpen && <DocumentReferenceModal ctx={ctx} title="Add Document Reference" subtitle={c.no + ' · ' + c.vendor} entityType="contract" entityId={c.id} contractNo={c.no} onClose={() => setAddOpen(false)} />}
      </div>
    );
  }

  /* ===================== AFOP & PO ===================== */
  function AfopTab({ c, ctx }) {
    const { store, can, navigate } = ctx;
    const toast = window.useToast();
    const [openPo, setOpenPo] = useState({});
    const [openAc, setOpenAc] = useState({});
    const [mode, setMode] = useState('reconciliation');
    const afops = store.afopLines.filter((a) => a.contractId === c.id).filter((a) => !a.deletedAt);
    const poTotalForAfop = (a) => store.poLines.filter((p) => p.afopLineId === a.id && !p.deletedAt).reduce((s, p) => s + p.amt, 0);
    const afopAmt = (a) => mode === 'reconciled' ? poTotalForAfop(a) || a.amt : a.amt;
    const totalAfop = afops.reduce((s, a) => s + afopAmt(a), 0);
    const contractDocs = (store.documentReferences || []).filter((r) => r.entityType === 'contract' && r.entityId === c.id);
    const editable = can('contracts', 'edit') && mode === 'planning';
    const wbOver = (a) => { const it = store.wpbItems.find((w) => w.id === a.wId); return it ? E.waterfallForItem(store, it).totalAfop > it.approved : false; };
    const afopRemaining = (a) => { const pos = store.poLines.filter((p) => p.afopLineId === a.id && !p.deletedAt); const baseAmt = mode === 'reconciled' ? poTotalForAfop(a) : a.amt; return baseAmt - pos.reduce((s, p) => s + p.amt, 0); };
    const ioWpbPairs = useMemo(() => { const seen = new Set(); const out = []; afops.forEach((a) => { const key = a.ioId + '|' + a.wId; if (!seen.has(key)) { seen.add(key); const io = store.ios.find((x) => x.id === a.ioId); const it = store.wpbItems.find((w) => w.id === a.wId); out.push({ ioId: a.ioId, wId: a.wId, ioLabel: io ? io.io + ' · ' + io.activities : a.ioId, wpbLabel: it ? it.name : a.wId }); } }); return out; }, [afops]);

    return (
      <div className="split">
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          <div className="card card-pad">
            <div className="section-title">Contract Documents</div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 8 }}>
              {contractDocs.length === 0
                ? <span className="muted" style={{ fontSize: 'var(--text-sm)' }}>No documents linked yet</span>
                : contractDocs.slice(0, 4).map((d) => (
                  <div key={d.id} className="row" style={{ justifyContent: 'space-between', fontSize: 'var(--text-sm)', gap: 8 }}>
                    <span className="muted" style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{d.description}</span>
                    <a className="link" style={{ fontSize: 12, whiteSpace: 'nowrap' }} href={d.url} target="_blank" rel="noopener noreferrer"><Icon name="external-link" size={12} />Open</a>
                  </div>
                ))}
              {contractDocs.length > 4 && <span className="muted" style={{ fontSize: 12 }}>+{contractDocs.length - 4} more — see Documents tab</span>}
            </div>
          </div>
          <div className="card card-pad">
            <div className="section-title">AFOP Summary</div>
            <KV k="Total AFOP Allocated" v={<span className="num" style={{ fontSize: 'var(--text-lg)', fontWeight: 600 }}>USD {E.fmtUSD0(totalAfop)}</span>} />
            {afops.some(wbOver) && <div className="badge badge-warning mt12"><Icon name="alert-triangle" size={12} />Exceeds a linked WP&amp;B approved budget</div>}
            <div className="field-hint mt12">Editing an AFOP amount recalculates Budget headroom, IO variance, reports, and Cockpit Action Items instantly.</div>
          </div>
        </div>

        <div className="card" style={{ overflow: 'hidden' }}>
          <div className="card-head">
            <span className="card-title">AFOP Lines & Annual PO</span>
            {can('contracts', 'edit') && mode === 'planning' && (
              <button className="btn btn-primary btn-sm" style={{ marginRight: 8 }} onClick={() => {
                const newLine = { id: 'af_' + c.id + '_' + Date.now(), contractId: c.id, no: afops.length + 1, desc: 'New AFOP Line', wId: '', ioId: '', amt: 0 };
                ctx.actions.addAfopLine(newLine); toast('AFOP line added', 'good');
              }}><Icon name="plus" size={14} />Add AFOP Line</button>
            )}
            <div className="subtabs">
              <button className={'subtab' + (mode === 'planning' ? ' active' : '')} onClick={() => setMode('planning')} title="Edit AFOP/PO lines, IO/WP&B assignments — active during planning cycle and after amendments">Planning</button>
              <button className={'subtab' + (mode === 'reconciled' ? ' active' : '')} onClick={() => setMode('reconciled')} title="Read-only view — fields confirmed by ERP import. Switch back to Planning after recording an amendment">Reconciliation</button>
            </div>
          </div>

          {mode === 'reconciled' && (
            <div style={{ background: 'var(--color-blue-50)', borderBottom: '1px solid var(--color-blue-100)', padding: '6px 14px', fontSize: 'var(--text-xs)', color: 'var(--color-blue-700)', display: 'flex', alignItems: 'center', gap: 6 }}>
              <Icon name="lock" size={13} /> Reconciliation — ERP data confirmed and locked. Values shown are from imported PO data. Record an amendment to return to Planning mode.
            </div>
          )}
          {mode === 'planning' && (
            <div style={{ background: 'var(--color-amber-50)', borderBottom: '1px solid var(--color-amber-100)', padding: '6px 14px', fontSize: 'var(--text-xs)', color: 'var(--color-warning-700)', display: 'flex', alignItems: 'center', gap: 6, justifyContent: 'space-between' }}>
              <span><Icon name="pencil" size={13} /> Planning — editing unlocked. Add/edit AFOP & PO lines. Save before switching to Reconciliation.</span>
              <button className="btn btn-primary" style={{ fontSize: 12, height: 30 }} onClick={() => {
                afops.forEach((a) => {
                  const poTotal = poTotalForAfop(a);
                  if (poTotal > 0) ctx.actions.setAfopField(a.id, { amt: poTotal });
                });
                toast('Planning saved — AFOP amounts synced to PO totals', 'good');
              }}><Icon name="save" size={13} />Save Planning</button>
            </div>
          )}

          <div className="section-label" style={{ padding: '6px 16px', background: 'var(--color-slate-50)', borderBottom: '1px solid var(--border-default)', fontSize: 'var(--text-xs)', textTransform: 'uppercase', letterSpacing: '.05em', color: 'var(--text-muted)', fontWeight: 600 }}>
            Section 1 — AFOP Lines
          </div>









          <div className="tbl-wrap">
            <table className="tbl">
              <thead style="position: sticky; top: 0; z-index: 1; background: var(--bg-default)"><tr>
                <th style={{ width: 36 }}></th>
                <th style={{ width: 44 }}>
                  <span className="row" style={{ gap: 4, alignItems: 'center' }}>
                    <Icon name="lock" size={11} color="#94a3b8" /><span>Line</span>
                  </span>
                </th>
                <th>
                  <span className="row" style={{ gap: 4, alignItems: 'center' }}>
                    <Icon name="lock" size={11} color="#94a3b8" /><span>Description</span>
                  </span>
                </th>
                <th>IO</th><th>WP&amp;B Line</th>
                <th className="num-col">AFOP Amt</th><th className="num-col">Remaining</th>
                {can('contracts', 'edit') && mode === 'planning' && <th style={{ width: 36 }}></th>}
              </tr></thead>
              <tbody>
                {afops.map((a) => {
                  const it = store.wpbItems.find((w) => w.id === a.wId);
                  const io = store.ios.find((x) => x.id === a.ioId);
                  const pos = store.poLines.filter((p) => p.afopLineId === a.id);
                  const isOpen = openPo[a.id];
                  return (
                    <React.Fragment key={a.id}>
                      <tr className="clickable" onClick={() => setOpenPo((o) => ({ ...o, [a.id]: !isOpen }))}>
                        <td><span className={'caret' + (isOpen ? ' open' : '')}><Icon name="chevron-right" size={15} /></span></td>
                        <td className={can('contracts', 'edit') && mode === 'planning' ? '' : 'cell-locked mono'}>
                          {can('contracts', 'edit') && mode === 'planning'
                            ? <input className="input mono" style={{ width: 50, height: 28, fontSize: 12 }} type="number" value={a.no} onChange={(e) => ctx.actions.setAfopField(a.id, { no: Number(e.target.value) })} />
                            : a.no}
                        </td>
                        <td className={can('contracts', 'edit') && mode === 'planning' ? '' : 'cell-locked'}>
                          {can('contracts', 'edit') && mode === 'planning'
                            ? <input className="input" style={{ width: 220, height: 28, fontSize: 12 }} value={a.desc} onChange={(e) => ctx.actions.setAfopField(a.id, { desc: e.target.value })} />
                            : a.desc}
                        </td>
                        <td onClick={(e) => e.stopPropagation()} style={{ fontSize: 12 }}>
                          {can('contracts', 'edit') && mode === 'planning'
                            ? <select className="select" style={{ height: 28, fontSize: 11, width: 200 }} value={a.ioId || ''}
                                onChange={(e) => {
                                  const newIoId = e.target.value;
                                  const patch = { ioId: newIoId };
                                  if (newIoId && !a.wId) {
                                    const pairedWpb = ioWpbPairs.filter((p) => p.ioId === newIoId);
                                    if (pairedWpb.length === 1) { patch.wId = pairedWpb[0].wId; toast('IO set — WP&B auto-filled from matrix', 'good'); }
                                    else { toast('IO updated', 'good'); }
                                  } else { toast('IO updated', 'good'); }
                                  ctx.actions.setAfopField(a.id, patch);
                                }}>
                                <option value="">—</option>
                                {store.ios.map((x) => <option key={x.id} value={x.id}>{x.io + ' · ' + x.activities}</option>)}
                              </select>
                            : <span className="mono">{io ? io.io + ' · ' + io.activities : '—'}</span>}
                        </td>
                        <td onClick={(e) => e.stopPropagation()} style={{ fontSize: 12 }}>
                          {can('contracts', 'edit') && mode === 'planning'
                            ? <select className="select" style={{ height: 28, fontSize: 11, width: 180 }} value={a.wId || ''}
                                onChange={(e) => {
                                  const newWId = e.target.value;
                                  const patch = { wId: newWId };
                                  if (newWId && !a.ioId) {
                                    const pairedIo = ioWpbPairs.filter((p) => p.wId === newWId);
                                    if (pairedIo.length === 1) { patch.ioId = pairedIo[0].ioId; toast('WP&B set — IO auto-filled from matrix', 'good'); }
                                    else { toast('WP&B updated', 'good'); }
                                  } else { toast('WP&B updated', 'good'); }
                                  ctx.actions.setAfopField(a.id, patch);
                                }}>
                                <option value="">—</option>
                                {store.wpbItems.map((w) => <option key={w.id} value={w.id}>{w.name}</option>)}
                              </select>
                            : <span>{it ? it.name : '—'}</span>}
                        </td>
                        <td className="num-col">
                          <Money v={poTotalForAfop(a) || a.amt} />
                          <span className="field-hint" style={{ fontSize: 9, display: 'block' }}>sum of POs</span>
                        </td>
                        <td className="num-col">
                          <span style={{ color: afopRemaining(a) < 0 ? 'var(--color-critical-600)' : undefined }}>
                            <Money v={afopRemaining(a)} />
                          </span>
                        </td>
                        {can('contracts', 'edit') && mode === 'planning' && (
                          <td className="col-actions">
                            <button className="icon-btn danger" title="Delete AFOP line" onClick={(e) => { e.stopPropagation(); ctx.actions.deleteAfopLine(a.id); toast('AFOP line soft-deleted', 'info'); }}>
                              <Icon name="trash-2" size={13} />
                            </button>
                          </td>
                        )}
                      </tr>


                      {/* Section 2: PO Lines (expandable sub-table) */}
                      {isOpen && (
                        <tr><td colSpan={8} className="drill"><div className="drill-inner">
                          <div className="muted mb8" style={{ fontSize: 11, textTransform: 'uppercase', letterSpacing: '.04em' }}>Section 2 — Annual PO Lines</div>
                          <table className="tbl tbl-compact" style={{ border: '1px solid var(--border-default)', borderRadius: 6 }}>
                            <thead style="position: sticky; top: 0; z-index: 1; background: var(--bg-default)"><tr>
                              <th style={{ width: 26 }}></th>
                              <th><span className="row" style={{ gap: 4, alignItems: 'center' }}><Icon name="lock" size={10} color="#94a3b8" /><span>ERP PO No</span></span></th>
                              <th style={{ width: 50 }}>Line</th>
                              <th><span className="row" style={{ gap: 4, alignItems: 'center' }}><Icon name="lock" size={10} color="#94a3b8" /><span>Year</span></span></th>
                              <th>Description</th>
                              <th className="num-col"><span className="row" style={{ gap: 4, alignItems: 'center', justifyContent: 'flex-end' }}><Icon name="lock" size={10} color="#94a3b8" /><span>PO Amount</span></span></th>
                              <th>Status</th>
                              <th className="num-col">AC Submitted</th>
                              <th className="num-col">AC Consumed</th>
                              <th className="num-col">Remaining</th>
                              {can('contracts', 'edit') && mode === 'planning' && <th style={{ width: 30 }}></th>}
                            </tr></thead>
                            <tbody>
                              {pos.filter((p) => !p.deletedAt).map((p) => {
                                const cons = E.acConsumedForPo(store, p.id);
                                const sub = E.acSubmittedForPo(store, p.id);
                                const acs = E.acsForPo(store, p.id, mode);
                                const isAcOpen = openAc[p.id];
                                return (
                                  <React.Fragment key={p.id}>
                                    <tr className="clickable">
                                      <td onClick={(e) => { e.stopPropagation(); setOpenAc((o) => ({ ...o, [p.id]: !isAcOpen })); }}>
                                        <span className={'caret' + (isAcOpen ? ' open' : '')} style={{ marginRight: 0 }}><Icon name="chevron-right" size={12} /></span>
                                      </td>
                                      <td className={editable ? '' : 'cell-locked mono'} style={{ fontSize: 12 }} onClick={(e) => isAcOpen && e.stopPropagation()}>
                                        {editable ? <input className="input mono" style={{ width: 100, height: 26, fontSize: 11 }} value={p.erpPoNo} onChange={(e) => ctx.actions.setPoField(p.id, { erpPoNo: e.target.value })} /> : p.erpPoNo}
                                      </td>
                                      <td className={editable ? 'mono' : 'cell-locked mono'} style={{ fontSize: 12, width: 50 }} onClick={(e) => isAcOpen && e.stopPropagation()}>
                                        {editable ? <input className="input num" style={{ width: 44, height: 26, fontSize: 11 }} type="number" value={p.lineNo || ''} onChange={(e) => ctx.actions.setPoField(p.id, { lineNo: Number(e.target.value) })} /> : (p.lineNo || '—')}
                                      </td>
                                      <td className={editable ? '' : 'cell-locked mono'} onClick={(e) => isAcOpen && e.stopPropagation()}>
                                        {editable ? <input className="input num" style={{ width: 60, height: 26, fontSize: 11 }} type="number" value={p.year} onChange={(e) => ctx.actions.setPoField(p.id, { year: Number(e.target.value) })} /> : p.year}
                                      </td>
                                      <td onClick={(e) => isAcOpen && e.stopPropagation()}>{editable ? <input className="input" style={{ width: 120, height: 26, fontSize: 11 }} value={p.desc} onChange={(e) => ctx.actions.setPoField(p.id, { desc: e.target.value })} /> : p.desc}</td>
                                      <td className={editable ? 'num-col' : 'cell-locked num-col'} onClick={(e) => isAcOpen && e.stopPropagation()}>
                                        {editable ? <input className="input mono" style={{ width: 90, textAlign: 'right', height: 26, fontSize: 11 }} type="number" value={p.amt} onChange={(e) => ctx.actions.setPoField(p.id, { amt: Number(e.target.value) })} /> : <Money v={p.amt} />}
                                      </td>
                                      <td onClick={(e) => isAcOpen && e.stopPropagation()}>{editable
                                        ? <select className="select" style={{ height: 26, fontSize: 11 }} value={p.status} onChange={(e) => ctx.actions.setPoField(p.id, { status: e.target.value })}>{store.lookups.poStatus.filter((s) => s.active).map((s) => <option key={s.id} value={s.id}>{s.label}</option>)}</select>
                                        : <StatusBadge store={store} list="poStatus" id={p.status} />}
                                      </td>
                                      <td className="num-col sub-col" onClick={(e) => isAcOpen && e.stopPropagation()}><Money v={sub} dash /></td>
                                      <td className="num-col" onClick={(e) => isAcOpen && e.stopPropagation()}><Money v={cons} dash /></td>
                                      <td className="num-col" onClick={(e) => isAcOpen && e.stopPropagation()}><Money v={p.amt - cons} /></td>
                                      {editable && <td className="col-actions"><button className="icon-btn danger" title="Delete PO line" onClick={(e) => { e.stopPropagation(); ctx.actions.deletePoLine(p.id); toast('PO line removed', 'info'); }}><Icon name="trash-2" size={12} /></button></td>}
                                    </tr>
                                    {isAcOpen && (
                                      <tr key={p.id + '_acs'}><td colSpan={editable ? 11 : 10} className="drill"><div className="drill-inner">
                                        <div className="muted mb8" style={{ fontSize: 11, textTransform: 'uppercase', letterSpacing: '.04em' }}>
                                          Section 3 — {mode === 'planning' ? 'Planning' : 'Reconciliation'}: {acs.length} AC{acs.length !== 1 ? 's' : ''} linked
                                        </div>
                                        {acs.length === 0 ? (
                                          <div className="muted" style={{ fontSize: 'var(--text-sm)', padding: '12px 0', textAlign: 'center' }}>
                                            {mode === 'planning' ? 'No pending ACs for this PO line' : 'No reconciled ACs for this PO line'}
                                          </div>
                                        ) : (
                                          <table className="tbl tbl-compact" style={{ border: '1px solid var(--border-default)', borderRadius: 6 }}>
              <thead style="position: sticky; top: 0; z-index: 1; background: var(--bg-default)"><tr>
                                              <th style={{ width: 70 }}>AC #</th>
                                              <th>CCP</th>
                                              <th className="num-col">{mode === 'planning' ? 'Submitted' : 'ERP Amount'}</th>
                                              <th style={{ width: 110 }}>Status</th>
                                              <th style={{ width: 50 }}></th>
                                            </tr></thead>
                                            <tbody>
                                              {acs.map((ac) => (
                                                <tr key={ac.id}>
                                                  <td className="mono" style={{ fontSize: 11 }}>{ac.acNumber}</td>
                                                  <td className="mono" style={{ fontSize: 11 }}>{E.cashLabel(ac.cashCallPeriod)}</td>
                                                  <td className="num-col mono" style={{ fontSize: 11 }}>
                                                    <Money v={mode === 'planning' ? ac.valueSubmitted : ac.erpAmount} dash />
                                                  </td>
                                                  <td><StatusBadge store={store} list="acStatus" id={ac.status} /></td>
                                                  <td>
                                                    <button className="btn btn-sm" style={{ fontSize: 11, height: 24 }} onClick={() => {
                                                      navigate('contract', { id: c.id, tab: 'aclog', focus: ac.id });
                                                    }}><Icon name="external-link" size={10} />View</button>
                                                  </td>
                                                </tr>
                                              ))}
                                            </tbody>
                                          </table>
                                        )}
                                      </div></td></tr>
                                    )}
                                  </React.Fragment>
                                );
                              })}
                              {pos.length === 0 && <tr><td colSpan={editable ? 11 : 10} className="muted" style={{ textAlign: "center", padding: 16 }}>No PO lines for this AFOP</td></tr>}
                              {can('contracts', 'edit') && mode === 'planning' && (
                                <tr><td colSpan={editable ? 11 : 10} style={{ padding: '6px 12px', background: 'var(--color-slate-50)' }}>
                                  <button className="btn btn-primary" style={{ fontSize: 12, height: 30 }} onClick={() => {
                                    ctx.actions.addPoLine({ id: 'po_' + a.id + '_' + Date.now(), afopLineId: a.id, erpPoNo: '', year: E.CY, desc: 'New PO Line', amt: 0, status: 'open' });
                                    toast('PO line added to ' + (a.desc || 'AFOP line'), 'good');
                                  }}><Icon name="plus" size={12} />Add PO Line</button>
                                </td></tr>
                              )}
                            </tbody>
                          </table>
                          {/* AFOP summary row */}
                          <div style={{ marginTop: 8, padding: '6px 12px', background: 'var(--color-slate-50)', borderRadius: 6, fontSize: 'var(--text-xs)', display: 'flex', gap: 16, color: 'var(--text-muted)' }}>
                            <span>{pos.filter((p) => !p.deletedAt).length} PO{pos.filter((p) => !p.deletedAt).length !== 1 ? 's' : ''}</span>
                            <span>|</span>
                            <span>AC Submitted: <strong style={{ color: 'var(--text-default)' }}><Money v={pos.reduce((s, p) => s + E.acSubmittedForPo(store, p.id), 0)} /></strong></span>
                            <span>|</span>
                            <span>ERP Consumed: <strong style={{ color: 'var(--text-default)' }}><Money v={pos.reduce((s, p) => s + E.acConsumedForPo(store, p.id), 0)} /></strong></span>
                          </div>
                        </div></td></tr>
                      )}
                    </React.Fragment>
                  );
                })}
                <tr style={{ fontWeight: 700, background: 'var(--color-slate-100)', borderTop: '2px solid var(--color-slate-300)' }}>
                  <td colSpan={6}>AFOP Total</td>
                  <td className="num-col"><Money v={totalAfop} /></td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    );
  }

  /* ===================== AC LOG (within contract) ===================== */
  function ContractAcTab({ c, ctx }) {
    const { store, navigate, can } = ctx;
    const toast = window.useToast();
    const [showDeleted, setShowDeleted] = useState(false);
    const [statusHist, setStatusHist] = useState(null);
    const [linkAc, setLinkAc] = useState(null);
    const [deleteAc, setDeleteAc] = useState(null);
    const [editAcId, setEditAcId] = useState(null);
    const [q, setQ] = useState('');
    const [fStatus, setFStatus] = useState('');
    const [fPoLine, setFPoLine] = useState('');
    const [sort, setSort] = useState({ col: 'cashCallPeriod', dir: 'asc' });
    const activeEditAc = editAcId ? store.acRecords.find((a) => a.id === editAcId) : null;
    const activeEditContract = activeEditAc ? store.contracts.find((ct) => ct.id === activeEditAc.contractId) : null;

    let acs = store.acRecords.filter((a) => a.contractId === c.id)
      .sort((x, y) => x.cashCallPeriod.localeCompare(y.cashCallPeriod) || x.acNumber.localeCompare(y.acNumber));
    if (!showDeleted) acs = acs.filter((a) => !a.deletedAt);
    acs = acs.filter((a) => {
      if (q && !(a.acNumber.includes(q) || (a.serviceDescription || '').toLowerCase().includes(q.toLowerCase()) || a.scope.toLowerCase().includes(q.toLowerCase()))) return false;
      if (fStatus && a.status !== fStatus) return false;
      if (fPoLine && a.poLineId !== fPoLine) return false;
      return true;
    });
    const acc = {
      acNumber: (a) => a.acNumber,
      valueSubmitted: (a) => a.valueSubmitted,
      status: (a) => a.status,
      cashCallPeriod: (a) => a.cashCallPeriod,
      erpAmount: (a) => a.erpAmount,
      poLineId: (a) => { const po = store.poLines.find((p) => p.id === a.poLineId); return po ? po.erpPoNo : ''; },
    };
    acs = window.sortRows(acs, sort, acc);

    const activeAcs = acs.filter((a) => !a.deletedAt);

    const setEditPeriod = (a, cp) => {
      const [yy, mm] = cp.split('-').map(Number);
      if (!yy || !mm) return;
      const lastDay = new Date(yy, mm, 0).getDate();
      ctx.actions.setAcField(a.id, {
        cashCallPeriod: cp, year: yy,
        periodStart: cp + '-01',
        periodEnd: cp + '-' + String(lastDay).padStart(2, '0'),
      });
      toast('Cash Call Period → ' + E.cashLabel(cp) + ' · services period auto-set: ' + cp + '-01 → ' + cp + '-' + lastDay, 'good');
    };

    return (
      <div>
        <div className="card" style={{ overflow: 'hidden' }}>
          <div className="table-toolbar">
            <span className="card-title">AC Records · {c.no}</span>
            <button className="btn btn-sm btn-secondary" style={{ marginLeft: 12, fontSize: 11, height: 28 }} onClick={() => navigate('contract', { id: c.id, tab: 'afop' })}>
              <Icon name="bar-chart" size={12} />AFOP & PO
            </button>
            <label className="row muted" style={{ gap: 6, fontSize: 12, marginLeft: 12 }}>
              <input type="checkbox" checked={showDeleted} onChange={(e) => setShowDeleted(e.target.checked)} />
              Show deleted
            </label>
            <div className="spacer" />
            {can('aclog', 'create') && window.PreplanButton && <window.PreplanButton contractId={c.id} small />}
            {can('aclog', 'create') && window.NewAcButton && <window.NewAcButton contractId={c.id} small />}
          </div>
          <div className="filterbar">
            <div className="search-box"><Icon name="search" size={15} /><input className="input" placeholder="Search AC#, service desc, scope…" value={q} onChange={(e) => setQ(e.target.value)} style={{ width: 220 }} /></div>
            <select className="select" value={fStatus} onChange={(e) => setFStatus(e.target.value)}><option value="">All statuses</option>{store.lookups.acStatus.filter((s) => s.active).map((s) => <option key={s.id} value={s.id}>{s.label}</option>)}</select>
            <select className="select" value={fPoLine} onChange={(e) => setFPoLine(e.target.value)} style={{ maxWidth: 200 }}><option value="">All PO lines</option>{store.poLines.filter((p) => { const af = store.afopLines.find((a) => a.id === p.afopLineId); return af && af.contractId === c.id && !p.deletedAt; }).map((p) => { const af = store.afopLines.find((a) => a.id === p.afopLineId); return <option key={p.id} value={p.id}>AFOP #{(af||{}).no}: {p.erpPoNo} ({p.year})</option>; })}</select>
          </div>
          <div className="tbl-wrap">
            <table className="tbl tbl-compact">
              <thead style={{ position: 'sticky', top: 0, zIndex: 1, background: 'var(--bg-default)' }}><tr>
                <SortHead label="AC No" col="acNumber" sort={sort} setSort={setSort} />
                <th>Services Period</th><th>Cur</th>
                <SortHead label="AC Submitted" col="valueSubmitted" sort={sort} setSort={setSort} numeric />
                <SortHead label="Status" col="status" sort={sort} setSort={setSort} />
                <th>Status History</th>
                <SortHead label="Cash Call" col="cashCallPeriod" sort={sort} setSort={setSort} />
                <SortHead label="PO Line" col="poLineId" sort={sort} setSort={setSort} />
                <SortHead label="ERP Amount" col="erpAmount" sort={sort} setSort={setSort} numeric />
                <th className="num-col">Gap</th>
                <th>SAP Dates</th>
                <th>Notes</th>
                <th>Document Links</th>
                {can('aclog', 'edit') && <th></th>}
              </tr></thead>
              <tbody>
                {acs.map((a) => {
                  const gap = (a.erpAmount || 0) - (a.valueSubmitted || 0);
                  const hasErp = !!a.erpAmount;
                  const acDocs = (store.documentReferences || []).filter((r) => r.entityType === 'ac_record' && r.entityId === a.id);
                  const historyCount = (a.acStatusHistory || []).length;
                  const latestHistory = (a.acStatusHistory || [])[historyCount - 1];
                  return (
                    <tr key={a.id} className={'clickable' + (a.deletedAt ? ' deleted-row' : '')} onClick={() => navigate('aclog', { focus: a.id })}>
                      <td className="mono">{a.acNumber}</td>
                      <td className="num" style={{ fontSize: 12 }}>{a.periodStart} → {a.periodEnd}</td>
                      <td>{a.cur}</td>
                      <td className="num-col"><Money v={a.valueSubmitted} dec={2} /></td>
                      <td onClick={(e) => e.stopPropagation()}>
                        {(() => { const sDef = store.lookups.acStatus.find(s => s.id === a.status); const isTerm = sDef?.is_terminal; if (isTerm || !can('aclog', 'edit') || a.deletedAt) return <StatusBadge store={store} list="acStatus" id={a.status} />; return <AcStatusSelect a={a} ctx={ctx} />; })()}
                      </td>
                      <td style={{ fontSize: 11 }} onClick={(e) => e.stopPropagation()}>
                        {historyCount > 0
                          ? <span className="link" onClick={() => setStatusHist(a)}>{historyCount} change{historyCount > 1 ? 's' : ''}</span>
                          : <span className="dash">—</span>}
                      </td>
                      <td>{E.cashLabel(a.cashCallPeriod)}</td>
                      <td style={{ fontSize: 11 }} onClick={(e) => { e.stopPropagation(); navigate('contract', { id: c.id, tab: 'afop' }); }}>
                        {(() => {
                          const po = store.poLines.find((p) => p.id === a.poLineId);
                          if (!po) return <span className="muted">—</span>;
                          const af = store.afopLines.find((x) => x.id === po.afopLineId);
                          return <span className="link">AFOP #{af ? af.no : '?'} · {po.erpPoNo || 'PO ' + po.id.slice(0,6)}</span>;
                        })()}
                      </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 style={{ fontSize: 11 }} onClick={(e) => e.stopPropagation()}>
                          {(a.erpAchieve || a.erpCreate || a.erpPost || a.erpClear) ? (
                            <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>
                              {a.erpAchieve && <span title="Achievement"><span className="muted">Ach:</span> <span className="mono">{E.fmtDate(a.erpAchieve)}</span></span>}
                              {a.erpCreate && <span title="Creation"><span className="muted">Cre:</span> <span className="mono">{E.fmtDate(a.erpCreate)}</span></span>}
                              {a.erpPost && <span title="Posting"><span className="muted">Pst:</span> <span className="mono">{E.fmtDate(a.erpPost)}</span></span>}
                              {a.erpClear && <span title="Clearing"><span className="muted">Clr:</span> <span className="mono">{E.fmtDate(a.erpClear)}</span></span>}
                            </div>
                          ) : <span className="dash">—</span>}
                        </td>

                      <td style={{ maxWidth: 140, fontSize: 11 }} onClick={(e) => e.stopPropagation()}>
                        {(() => { const sDef = store.lookups.acStatus.find(s => s.id === a.status); const isTerm = sDef?.is_terminal; if (isTerm || !can('aclog', 'edit') || a.deletedAt) return a.notes || '—'; return <input className="input" style={{ width: '100%', fontSize: 11, height: 24 }} value={a.notes || ''} onChange={(e) => ctx.actions.setAcField(a.id, { notes: e.target.value })} placeholder="Notes..." />; })()}
                      </td>
                      <td onClick={(e) => e.stopPropagation()}>
                        <div className="row" style={{ gap: 4 }}>
                          {acDocs.length > 0
                            ? <span className="link" style={{ fontSize: 12 }} onClick={() => toast(acDocs.map((d) => d.description + (d.url ? ': ' + d.url : '')).join(', '), 'info')}>{acDocs.length} link{acDocs.length > 1 ? 's' : ''}</span>
                            : <span className="dash">—</span>}
                          {(() => { const sDef = store.lookups.acStatus.find(s => s.id === a.status); const isTerm = sDef?.is_terminal; if (!isTerm && can('aclog', 'edit') && !a.deletedAt) return (<button className="icon-btn" style={{ width: 20, height: 20 }} title="Add SharePoint link" onClick={() => setLinkAc(a)}><Icon name="link-2" size={12} /></button>); return null; })()}
                        </div>
                      </td>
                      {can('aclog', 'edit') && (
                        <td className="col-actions" onClick={(e) => e.stopPropagation()}>
                          {!a.deletedAt ? (
                            <div className="row" style={{ gap: 2 }}>
                              {(() => { const sDef = store.lookups.acStatus.find(s => s.id === a.status); const isTerm = sDef?.is_terminal; return isTerm ? (
                                <button className="icon-btn" title="View (read-only)" onClick={() => setEditAcId(a.id)}>
                                  <Icon name="eye" size={14} />
                                </button>
                              ) : (<>
                                <button className="icon-btn" title="Edit AC Record" onClick={() => setEditAcId(a.id)}>
                                  <Icon name="pencil" size={14} />
                                </button>
                                <button className="icon-btn danger" title="Soft delete" onClick={() => setDeleteAc(a)}>
                                  <Icon name="trash-2" size={14} />
                                </button>
                              </>); })()}
                              <button className="icon-btn" title="Copy as placeholder" onClick={() => { ctx.actions.duplicateAc(a.id); toast('AC copied as new placeholder', 'good'); }}>
                                <Icon name="copy" size={14} />
                              </button>
                            </div>
                          ) : (
                            <button className="icon-btn" title="Restore" onClick={() => { ctx.actions.restoreAcRecord(a.id); toast('AC ' + a.acNumber + ' restored', 'good'); }}>
                              <Icon name="rotate-ccw" size={14} />
                            </button>
                          )}
                        </td>
                      )}
                    </tr>
                  );
                })}
              </tbody>
            </table>
            {activeAcs.length === 0 && <EmptyState icon="receipt" title="No AC records for this contract" sub="Use Pre-plan ACs to generate monthly placeholders, or add an ad-hoc AC." />}
          </div>
        </div>
        {linkAc && <DocumentReferenceModal ctx={ctx} title="Add AC Document Link" subtitle={c.no + ' / AC ' + linkAc.acNumber} entityType="ac_record" entityId={linkAc.id} contractNo={c.no} fixedCategory="dc_ac_doc" defaultDescription={'AC ' + linkAc.acNumber + ' document'} onClose={() => setLinkAc(null)} />}
        {deleteAc && (
          <Modal title="Soft Delete AC Record" subtitle={c.no + ' / AC ' + deleteAc.acNumber} onClose={() => setDeleteAc(null)}
            footer={<><button className="btn btn-secondary" onClick={() => setDeleteAc(null)}>Cancel</button><button className="btn btn-destructive" onClick={() => { ctx.actions.deleteAcRecord(deleteAc.id); toast('AC ' + deleteAc.acNumber + ' soft-deleted. Admin can recover it from Settings.', 'warn'); setDeleteAc(null); }}>Soft delete</button></>}>
            <p className="muted" style={{ margin: 0 }}>This AC record will be hidden from the active contract view. Status history and SharePoint document references remain retained.</p>
          </Modal>
        )}
        {statusHist && (
          <Modal title="Status History" subtitle={'AC ' + statusHist.acNumber + ' · ' + statusHist.contractNo} onClose={() => setStatusHist(null)}
            footer={<button className="btn btn-secondary" onClick={() => setStatusHist(null)}>Close</button>}>
            {(statusHist.acStatusHistory || []).length === 0 ? (
              <p className="muted">No status changes recorded.</p>
            ) : (
              <table className="tbl tbl-compact">
                <thead><tr><th>From</th><th>To</th><th>Date</th></tr></thead>
                <tbody>
                  {(statusHist.acStatusHistory || []).map((h, i) => (
                    <tr key={i}>
                      <td>{h.from ? E.lkLabel(store, 'acStatus', h.from) : 'Created'}</td>
                      <td>{E.lkLabel(store, 'acStatus', h.to)}</td>
                      <td className="mono" style={{ fontSize: 12 }}>{h.changedAt || '—'}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}
          </Modal>
        )}
        {activeEditAc && (() => {
            const statusDef = store.lookups.acStatus.find(s => s.id === activeEditAc.status);
            const isTerminal = statusDef?.is_terminal;
            const hasErpData = !!(activeEditAc.erpAmount);
            const isFullyLocked = isTerminal;
            return (
          <Modal title="Edit AC Record" subtitle={activeEditAc.contractNo + ' / AC ' + activeEditAc.acNumber} size="lg" onClose={() => setEditAcId(null)}
            footer={<>
              <button className="btn btn-secondary" onClick={() => setEditAcId(null)}>Cancel</button>
              <button className="btn btn-primary" onClick={() => { toast('Saved', 'good'); setEditAcId(null); }}><Icon name="save" size={14} />Save & Close</button>
            </>}>
            {hasErpData && (
              <div style={{ background: 'var(--color-blue-50)', border: '1px solid var(--color-blue-100)', borderRadius: 6, padding: '8px 12px', marginBottom: 12, fontSize: 'var(--text-xs)', color: 'var(--color-blue-700)', display: 'flex', alignItems: 'center', gap: 6 }}>
                <Icon name="lock" size={13} /> {isTerminal ? "🔒 05 Done — budget consumed. All fields locked. Notes remain editable." : "🔒 Submitted to ERP — ERP AC Amount and ERP AC Number are locked. Other fields remain editable until finalized."}
              </div>
            )}
            <div className="form-grid">
              <Field label="Company Contract No"><div className="field-readonly mono">{activeEditAc.contractNo}</div></Field>
              <Field label="Contractor"><div className="field-readonly">{activeEditAc.vendor}</div></Field>
              <Field label="AC Number">
                {isFullyLocked ? <div className="field-readonly mono">{activeEditAc.acNumber || '—'}</div> : <input className="input mono" value={activeEditAc.acNumber || ''} onChange={(e) => ctx.actions.setAcField(activeEditAc.id, { acNumber: e.target.value, erpAcNo: activeEditAc.contractNo + '-O-' + e.target.value })} />}
              </Field>
              <Field label="Cash Call Period">
                {isFullyLocked ? <div className="field-readonly mono">{E.cashLabel(activeEditAc.cashCallPeriod) || '—'}</div> : (() => {
                  const ccpOptions = [];
                  if (activeEditContract) {
                    const s = new Date(activeEditContract.start);
                    const e = new Date(activeEditContract.end);
                    const d = new Date(s.getFullYear(), s.getMonth(), 1);
                    while (d <= new Date(e.getFullYear() + 3, e.getMonth(), 1)) {
                      const val = d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0');
                      ccpOptions.push({ value: val, label: E.cashLabel(val) });
                      d.setMonth(d.getMonth() + 1);
                    }
                  }
                  return (
                    <select className="select" style={{ height: 30, fontSize: 12, width: 170 }} value={activeEditAc.cashCallPeriod || ''} onChange={(e) => setEditPeriod(activeEditAc, e.target.value)}>
                      <option value="">Select month…</option>
                      {ccpOptions.map((o) => <option key={o.value} value={o.value}>{o.label}</option>)}
                    </select>
                  );
                })()}
              </Field>
              
              <Field label="Currency" hint={activeEditContract ? 'Matches contract currency' : ''}>
                <div className="field-readonly">{activeEditAc.cur || (activeEditContract ? activeEditContract.cur : 'USD')}</div>
              </Field>
              <Field label="Services Period">
                {isFullyLocked ? <div className="field-readonly">{activeEditAc.periodStart || '—'} → {activeEditAc.periodEnd || '—'}</div> : <div className="row" style={{ gap: 8, alignItems: 'center' }}><input className="input mono" type="date" value={activeEditAc.periodStart || ''} onChange={(e) => ctx.actions.setAcField(activeEditAc.id, { periodStart: e.target.value })} style={{ width: 160 }} /><span className="muted">→</span><input className="input mono" type="date" value={activeEditAc.periodEnd || ''} onChange={(e) => ctx.actions.setAcField(activeEditAc.id, { periodEnd: e.target.value })} style={{ width: 160 }} /></div>}
              </Field>
              <Field label="PO Line" span>
                {isFullyLocked ? (() => {
                  const curPo = store.poLines.find((p) => p.id === activeEditAc.poLineId);
                  const curAf = curPo ? store.afopLines.find((a) => a.id === curPo.afopLineId) : null;
                  return <div className="field-readonly">{curPo ? 'AFOP #' + (curAf ? curAf.no : '?') + ': PO ' + curPo.erpPoNo + ' · ' + curPo.desc : '—'}</div>;
                })() : (() => {
                  const poOptions = activeEditContract ? store.poLines.filter((p) => {
                    const af = store.afopLines.find((a) => a.id === p.afopLineId);
                    return af && af.contractId === activeEditContract.id && !p.deletedAt;
                  }).map((p) => {
                    const af = store.afopLines.find((a) => a.id === p.afopLineId);
                    return { value: p.id, label: 'AFOP #' + (af ? af.no : '?') + ': PO ' + p.erpPoNo + ' · ' + p.desc + ' (' + p.year + ')', afopId: p.afopLineId, ioId: af ? af.ioId : null, wId: af ? af.wId : null };
                  }) : [];
                  return (<>
                    <Select value={activeEditAc.poLineId || ''} onChange={(v) => {
                      const sel = poOptions.find((o) => o.value === v);
                      ctx.actions.setAcField(activeEditAc.id, {
                        poLineId: v,
                        afopLineId: sel ? sel.afopId : activeEditAc.afopLineId,
                        ioId: sel ? sel.ioId : activeEditAc.ioId,
                        wId: sel ? sel.wId : activeEditAc.wId,
                      });
                      toast('PO line updated — AFOP, IO & WP&B auto-derived', 'good');
                    }} placeholder={poOptions.length ? 'Select PO line…' : 'No PO lines for this contract'} options={poOptions} />
                    {activeEditAc.poLineId && (() => {
                      const p = store.poLines.find((x) => x.id === activeEditAc.poLineId);
                      const afLine = p ? store.afopLines.find((x) => x.id === p.afopLineId) : null;
                      return (
                        <div className="field-hint" style={{ marginTop: 4 }}>
                          → AFOP #{afLine ? afLine.no : '?'} → IO {activeEditAc.ioId ? (store.ios.find((x) => x.id === activeEditAc.ioId) || {}).io || activeEditAc.ioId : '—'} → WP&B {activeEditAc.wId ? (store.wpbItems.find((x) => x.id === activeEditAc.wId) || {}).name || activeEditAc.wId : '—'}
                        </div>
                      );
                    })()}
                  </>);
                })()}
              </Field>
              <Field label="AC Value Submitted">
                {isFullyLocked ? <div className="field-readonly num"><Money v={activeEditAc.valueSubmitted} cur={activeEditAc.cur} dec={2} /></div> : <input className="input num" type="number" value={activeEditAc.valueSubmitted || ''} onChange={(e) => ctx.actions.setAcField(activeEditAc.id, { valueSubmitted: Number(e.target.value) || 0 })} />}
              </Field>
              <Field label="ERP AC Amount" hint={hasErpData ? 'SAP-sourced — read-only' : 'Editable until submitted to ERP'}>
                <div className="field-readonly num"><Money v={activeEditAc.erpAmount} cur={activeEditAc.cur} dec={2} dash /></div>
              </Field>
              <Field label="Status">
                {isFullyLocked ? <StatusBadge store={store} list="acStatus" id={activeEditAc.status} /> : <Select value={activeEditAc.status} onChange={(v) => { ctx.actions.setAcStatus(activeEditAc.id, v); if (v === 's05') toast('AC ' + activeEditAc.acNumber + ' set to 05 Done — budget recalculated', 'good'); }} options={store.lookups.acStatus.filter((s) => s.active).map((s) => ({ value: s.id, label: s.label }))} />}
              </Field>
              <Field label="ERP AC Number"><div className="field-readonly mono">{activeEditAc.erpAcNo || '—'}</div></Field>
              <Field label="Notes" span>
                <textarea className="input" rows={3} value={activeEditAc.notes || ''} onChange={(e) => ctx.actions.setAcField(activeEditAc.id, { notes: e.target.value })} />
              </Field>
            </div>
          </Modal>
        ); })()}
      </div>
    );
  }

  function AcStatusSelect({ a, ctx }) {
    const { store } = ctx;
    const toast = window.useToast();
    return (
      <select className="select" style={{ height: 28, fontSize: 12, paddingRight: 24 }} value={a.status}
        onChange={(e) => { const v = e.target.value; ctx.actions.setAcStatus(a.id, v); if (v === 's05') toast('AC ' + a.acNumber + ' set to 05 Done — budget recalculated', 'good'); }}>
        {store.lookups.acStatus.filter((s) => s.active).map((s) => <option key={s.id} value={s.id}>{s.label}</option>)}
      </select>
    );
  }

  /* ===================== AMENDMENTS ===================== */
  function AmendmentsTab({ c, ctx }) {
    const { store } = ctx;
    const toast = window.useToast();
    const [open, setOpen] = useState({});
    const [linkAm, setLinkAm] = useState(null);
    const ams = c.amendments || [];

    return (
      <div className="card card-pad" style={{ maxWidth: 820 }}>
        <div className="row" style={{ justifyContent: 'space-between', marginBottom: 16 }}>
          <div className="section-title" style={{ margin: 0 }}>Amendment History</div>
          <div className="row" style={{ gap: 8 }}>
            {ctx.can('contracts', 'edit') && <window.NewAmendmentButton c={c} ctx={ctx} />}
          </div>
        </div>
        <div className="timeline">
          {ams.slice().reverse().map((am, i) => {
            const isOpen = open[am.no];
            const amendDocs = (store.documentReferences || []).filter((r) => r.entityType === 'amendment' && (am.id ? r.entityId === am.id : r.entityId === c.id && r.description.includes(am.no)));
            return (
              <div key={am.no} className={'tl-node' + (i === 0 ? ' recent' : '')}>
                <div className="card" style={{ borderColor: i === 0 ? 'var(--color-blue-100)' : undefined }}>
                  <div className="row" style={{ justifyContent: 'space-between', padding: '12px 16px', cursor: 'pointer' }} onClick={() => setOpen((o) => ({ ...o, [am.no]: !isOpen }))}>
                    <div className="row" style={{ gap: 10 }}>
                      <span className="mono" style={{ fontWeight: 600 }}>{am.no}</span>
                      <StatusBadge store={store} list="amendmentType" id={am.type} />
                      <span className={`badge ${(am.status || 'Recorded') === 'Superseded' ? 'badge-neutral' : (am.status || 'Recorded') === 'Completed' ? 'badge-green' : (am.status || 'Recorded') === 'Draft' ? 'badge-neutral' : 'badge-blue'}`} style={{ fontSize: 10, textTransform: 'capitalize' }}>{am.status || 'Recorded'}</span>
                      <span className="muted" style={{ fontSize: 'var(--text-sm)' }}>{am.desc}</span>
                    </div>
                    <div className="row" style={{ gap: 10 }}>
                      <span className="muted" style={{ fontSize: 12 }}>{E.fmtDateNice(am.date)}</span>
                      <span className={'caret' + (isOpen ? ' open' : '')}><Icon name="chevron-right" size={15} /></span>
                    </div>
                  </div>
                  {isOpen && (
                    <div style={{ padding: '0 16px 14px' }}>
                      {/* Change diff table */}
                      <table className="tbl tbl-compact" style={{ border: '1px solid var(--border-default)', borderRadius: 6 }}>
                        <thead><tr><th>Field</th><th>Previous</th><th>Updated</th></tr></thead>
                        <tbody>
                          {am.changes.map((ch, j) => (
                            <tr key={j}>
                              <td className="dim">{ch.field}</td>
                              <td><span className="diff-old">{ch.old}</span></td>
                              <td><span className="diff-new">{ch.neu}</span></td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                      {/* Next Step */}
                      <div className="mt12 row" style={{ gap: 8, alignItems: 'center' }}>
                        <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--text-muted)' }}>Next Step:</span>
                        {ctx.can('contracts', 'edit') ? (
                          <select className="select" style={{ height: 26, fontSize: 12 }} value={am.nextStep || ''}
                            onChange={(e) => { ctx.actions.updateAmendment(c.id, am.no, { nextStep: e.target.value }); toast('Next step updated', 'good'); }}>
                            {(am.nextStepOptions || ['Close Out']).map((opt) => <option key={opt} value={opt}>{opt}</option>)}
                          </select>
                        ) : (
                          <span className="badge badge-neutral" style={{ fontSize: 11 }}>{am.nextStep || 'Close Out'}</span>
                        )}
                      </div>
                      {/* Documents */}
                      <div className="mt8">
                        <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--text-muted)', marginBottom: 4 }}>Documents</div>
                        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                          {amendDocs.map((d) => (
                            <div key={d.id} className="row" style={{ gap: 4, fontSize: 11, background: 'var(--color-slate-50)', borderRadius: 4, padding: '2px 6px' }}>
                              {d.url ? <a className="link" href={d.url} target="_blank" rel="noopener noreferrer">{d.description}</a> : <span>{d.description}</span>}
                            </div>
                          ))}
                          {amendDocs.length === 0 && <span className="muted" style={{ fontSize: 11 }}>No document links</span>}
                        </div>
                      </div>
                      {/* Amendment actions */}
                      <div className="row mt8" style={{ gap: 6, justifyContent: 'flex-end' }}>
                        <button className="btn btn-secondary btn-sm" style={{ fontSize: 11 }} onClick={() => setLinkAm(am)}><Icon name="link-2" size={12} />Add Document</button>
                      </div>
                      <div className="field-hint mt8">Confirmation letter dated {E.fmtDateNice(am.letter)}</div>
                    </div>
                  )}
                </div>
              </div>
            );
          })}
          <div className="tl-node original">
            <div className="card card-pad" style={{ background: 'var(--color-slate-50)' }}>
              <span className="badge badge-neutral mb8">Original Contract</span>
              <div className="grid-3">
                <KV k="Original Value" v={c.cur + ' ' + E.fmtMoney(c.orig, c.cur)} />
                <KV k="Original End Date" v={c.origEnd} mono />
                <KV k="Start Date" v={c.start} mono />
              </div>
            </div>
          </div>
        </div>
        {linkAm && <DocumentReferenceModal ctx={ctx} title="Add Amendment Document Link" subtitle={c.no + ' / ' + linkAm.no} entityType="amendment" entityId={linkAm.id || c.id} contractNo={c.no} fixedCategory="dc_amendment" defaultDescription={linkAm.no + ' document'} onClose={() => setLinkAm(null)} />}
      </div>
    );
  }

  function NewAmendmentButton({ c, ctx }) {
    const [open, setOpen] = useState(false);
    const toast = window.useToast();
    const { store } = ctx;
    const FIELD_OPTIONS = [
      { value: 'End Date', label: 'End Date' },
      { value: 'Current Contract Value', label: 'Contract Value' },
      { value: 'Scope', label: 'Scope of Work' },
      { value: 'IO/WP&B Mapping', label: 'IO/WP&B Mapping' },
    ];
    const blankChange = () => ({ field: 'End Date', neu: '' });
    const blank = {
      no: 'Amend ' + ((c.amendments || []).length + 1), type: 'end_ext', date: E.fmtDate(E.TODAY),
      letter: E.fmtDate(E.TODAY), desc: '',
      changes: [blankChange()],
    };
    const [f, setF] = useState(blank);
    useEffect(() => { if (open) setF({ ...blank, changes: [blankChange()] }); }, [open]);
    const addChange = () => setF({ ...f, changes: [...f.changes, blankChange()] });
    const removeChange = (i) => {
      if (f.changes.length <= 1) return;
      setF({ ...f, changes: f.changes.filter((_, idx) => idx !== i) });
    };
    const updateChange = (i, patch) => {
      const chgs = [...f.changes];
      chgs[i] = { ...chgs[i], ...patch };
      setF({ ...f, changes: chgs });
    };
    const oldValueFor = (field) => {
      if (field === 'End Date') return c.end;
      if (field === 'Current Contract Value') return c.cur + ' ' + E.fmtMoney(c.current, c.cur);
      if (field === 'Scope') return c.scope || '—';
      if (field === 'IO/WP&B Mapping') {
        const afops = store.afopLines.filter((a) => a.contractId === c.id && !a.deletedAt);
        return afops.map((a) => {
          const io = store.ios.find((x) => x.id === a.ioId);
          const wpb = store.wpbItems.find((w) => w.id === a.wId);
          return 'AFOP#' + a.no + ': IO ' + (io ? io.io : a.ioId) + ' · WP&B ' + (wpb ? wpb.name : a.wId);
        }).join(' | ');
      }
      return '';
    };
    const save = () => {
      const valid = f.changes.filter((ch) => ch.neu);
      if (!valid.length) { toast('Enter at least one new value', 'warn'); return; }
      const changes = valid.map((ch) => {
        const neu = ch.field === 'Current Contract Value' && !/[a-z]/i.test(ch.neu) ? (c.cur + ' ' + ch.neu) : ch.neu;
        return { field: ch.field, old: oldValueFor(ch.field), neu };
      });
      ctx.actions.addAmendment(c.id, {
        no: f.no, type: f.type, date: f.date, letter: f.letter, desc: f.desc,
        changes,
      });
      toast('Amendment ' + f.no + ' recorded — ' + changes.length + ' change(s)', 'good');
      setOpen(false);
    };
    return (<>
      <button className="btn btn-primary" onClick={() => setOpen(true)}><Icon name="plus" size={15} />New Amendment</button>
      {open && <Modal title="New Amendment" subtitle={c.no + ' · ' + c.vendor} size="wide" onClose={() => setOpen(false)}
        footer={<><button className="btn btn-secondary" onClick={() => setOpen(false)}>Cancel</button><button className="btn btn-primary" onClick={save}>Record amendment</button></>}>
        <div className="form-grid">
          <Field label="Amendment No" req><input className="input mono" value={f.no} onChange={(e) => setF({ ...f, no: e.target.value })} /></Field>
          <Field label="Amendment Type" req><Select value={f.type} onChange={(v) => setF({ ...f, type: v })} options={ctx.store.lookups.amendmentType.map((s) => ({ value: s.id, label: s.label }))} /></Field>
          <Field label="Effective Date" req><input type="date" className="input mono" value={f.date} onChange={(e) => setF({ ...f, date: e.target.value })} /></Field>
          <Field label="Confirmation Letter Date" req><input type="date" className="input mono" value={f.letter} onChange={(e) => setF({ ...f, letter: e.target.value })} /></Field>
          <Field label="Description" span><input className="input" value={f.desc} onChange={(e) => setF({ ...f, desc: e.target.value })} placeholder="What changed and why" /></Field>
          <div style={{ borderTop: '1px solid var(--border-default)', paddingTop: 14, marginTop: 4 }}>
            <div className="row" style={{ justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
              <span className="section-title" style={{ margin: 0 }}>Changes ({f.changes.length})</span>
              <button className="btn btn-secondary btn-sm" onClick={addChange}><Icon name="plus" size={14} />Add Change</button>
            </div>
            {f.changes.map((ch, i) => (
              <div key={i} className="card card-pad mb8" style={{ background: 'var(--color-slate-50)', border: '1px solid var(--border-default)' }}>
                <div className="row" style={{ justifyContent: 'space-between', marginBottom: 6 }}>
                  <span className="muted" style={{ fontSize: 11, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '.04em' }}>Change {i + 1}</span>
                  {f.changes.length > 1 && <button className="icon-btn danger" title="Remove" onClick={() => removeChange(i)}><Icon name="x" size={14} /></button>}
                </div>
                <div className="form-grid" style={{ gridTemplateColumns: '1fr 1fr' }}>
                  <Field label="Field" req>
                    <Select value={ch.field} onChange={(v) => updateChange(i, { field: v, neu: '', afopLineId: null, oldIoId: null, newIoId: null, oldWId: null, newWId: null })}
                      options={FIELD_OPTIONS} />
                  </Field>
                  <Field label="New Value" req>
                    {ch.field === 'End Date'
                      ? <input type="date" className="input mono" value={ch.neu} onChange={(e) => updateChange(i, { neu: e.target.value })} />
                      : ch.field === 'IO/WP&B Mapping'
                      ? <input className="input" value={ch.neu} onChange={(e) => updateChange(i, { neu: e.target.value })} placeholder="e.g. AFOP#2: w10→w11" />
                      : <input className="input" value={ch.neu} onChange={(e) => updateChange(i, { neu: e.target.value })} placeholder={ch.field === 'Current Contract Value' ? 'e.g. 1,300,000' : 'New value'} />}
                  </Field>
                </div>
                {ch.field === 'IO/WP&B Mapping' && (
                  <div className="form-grid" style={{ gridTemplateColumns: '1fr 1fr', marginTop: 8, paddingTop: 8, borderTop: '1px dashed var(--border-default)' }}>
                    <div>
                      <div className="field-hint mb4">Select AFOP Line to remap</div>
                      <select className="select" style={{ width: '100%', height: 30, fontSize: 12 }}
                        value={ch.afopLineId || ''}
                        onChange={(e) => {
                          const afId = e.target.value;
                          const af = store.afopLines.find((a) => a.id === afId);
                          const io = af ? store.ios.find((x) => x.id === af.ioId) : null;
                          const wpb = af ? store.wpbItems.find((w) => w.id === af.wId) : null;
                          const newNeu = af ? ('AFOP#' + af.no + ': IO ' + (io ? io.io : af.ioId) + ' · WP&B ' + (wpb ? wpb.name : af.wId) + ' → ') : '';
                          updateChange(i, { afopLineId: afId, oldIoId: af ? af.ioId : null, oldWId: af ? af.wId : null, newIoId: af ? af.ioId : null, newWId: af ? af.wId : null, neu: newNeu });
                        }}>
                        <option value="">Select AFOP line…</option>
                        {store.afopLines.filter((a) => a.contractId === c.id && !a.deletedAt).map((a) => {
                          const io = store.ios.find((x) => x.id === a.ioId);
                          const wpb = store.wpbItems.find((w) => w.id === a.wId);
                          return <option key={a.id} value={a.id}>AFOP #{a.no}: IO {io ? io.io : a.ioId} · {wpb ? wpb.name : a.wId}</option>;
                        })}
                      </select>
                    </div>
                    <div className="row" style={{ gap: 8, alignItems: 'flex-end' }}>
                      <div style={{ flex: 1 }}>
                        <div className="field-hint mb4">Current IO → New IO</div>
                        <div className="row" style={{ gap: 4, alignItems: 'center' }}>
                          <span className="mono" style={{ fontSize: 11, color: 'var(--text-muted)' }}>{(() => { const io = store.ios.find((x) => x.id === ch.oldIoId); return io ? io.io : '—'; })()}</span>
                          <span>→</span>
                          <select className="select" style={{ flex: 1, height: 30, fontSize: 12 }}
                            value={ch.newIoId || ''}
                            onChange={(e) => {
                              const ioId = e.target.value;
                              const io = store.ios.find((x) => x.id === ioId);
                              updateChange(i, { newIoId: ioId, neu: (ch.neu || '').replace(/IO .+ ·/, 'IO ' + (io ? io.io : ioId) + ' ·') });
                            }}>
                            {store.ios.map((x) => <option key={x.id} value={x.id}>{x.io} · {x.activities}</option>)}
                          </select>
                        </div>
                      </div>
                    </div>
                    <div style={{ gridColumn: '1 / -1' }}>
                      <div className="field-hint mb4">Current WP&B → New WP&B</div>
                      <div className="row" style={{ gap: 4, alignItems: 'center' }}>
                        <span className="mono" style={{ fontSize: 11, color: 'var(--text-muted)' }}>{(() => { const wpb = store.wpbItems.find((w) => w.id === ch.oldWId); return wpb ? wpb.name : '—'; })()}</span>
                        <span>→</span>
                        <select className="select" style={{ flex: 1, height: 30, fontSize: 12 }}
                          value={ch.newWId || ''}
                          onChange={(e) => {
                            const wId = e.target.value;
                            const wpb = store.wpbItems.find((w) => w.id === wId);
                            updateChange(i, { newWId: wId, neu: (ch.neu || '').replace(/WP&B .+/, 'WP&B ' + (wpb ? wpb.name : wId)) });
                          }}>
                          {store.wpbItems.map((w) => <option key={w.id} value={w.id}>{w.name}</option>)}
                        </select>
                      </div>
                    </div>
                  </div>
                )}
                <div className="field-hint mt4">Current: <span className="mono">{oldValueFor(ch.field)}</span></div>
              </div>
            ))}
          </div>
        </div>
      </Modal>}
    </>);
  }

  Object.assign(window, { DocumentsTab, AfopTab, ContractAcTab, AmendmentsTab, NewAmendmentButton, AcStatusSelect });
})();
