/* Close worklist — the Close Chain as prepared decisions (2026 shadow) */
const { useState: cwS } = React;

function whatIDid(r) {
  const c = r.close; const done = []; const stopped = [];
  if (c.worksheet && c.worksheet.parse !== 'failed') done.push('found the returned client selection'); else if (c.worksheet) stopped.push('could not read the worksheet layout');
  if (c.lock) done.push('matched the authoritative AmRisk lock'); else stopped.push('have not received the AmRisk lock yet');
  if (c.rows.length) done.push('parsed ' + c.rows.length + ' coverage lines');
  const bad = c.rows.filter((x) => ['exact', 'corrected'].indexOf(x.st) < 0);
  const unmapped = bad.filter((x) => x.st === 'map').length;
  const mismatch = bad.filter((x) => x.st === 'mismatch').length;
  if (c.rows.length && !unmapped) done.push('mapped every risk code');
  if (unmapped) stopped.push('could not map ' + unmapped + ' coverage label' + (unmapped > 1 ? 's' : '') + ' to a confirmed risk code');
  if (c.rows.length && !mismatch) done.push('reconciled every premium against the lock');
  if (mismatch) stopped.push('found ' + mismatch + ' premium that does not match the locked selection');
  if (c.approved) done.push('recorded the approved grid for comparison');
  if (c.billing && c.billing.invoice === 'Observed') done.push('observed the manually recorded invoice');
  if (c.receipt && c.receipt.match === 'confirmed') done.push('closed the payment condition on the confirmed receipt');
  if (c.receipt && c.receipt.match === 'ambiguous') stopped.push('found a receipt that matches two renewals equally well');
  return { done, stopped };
}

function CloseCard({ r, kind }) {
  const app = useApp(); const c = r.close; const AG = window.AG;
  const [open, setOpen] = cwS(null);
  const [done, setDone] = cwS(null);
  const w = whatIDid(r);
  const a = AG.advOf(r);
  const total = c.rows.reduce((s, x) => s + (x.lk || 0), 0);
  const tone = kind === 'blocked' ? 'blocked' : kind === 'prepared' ? 'today' : kind === 'cleared' ? 'week' : '';
  const verb = kind === 'prepared' ? 'Approve the prepared coverage grid'
    : kind === 'blocked' ? (c.worksheet && c.worksheet.parse === 'failed' ? 'Decide how to read an unsupported worksheet' : c.receipt && c.receipt.match === 'ambiguous' ? 'Decide which renewal the payment belongs to' : 'Resolve ' + c.rows.filter((x) => ['exact', 'corrected'].indexOf(x.st) < 0).length + ' unreconciled coverage lines')
      : kind === 'cleared' ? (gateOpen(c.gates) ? 'Release eligible — no action taken' : CLOSE_LABEL[c.state]) : CLOSE_LABEL[c.state];
  const resolveLabel = () => resolveKind === 'grid' ? 'Review and approve grid' : resolveKind === 'receipt' ? 'Confirm match' : resolveKind === 'parse' ? 'Decide how to proceed' : 'Resolve exception';
  const resolveKind = kind === 'prepared' ? 'grid' : (c.receipt && c.receipt.match === 'ambiguous') ? 'receipt' : (!c.rows.length || (c.worksheet && c.worksheet.parse === 'failed')) ? 'parse' : 'verify';
  return <div className={'dcard ' + tone}>
    <div className="acc" />
    <div className="grow" style={{ minWidth: 0 }}>
      <div style={{ display: 'flex' }}>
        <div className="dcard-b">
          <div className="dcard-h"><span className="who">{r.account}</span><span className="meta">{a ? a.name : 'no advisor'} · {r.policy} · {r.stage}</span></div>
          <div className="verb">{verb}</div>
          <div className="body">
            {w.done.length ? <><b>What I did.</b> I {w.done.join(', ')}. </> : null}
            {w.stopped.length ? <><b>Where I stopped.</b> I {w.stopped.join(', and ')} — so I staged nothing further.</> : null}
          </div>
          <div className="dsig">
            <span className={'cf ' + (kind === 'blocked' ? 'blocked' : 'high')}><i className="cd" />{kind === 'blocked' ? 'Not determinable by me' : kind === 'prepared' ? 'High confidence' : 'Handled'}</span>
            <span className="dot">·</span>
            <span>Expected: <b>{kind === 'prepared' ? 'clear the grid for comparison' : kind === 'blocked' ? 'human clarification required' : kind === 'monitor' ? 'awaiting an external party' : 'shadow evidence complete'}</b></span>
          </div>
          <div className="dcard-chips">
            {c.rows.length ? <span className="chip"><i className="cd" />{c.rows.length} coverages · {money(total)}</span> : null}
            <span className={'chip ' + (c.lock ? 'green' : 'amber')}><i className="cd" />{c.lock ? 'AmRisk lock received' : 'awaiting AmRisk lock'}</span>
            <span className="chip"><i className="cd" />{c.billing.funding === 'Unknown' ? 'funding choice unknown' : c.billing.funding.toLowerCase()}</span>
            <span className={'chip ' + (gateOpen(c.gates) ? 'green' : '')}><i className="cd" />{gateOpen(c.gates) ? 'release eligible' : 'gate blocked'}</span>
            <span className="chip amber"><i className="cd" />2026 shadow</span>
          </div>
        </div>
        <div className="dcard-r">
          <span className={'when' + (kind === 'blocked' || kind === 'prepared' ? ' now' : '')}>{kind === 'prepared' ? 'Act today' : kind === 'blocked' ? 'Blocked' : kind === 'monitor' ? 'Monitoring' : 'Cleared'}</span>
          <AutoTag v={kind === 'prepared' ? 'prepared' : kind === 'blocked' ? 'blocked' : kind === 'cleared' ? 'handled' : 'monitor'} />
          <button className="reasoning-link" onClick={() => setOpen(open === 'gate' ? null : 'gate')}>{open === 'gate' ? 'Hide readiness' : 'Release readiness'}<Icon n={open === 'gate' ? 'chevron-up' : 'arrow-right'} s={13} /></button>
        </div>
      </div>
      {open === 'gate' ? <div className="rpanel">
        <div className="row" style={{ marginBottom: 11 }}><span className="eyebrow">Would this be eligible to proceed at cutover?</span><span className="grow" /><span className="pill t-amber">Computed only — Phase One releases nothing</span></div>
        <div className="rgrid">
          {[['Coverage grid', c.gates.grid], ['Policy record', c.gates.policy], ['Billing', c.gates.billing], ['Receipt', c.gates.receipt], ['Exceptions', c.gates.exceptions]].map((x) => <div key={x[0]}>
            <span className="l">{x[0]}</span>
            <span className="v row" style={{ gap: 6 }}>
              <Icon n={['approved', 'exists', 'valid', 'confirmed', 'clear'].indexOf(x[1]) >= 0 ? 'check' : 'x'} s={13} style={{ color: ['approved', 'exists', 'valid', 'confirmed', 'clear'].indexOf(x[1]) >= 0 ? 'var(--green-deep)' : 'var(--red-deep)' }} />
              {x[1] === 'expected-later' ? 'Expected later' : x[1][0].toUpperCase() + x[1].slice(1)}
            </span>
          </div>)}
        </div>
        <div className="rconc"><b>{gateOpen(c.gates) ? 'Release eligible.' : 'Blocked.'}</b> {gateOpen(c.gates) ? 'Every gate is satisfied, so this renewal would be eligible to proceed if the production workflow were live. In the 2026 cycle that produces no policy action — the eligibility is recorded and compared.' : gateReason(c.gates) + ' Policy record state is reported rather than assumed, because whether the record already exists or is created later is still unresolved.'}</div>
        {c.recon ? <div className="rconc" style={{ borderLeftColor: 'var(--line-strong)', marginTop: 9 }}><b>Against Madison's manual process.</b> {c.recon.coverageMatch === 'exact' ? 'Identical coverage, risk codes, and premium totals. Engine grid was ready ' + Math.abs(Math.round((new Date(c.recon.manualDoneAt) - new Date(c.recon.engineReadyAt)) / window.MD.DAY)) + ' days before the manual entry completed.' : c.recon.discrepancies.length + ' differences: ' + c.recon.discrepancies.map((d) => d.field + ' (engine ' + d.engine + ' vs manual ' + d.manual + ')').join('; ') + '.'}</div> : null}
      </div> : null}
      {open === 'resolve' ? <ResolvePanel kind={resolveKind} d={{ renewal: r.id, id: resolveKind === 'grid' ? 'DEC-4' : resolveKind === 'receipt' ? 'DEC-3' : 'DEC-6' }} onDone={(m) => { setDone(m); setOpen(null); }} /> : null}
      <div className="dbar">
        {done ? <><span className="decided approved"><Icon n="check" s={15} />{done}</span><span className="note">Recorded by {app.user.name}</span></>
          : kind === 'cleared' ? <><span className="decided approved"><Icon n="check" s={15} />{gateOpen(c.gates) ? 'Release eligible · recorded, nothing released' : 'Grid approved · comparison recorded'}</span><span className="note">{c.approved ? 'Approved by ' + c.approved.by + ' · ' + dt(c.approved.at, false) : ''}</span></>
            : kind === 'monitor' ? <><span className="decided held"><Icon n="clock" s={15} />Waiting on {c.lock ? (c.billing.financing === 'Signature pending' ? 'the client signature' : 'the client') : 'AmRisk'}</span><span className="note">No action would add anything today. I re-evaluate at 14:00.</span></>
              : <>
                <Gated action={resolveKind === 'grid' ? 'approve' : resolveKind === 'receipt' ? 'receipt' : 'map'} label={resolveKind === 'grid' ? 'Approve shadow grid' : resolveKind === 'receipt' ? 'Confirm match' : 'Resolve exception'}>
                  <button className="btn p" onClick={() => setOpen(open === 'resolve' ? null : 'resolve')}>{resolveLabel()}</button>
                </Gated>
                <button className="btn" onClick={() => app.nav('#/renewal/' + r.id)}>Open briefing</button>
                <span className="note">{kind === 'blocked' ? 'I will not guess between the options — a person decides.' : 'Approval records a comparison. No production write occurs.'}</span>
              </>}
      </div>
    </div>
  </div>;
}

function CloseScreen() {
  const app = useApp(); const MD = window.MD; const cy = MD.cycle;
  const inClose = MD.renewals.filter((r) => r.close);
  const bad = (r) => r.close.rows.filter((x) => ['exact', 'corrected'].indexOf(x.st) < 0).length || (r.close.worksheet && r.close.worksheet.parse === 'failed') || (r.close.receipt && r.close.receipt.match === 'ambiguous');
  const blocked = inClose.filter((r) => bad(r));
  const prepared = inClose.filter((r) => !bad(r) && r.close.state === 'GRID_STAGED');
  const cleared = inClose.filter((r) => !bad(r) && CLOSE_STATES.indexOf(r.close.state) >= CLOSE_STATES.indexOf('GRID_APPROVED'));
  const monitor = inClose.filter((r) => !bad(r) && prepared.indexOf(r) < 0 && cleared.indexOf(r) < 0);
  return <div className="ag-canvas">
    <div className="ph"><div className="ph-row"><div className="grow">
      <h1>Close worklist</h1>
      <p className="sub">I watch for returned selections, pair them with the AmRisk lock, parse and reconcile the coverage, and stage the grid. <b>{prepared.length} decision{prepared.length === 1 ? '' : 's'} prepared, {blocked.length} where I stopped</b>, and {cleared.length} already cleared this cycle. Nothing here writes to production.</p>
    </div><span className="ph-badge" style={{ background: 'var(--tint-amber)', borderColor: 'rgba(231,152,0,.28)', color: 'var(--amber-deep)' }}><Icon n="lock" s={14} />2026 shadow</span></div></div>

    <div className="note amber" style={{ marginBottom: 26 }}><Icon n="alert" s={15} /><span><b>2026 shadow cycle.</b> I stage and compare. No production policy, coverage, invoice, or release write happens anywhere in this section — approving a grid records a comparison, and opening a release gate records eligibility. Cutover is a 2027 decision based on this evidence.</span></div>

    {prepared.length ? <div className="secwrap">
      <div className="sec"><span className="st">Prepared coverage decisions</span><span className="sn">{prepared.length}</span><span className="snote">Everything reconciles — one approval each</span></div>
      {prepared.map((r) => <CloseCard key={r.id} r={r} kind="prepared" />)}
    </div> : null}

    {blocked.length ? <div className="secwrap">
      <div className="sec"><span className="st">Where I stopped</span><span className="sn">{blocked.length}</span><span className="snote">I could not safely determine these</span></div>
      {blocked.map((r) => <CloseCard key={r.id} r={r} kind="blocked" />)}
    </div> : null}

    {monitor.length ? <div className="secwrap">
      <div className="sec"><span className="st">Waiting on someone else</span><span className="sn">{monitor.length}</span><span className="snote">Watched, not chased</span></div>
      {monitor.map((r) => <CloseCard key={r.id} r={r} kind="monitor" />)}
    </div> : null}

    {cleared.length ? <div className="secwrap">
      <div className="sec"><span className="st">Cleared</span><span className="sn">{cleared.length}</span><span className="snote">Approved, confirmed, or eligible — recorded only</span></div>
      {cleared.map((r) => <CloseCard key={r.id} r={r} kind="cleared" />)}
    </div> : null}

    <div className="secwrap">
      <div className="sec"><span className="st">Cutover evidence</span><span className="snote">What the shadow cycle has proven so far</span></div>
      <div className="profile-strip">
        <div className="ps-cell"><div className="ps-l">Renewals staged</div><div className="ps-v">{cy.staged}</div></div>
        <div className="ps-cell"><div className="ps-l">Exact match</div><div className="ps-v" style={{ color: 'var(--green-deep)' }}>{Math.round((cy.exact / cy.staged) * 100)}%</div></div>
        <div className="ps-cell"><div className="ps-l">With discrepancy</div><div className="ps-v" style={{ color: 'var(--red-deep)' }}>{cy.discrepancy}</div></div>
        <div className="ps-cell"><div className="ps-l">Unresolved</div><div className="ps-v">{cy.unresolved}</div></div>
        <div className="ps-cell"><div className="ps-l">My grid ready</div><div className="ps-v">{cy.engineReadyAvg}d</div></div>
        <div className="ps-cell"><div className="ps-l">Manual completion</div><div className="ps-v">{cy.manualDoneAvg}d</div></div>
      </div>
      <div className="signals" style={{ marginTop: 12 }}>
        {[['Parse error', cy.parseErr], ['Coverage mapping error', cy.mapErr], ['Manual entry error', cy.manualErr], ['Timing difference', cy.timing]].map((x) => <div className="sig" key={x[0]}>
          <div className="row"><span className="sname">{x[0]}</span><span className="grow" /><span style={{ fontSize: 19, fontWeight: 600 }}>{x[1]}</span></div>
          <div className="smeta">classified this cycle</div>
        </div>)}
      </div>
      <div className="note" style={{ marginTop: 12 }}><Icon n="info" s={15} style={{ color: 'var(--text-muted)' }} /><span>Timing is recorded, not celebrated: a faster staged grid only matters if coverage identity, risk codes, and premium reconcile exactly. A discrepancy may stay unclassified — I never force a category to clear a queue.</span></div>
    </div>

    <div className="secwrap">
      <div className="sec"><span className="st">Coverage mapping registry</span><span className="snote">Versioned, reviewed — an unknown label never becomes a coverage record</span></div>
      <div className="btbl-wrap">
        <table className="btbl">
          <thead><tr><th>Coverage</th><th>Recognized aliases</th><th>Risk code</th><th>Version</th><th>Status</th><th>Last reviewed</th></tr></thead>
          <tbody>{MD.mappings.map((m) => <tr key={m.coverage} style={{ cursor: 'default' }}>
            <td><b>{m.coverage}</b></td>
            <td className="mut"><span className="trunc" style={{ maxWidth: 250, display: 'block' }}>{m.aliases}</span></td>
            <td className="mono">{m.code || '—'}</td>
            <td className="mono mut">{m.ver}</td>
            <td>{m.status === 'Active' ? <span className="pill t-green">Active</span> : <span className="pill t-amber"><Icon n="alert" s={10} />Unmapped</span>}</td>
            <td className="mut">{m.reviewed ? dt(m.reviewed, false) : '—'}</td>
          </tr>)}</tbody>
        </table>
      </div>
    </div>
  </div>;
}

Object.assign(window, { CloseScreen, CloseCard, whatIDid });
