// ============================================================================
// Sandbox views — the five screens.
// Reads from props (state owned by sandbox-app.jsx).
// ============================================================================

// ----------------------------- BRIEFING --------------------------------------
const SXBriefing = ({ data, approvals, onJump }) => {
  const pendingCount = approvals.filter(a => a.status === 'pending').length;
  const yoursCount   = approvals.filter(a => a.status === 'pending' && a.dri && a.dri.startsWith('Tom')).length;
  return (
    <div style={{ flex: 1, padding: '24px 32px 80px', overflow: 'auto' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', marginBottom: 18, flexWrap: 'wrap', gap: 16 }}>
        <div>
          <h1 className="disp" style={{ fontSize: 42, color: 'var(--paper)', margin: 0, letterSpacing: '-0.005em' }}>MORNING BRIEFING</h1>
          <Mono style={{ fontSize: 11, color: 'var(--steel-500)', marginTop: 6, display: 'block' }}>
            AS OF {data.company.as_of} · RENDERED IN 412ms · {data.company.node_id}
          </Mono>
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          <Btn>Bonding · XLSX</Btn>
          <Btn>CSV</Btn>
          <Btn>JSON</Btn>
        </div>
      </div>

      <Tick style={{ display: 'block', marginBottom: 8 }}>KPIs · 4 green · 2 amber · 0 red</Tick>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 0, marginBottom: 24 }}>
        {data.kpis.map(k => (
          <KPI key={k.label} label={k.label}
               value={k.label === 'APPROVALS PENDING' ? String(pendingCount) : k.value}
               color={k.color}
               note={k.label === 'APPROVALS PENDING' ? `${yoursCount} awaiting Tom · live count` : k.note} />
        ))}
      </div>

      {/* Forecast */}
      <div style={{ border: '1px solid var(--line)', background: 'var(--ink-800)', padding: '18px 20px', marginBottom: 18 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 10, flexWrap: 'wrap', gap: 8 }}>
          <h2 className="disp" style={{ fontSize: 20, color: 'var(--paper)', margin: 0 }}>13-WEEK CASH FORECAST</h2>
          <Mono style={{ fontSize: 10, color: 'var(--steel-500)' }}>MIN TARGET $80K · ⨯ FLAGS WEEKS BELOW</Mono>
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
          {data.forecast.slice(0, 7).map(w => {
            const pct = Math.min(100, Math.abs(w.cents) / 220 * 100);
            return (
              <div key={w.wk} style={{ display: 'flex', alignItems: 'center', gap: 10, fontSize: 11 }}>
                <Mono style={{ width: 90, color: 'var(--steel-500)' }}>wk{w.wk} {w.date}</Mono>
                <div style={{ flex: 1, height: 18, background: 'var(--ink-700)', position: 'relative' }}>
                  <div style={{ height: 18, width: `${pct}%`, background: w.neg ? 'var(--rust)' : w.below ? 'var(--amber)' : 'var(--green)' }}/>
                </div>
                <Mono style={{ width: 90, textAlign: 'right', color: w.below ? '#F59E0B' : 'var(--paper)' }}>${w.cents}K</Mono>
                <span style={{ width: 18, color: 'var(--amber)', textAlign: 'center' }}>{w.below ? '⨯' : ''}</span>
              </div>
            );
          })}
        </div>
      </div>

      {/* Project alerts */}
      <div style={{ border: '1px solid rgba(245,158,11,0.3)', background: 'rgba(245,158,11,0.06)', padding: '14px 18px' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8 }}>
          <Dot color="var(--amber)" />
          <Mono style={{ fontSize: 11, color: '#F59E0B', letterSpacing: '0.14em', textTransform: 'uppercase' }}>PROJECT ALERTS · {data.project_alerts.length}</Mono>
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 6, fontSize: 12, color: 'var(--paper)' }}>
          {data.project_alerts.map((a, i) => (
            <div key={i}>
              <Mono style={{ color: '#F59E0B' }}>[{a.kind}]</Mono>{' '}
              <Mono>{a.job}</Mono> — {a.detail}
            </div>
          ))}
        </div>
      </div>

      <div style={{ marginTop: 28, display: 'flex', gap: 10, flexWrap: 'wrap' }}>
        <Btn kind="primary" onClick={() => onJump?.('queue')}>Open the queue · {pendingCount} pending →</Btn>
        <Btn onClick={() => onJump?.('job')}>Open JOB#41209 →</Btn>
      </div>
    </div>
  );
};

// ----------------------------- QUEUE -----------------------------------------
const SXApprovalRow = ({ a, onDecide, expanded, onToggle, tourTarget }) => {
  const stateColor = {
    pending:  'var(--line)',
    approved: 'var(--green)',
    rejected: 'var(--rust)',
    edited:   'var(--amber)',
    expired:  'var(--steel-500)',
    conflict: 'var(--rust)',
  }[a.status];
  return (
    <div data-tour-id={tourTarget} style={{
      border: '1px solid var(--line)', borderLeft: `2px solid ${stateColor}`,
      background: a.status === 'conflict' ? 'rgba(193,67,45,0.05)' : 'var(--ink-800)',
      padding: '14px 18px',
      opacity: a.status === 'rejected' || a.status === 'expired' ? 0.7 : 1,
      transition: 'opacity 200ms',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', gap: 14, alignItems: 'flex-start', flexWrap: 'wrap' }}>
        <div style={{ flex: '1 1 320px', minWidth: 0 }}>
          <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 8 }}>
            <Mono style={{ fontSize: 11, color: 'var(--steel-500)' }}>#{a.id}</Mono>
            <span style={{ fontWeight: 600, color: 'var(--paper)' }}>{a.kind}</span>
            <TierTag tier={a.tier} />
            <DeptTag>{a.department}</DeptTag>
            {a._sandbox && (
              <span style={{
                background: 'rgba(59,130,246,0.10)', color: 'var(--signal)',
                border: '1px solid rgba(59,130,246,0.4)',
                padding: '2px 8px', fontFamily: 'var(--font-mono)',
                fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.10em',
              }}>Drafted this session</span>
            )}
            {a.status !== 'pending' && <StatusStamp status={a.status} />}
            {a.status === 'pending' && a.dri && (
              <span style={{
                background: 'rgba(245,158,11,0.10)', color: '#F59E0B',
                border: '1px solid rgba(245,158,11,0.3)',
                padding: '2px 8px', fontFamily: 'var(--font-mono)',
                fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.10em',
              }}>Awaiting {a.dri}</span>
            )}
          </div>
          <div style={{
            fontSize: 13, color: 'var(--paper)', marginTop: 6,
            textDecoration: (a.status === 'rejected' || a.status === 'expired') ? 'line-through' : 'none',
            textDecorationColor: 'rgba(232,237,243,0.35)',
          }}>{a.summary}</div>
          <Mono style={{ fontSize: 10, color: 'var(--steel-500)', marginTop: 6, display: 'block' }}>
            amount: {a.amount} · created_by: {a.created_by} · {a.at}
          </Mono>
        </div>
        {a.status === 'pending' && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
            <Btn kind="approve" onClick={() => onDecide?.(a.id, 'approved')}>Approve</Btn>
            <Btn kind="reject"  onClick={() => onDecide?.(a.id, 'rejected')}>Reject</Btn>
            <Btn kind="edit"    onClick={onToggle}>{expanded ? 'Close' : 'Edit'}</Btn>
          </div>
        )}
      </div>

      {a.match && (
        <div style={{ marginTop: 10, border: '1px solid var(--line)', padding: '8px 10px', background: 'var(--ink-900)' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }}>
            <Mono style={{ fontSize: 10, color: 'var(--paper)', letterSpacing: '0.12em', textTransform: 'uppercase' }}>3-way match</Mono>
            <span style={{
              background: a.match.ok ? 'rgba(34,197,94,0.15)' : 'rgba(193,67,45,0.18)',
              color: a.match.ok ? '#22C55E' : '#E47862',
              padding: '2px 8px', fontFamily: 'var(--font-mono)', fontSize: 10,
              textTransform: 'uppercase', letterSpacing: '0.10em',
            }}>{a.match.ok ? 'matched' : 'variance'}</span>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 10, textAlign: 'center' }}>
            {[['PO', a.match.po], ['Received', a.match.recv], ['Billed', a.match.bill]].map(([l, v]) => (
              <div key={l}>
                <Mono style={{ fontSize: 9, color: 'var(--steel-500)', letterSpacing: '0.16em', textTransform: 'uppercase' }}>{l}</Mono>
                <div><Mono style={{ fontSize: 13, color: 'var(--paper)' }}>{v}</Mono></div>
              </div>
            ))}
          </div>
        </div>
      )}

      {expanded && (
        <div style={{ marginTop: 10, padding: 10, background: 'var(--ink-900)', border: '1px solid var(--line)' }}>
          <Tick size={9}>Edit payload — re-validated server-side</Tick>
          <pre style={{
            margin: '6px 0 0', background: 'transparent', color: 'var(--paper)',
            fontFamily: 'var(--font-mono)', fontSize: 11, lineHeight: 1.5,
            whiteSpace: 'pre-wrap', wordBreak: 'break-word',
          }}>{JSON.stringify(a.payload, null, 2)}</pre>
          <div style={{ display: 'flex', gap: 6, marginTop: 10 }}>
            <Btn kind="approve" onClick={() => onDecide?.(a.id, 'edited')}>Save & approve</Btn>
            <Btn onClick={onToggle}>Cancel</Btn>
          </div>
        </div>
      )}
    </div>
  );
};

const SXQueue = ({ data, approvals, onDecide, expanded, setExpanded }) => {
  const [filter, setFilter] = React.useState('all'); // all | mine | done
  const filtered = approvals.filter(a => {
    if (filter === 'mine') return a.status === 'pending' && a.dri && a.dri.startsWith('Tom');
    if (filter === 'done') return a.status !== 'pending';
    return true;
  });
  return (
    <div style={{ flex: 1, padding: '24px 32px 80px', overflow: 'auto' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', marginBottom: 18, flexWrap: 'wrap', gap: 16 }}>
        <div>
          <h1 className="disp" style={{ fontSize: 42, color: 'var(--paper)', margin: 0 }}>APPROVAL QUEUE</h1>
          <Mono style={{ fontSize: 11, color: 'var(--steel-500)', marginTop: 6, display: 'block' }}>
            {approvals.filter(a => a.status === 'pending').length} PENDING · {approvals.filter(a => a.status === 'pending' && a.dri && a.dri.startsWith('Tom')).length} AWAITING YOU · {data.company.node_id}
          </Mono>
        </div>
        <div style={{ display: 'flex', gap: 6 }}>
          <Btn kind={filter === 'all'  ? 'primary' : 'ghost'} onClick={() => setFilter('all')}>All</Btn>
          <Btn kind={filter === 'mine' ? 'primary' : 'ghost'} onClick={() => setFilter('mine')}>Awaiting me</Btn>
          <Btn kind={filter === 'done' ? 'primary' : 'ghost'} onClick={() => setFilter('done')}>Decided</Btn>
        </div>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {filtered.length === 0 ? (
          <div style={{ padding: 40, textAlign: 'center', border: '1px solid var(--line)', background: 'var(--ink-800)' }}>
            <Tick>Queue empty for this filter</Tick>
            <div className="disp" style={{ fontSize: 32, color: 'var(--paper)', marginTop: 10 }}>ALL CLEAR.</div>
          </div>
        ) : filtered.map((a, i) => (
          <SXApprovalRow key={a.id} a={a}
            tourTarget={i === 0 ? 'first-row' : null}
            expanded={expanded === a.id}
            onToggle={() => setExpanded(e => e === a.id ? null : a.id)}
            onDecide={onDecide} />
        ))}
      </div>
    </div>
  );
};

// ----------------------------- JOB DETAIL ------------------------------------
const SXJobDetail = ({ data }) => {
  const job = data.job;
  return (
    <div style={{ flex: 1, padding: '24px 32px 80px', overflow: 'auto' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 8, flexWrap: 'wrap', gap: 16 }}>
        <div>
          <Mono style={{ fontSize: 11, color: 'var(--steel-500)', letterSpacing: '0.18em', display: 'block', marginBottom: 4 }}>{job.code} · {job.customer}</Mono>
          <h1 className="disp" style={{ fontSize: 38, color: 'var(--paper)', margin: 0 }}>{job.name.toUpperCase()}</h1>
        </div>
        <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
          <Stamp color="var(--green)">{job.status}</Stamp>
          <Stamp color="var(--paper)">PHASE {job.phase}</Stamp>
        </div>
      </div>
      <Mono style={{ fontSize: 11, color: 'var(--steel-500)', marginBottom: 18, display: 'block' }}>
        START {job.start} · TARGET {job.target} · PM {job.pm} · CONTRACT {fmtUSD(job.contract_now_cents)} (WAS {fmtUSD(job.contract_was_cents)})
      </Mono>

      <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 14 }}>
        <div>
          <Tick style={{ display: 'block', marginBottom: 8 }}>BUDGET vs ACTUAL · BY PHASE</Tick>
          <div style={{ border: '1px solid var(--line)', background: 'var(--ink-800)' }}>
            {job.budget_lines.map(line => {
              const pct = Math.round(line.actual / line.budget * 100);
              const color = line.status === 'amber' ? 'var(--amber)' : 'var(--green)';
              return (
                <div key={line.name} style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '10px 14px', borderBottom: '1px solid var(--line)' }}>
                  <span style={{ width: 170, color: 'var(--paper)', fontSize: 13 }}>{line.name}</span>
                  <div style={{ flex: 1, height: 6, background: 'var(--ink-700)', position: 'relative' }}>
                    <div style={{ height: 6, width: `${Math.min(pct, 100)}%`, background: color }}/>
                  </div>
                  <Mono style={{ width: 90, textAlign: 'right', color: 'var(--paper)', fontSize: 12 }}>{fmtUSD(line.actual * 100)}</Mono>
                  <Mono style={{ width: 60, textAlign: 'right', color: 'var(--steel-500)', fontSize: 11 }}>/ {pct}%</Mono>
                </div>
              );
            })}
          </div>

          <Tick style={{ display: 'block', marginTop: 18, marginBottom: 8 }}>RECENT ACTIVITY</Tick>
          <div style={{ border: '1px solid var(--line)', background: 'var(--ink-800)' }}>
            {job.activity.map((row, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '8px 14px', borderBottom: '1px solid var(--line)' }}>
                <Mono style={{ width: 48, color: 'var(--steel-500)', fontSize: 11 }}>{row.t}</Mono>
                <Mono style={{
                  width: 64, fontSize: 10, letterSpacing: '0.12em', textTransform: 'uppercase',
                  color: row.kind === 'approve' ? 'var(--green)' : row.kind === 'sync' ? 'var(--signal)' : 'var(--paper-dim)',
                }}>{row.kind}</Mono>
                <span style={{ flex: 1, color: 'var(--paper)', fontSize: 12 }}>{row.d}</span>
              </div>
            ))}
          </div>
        </div>

        <div>
          <Tick style={{ display: 'block', marginBottom: 8 }}>FINANCIALS</Tick>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 0 }}>
            <KPI label="CONTRACT"     value={fmtUSD(job.contract_now_cents) } color="green" />
            <KPI label="BILLED MTD"   value={fmtUSD(job.billed_to_date_cents)} color="green" />
            <KPI label="COST TO DATE" value={fmtUSD(job.cost_to_date_cents)} color="amber" note={`vs budget ${fmtUSD(job.budget_cents)}`} />
            <KPI label="RETENTION"    value={fmtUSD(job.retention_cents)}    color="green" note={`${job.retention_pct}% withheld`} />
          </div>

          <Tick style={{ display: 'block', marginTop: 18, marginBottom: 8 }}>TEAM</Tick>
          <div style={{ border: '1px solid var(--line)', background: 'var(--ink-800)', padding: '10px 14px', display: 'flex', flexDirection: 'column', gap: 8 }}>
            {[['PM', job.pm], ['SUPER', job.super], ['EST', job.estimator], ['ACCT', job.accountant]].map(([r, n]) => (
              <div key={r} style={{ display: 'flex', justifyContent: 'space-between' }}>
                <Mono style={{ fontSize: 10, color: 'var(--steel-500)', letterSpacing: '0.12em' }}>{r}</Mono>
                <span style={{ fontSize: 12, color: 'var(--paper)' }}>{n}</span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
};

// ----------------------------- FIELD ----------------------------------------
// Tablet/phone-style queue for the PM in the truck. Single column, big buttons.
const SXField = ({ approvals, onDecide }) => {
  const mine = approvals.filter(a =>
    a.status === 'pending' && (
      (a.dri && a.dri.includes('M. Reyes')) || a.department === 'pm'
    )
  );
  const pending = approvals.filter(a => a.status === 'pending').length;

  return (
    <div style={{ flex: 1, padding: '24px 32px 80px', overflow: 'auto' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', marginBottom: 18, flexWrap: 'wrap', gap: 16 }}>
        <div>
          <Mono style={{ fontSize: 11, color: 'var(--steel-500)', letterSpacing: '0.18em', display: 'block', marginBottom: 4 }}>
            FIELD · iPad · M. REYES (PM)
          </Mono>
          <h1 className="disp" style={{ fontSize: 42, color: 'var(--paper)', margin: 0 }}>
            {mine.length === 0 ? 'CAUGHT UP.' : `${mine.length} TO SIGN.`}
          </h1>
          <Mono style={{ fontSize: 11, color: 'var(--steel-500)', marginTop: 6, display: 'block' }}>
            ROUTED TO ME · {pending} OPEN ACROSS ALL DEPTS · OFFLINE-CAPABLE
          </Mono>
        </div>
        <Stamp color="var(--green)">{'NODE LIVE'}</Stamp>
      </div>

      {mine.length === 0 ? (
        <div style={{ padding: 40, background: 'var(--ink-800)', border: '1px solid var(--line)', textAlign: 'center' }}>
          <div className="disp" style={{ fontSize: 28, color: 'var(--paper)' }}>NOTHING ROUTED TO YOU.</div>
          <Mono style={{ fontSize: 10, color: 'var(--steel-500)', display: 'block', marginTop: 10, letterSpacing: '0.14em' }}>
            TIP · DRAFT A CO OR WO AND IT WILL LAND HERE
          </Mono>
        </div>
      ) : (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(380px, 1fr))', gap: 14 }}>
          {mine.map(a => (
            <div key={a.id} style={{ background: 'var(--ink-800)', border: '1px solid var(--line)', borderLeft: '3px solid var(--signal)', padding: 18 }}>
              <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 8 }}>
                <Mono style={{ fontSize: 10, color: 'var(--steel-500)' }}>#{a.id} · {a.at}</Mono>
                <TierTag tier={a.tier} />
                <DeptTag>{a.kind.replace(/_/g, ' ')}</DeptTag>
              </div>
              <div style={{ fontSize: 15, color: 'var(--paper)', margin: '6px 0 10px', lineHeight: 1.4 }}>{a.summary}</div>
              <Mono style={{ fontSize: 12, color: 'var(--paper-dim)', display: 'block', marginBottom: 14 }}>
                amount: {a.amount}
              </Mono>
              <div style={{ display: 'flex', gap: 8 }}>
                <Btn kind="approve" onClick={() => onDecide?.(a.id, 'approved')} style={{ flex: 1, padding: '12px 14px', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', fontFamily: 'var(--font-mono)' }}>✓ APPROVE</Btn>
                <Btn onClick={() => {}} style={{ flex: 1, padding: '12px 14px', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', fontFamily: 'var(--font-mono)' }}>EDIT</Btn>
                <Btn kind="reject" onClick={() => onDecide?.(a.id, 'rejected')} style={{ flex: 1, padding: '12px 14px', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', fontFamily: 'var(--font-mono)' }}>× REJECT</Btn>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

// ----------------------------- AUDIT LOG -------------------------------------
const SXAudit = ({ audit }) => (
  <div style={{ flex: 1, padding: '24px 32px 80px', overflow: 'auto' }}>
    <h1 className="disp" style={{ fontSize: 42, color: 'var(--paper)', margin: 0 }}>AUDIT LOG</h1>
    <Mono style={{ fontSize: 11, color: 'var(--steel-500)', marginTop: 6, display: 'block', marginBottom: 18 }}>
      APPEND-ONLY · UPDATE/DELETE BLOCKED BY DB TRIGGER · {audit.length} ROWS IN VIEW
    </Mono>
    <div style={{ border: '1px solid var(--line)', background: 'var(--ink-800)' }}>
      {audit.map((row, i) => (
        <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '8px 14px', borderBottom: i === audit.length - 1 ? 0 : '1px solid var(--line)' }}>
          <Mono style={{ width: 90, color: 'var(--steel-500)', fontSize: 10 }}>{row.at}</Mono>
          <Mono style={{
            width: 110, fontSize: 10, letterSpacing: '0.10em', textTransform: 'uppercase',
            color: row.kind.startsWith('approve') ? 'var(--green)'
                 : row.kind.startsWith('reject')  ? 'var(--rust)'
                 : row.kind.startsWith('agent')   ? 'var(--signal)'
                 : 'var(--paper-dim)',
          }}>{row.kind}</Mono>
          <Mono style={{ width: 150, color: 'var(--paper-dim)', fontSize: 10 }}>{row.actor}</Mono>
          <span style={{ flex: 1, color: 'var(--paper)', fontSize: 12, minWidth: 0 }}>{row.msg}</span>
        </div>
      ))}
    </div>
  </div>
);

Object.assign(window, { SXBriefing, SXQueue, SXJobDetail, SXField, SXAudit, SXApprovalRow });
