// screens-ops.jsx — Ops: Rook's side of the counter (desktop only)
//
// The customer app answers "what can I buy?". This answers the questions Rook
// actually has on a Sunday night: who ordered what, do I have the packs, what's
// the route, and which collections should I be buying. Numbers here are driven
// by the same helpers the storefront uses, so pricing never drifts between the
// two views.

/* ───────────── small presentational pieces ───────────── */

function OpsStat({ label, value, sub, tone }) {
  const color = tone === 'accent' ? 'var(--accent)' : tone === 'good' ? 'var(--good)' : tone === 'gold' ? 'var(--gold)' : 'var(--ink)';
  return (
    <div className="card hairline ops-stat">
      <div className="kicker">{label}</div>
      <div style={{ fontFamily: 'var(--ff-display)', fontWeight: 800, fontSize: 30, letterSpacing: '-0.025em', lineHeight: 1, marginTop: 8, color }}>{value}</div>
      {sub && <div className="muted" style={{ fontSize: 12, marginTop: 6, fontFamily: 'var(--ff-mono)' }}>{sub}</div>}
    </div>
  );
}

function OpsPanel({ title, kicker, action, children, wide = false }) {
  return (
    <section className={'card hairline ops-panel' + (wide ? ' ops-panel-wide' : '')}>
      <header className="ops-panel-hd">
        <div>
          {kicker && <div className="kicker" style={{ marginBottom: 5 }}>{kicker}</div>}
          <h2 style={{ fontFamily: 'var(--ff-display)', fontWeight: 800, fontSize: 19, letterSpacing: '-0.02em', margin: 0 }}>{title}</h2>
        </div>
        {action}
      </header>
      {children}
    </section>
  );
}

/* ───────────── order book ───────────── */

function OpsOrderBook({ t, day, setDay }) {
  const rows = OPS_ORDERS.filter(o => day === 'all' || o.day === day);
  const zoneName = (id) => (NEIGHBORHOODS.find(n => n.id === id) || {}).name || id;

  return (
    <OpsPanel kicker="Open drop · closes Sun 8 PM" title="Order book" wide
      action={
        <div className="subtabs ops-daytabs">
          {[{ id: 'all', day: 'All' }].concat(DELIVERY_DAYS).map(d => (
            <button key={d.id} className={'subtab' + (day === d.id ? ' on' : '')} onClick={() => setDay(d.id)}>{d.day}</button>
          ))}
        </div>
      }>
      <div className="ops-tablewrap">
        <table className="ops-table">
          <thead>
            <tr>
              <th>Order</th><th>Customer</th><th>Zone</th><th>Day</th>
              <th className="num">Packs</th><th className="num">Total</th><th>Status</th>
            </tr>
          </thead>
          <tbody>
            {rows.map(o => {
              const packs = opsOrderPacks(o);
              return (
                <tr key={o.id}>
                  <td className="mono">{o.id}</td>
                  <td style={{ fontWeight: 600 }}>{o.who}</td>
                  <td className="muted">{zoneName(o.zone)}</td>
                  <td className="mono">{(DELIVERY_DAYS.find(d => d.id === o.day) || {}).day}</td>
                  <td className="num mono" style={{ fontWeight: 700 }}>{packs}</td>
                  <td className="num mono" style={{ fontWeight: 700 }}>{money(opsOrderTotal(o, t.markup))}</td>
                  <td>
                    <span className={'badge ' + (o.paid ? 'badge-good' : 'badge-low')}>{o.paid ? 'Paid' : 'Unpaid'}</span>
                  </td>
                </tr>
              );
            })}
            {rows.length === 0 && (
              <tr><td colSpan={7} className="muted" style={{ textAlign: 'center', padding: '22px 0' }}>No orders on this day yet.</td></tr>
            )}
          </tbody>
        </table>
      </div>
    </OpsPanel>
  );
}

/* ───────────── pick list ───────────── */
// Committed packs vs packs on the shelf. Negative headroom is the thing that
// ruins a delivery day, so it leads.

function OpsPickList() {
  const rows = opsPickList();
  const shortfall = rows.filter(r => r.need > r.stock);
  return (
    <OpsPanel kicker="Before Tuesday" title="Pick list"
      action={shortfall.length > 0
        ? <span className="badge badge-accent">{shortfall.length} short</span>
        : <span className="badge badge-good">All covered</span>}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {rows.map(({ set, need, stock }) => {
          const short = need > stock;
          const pct = Math.min(100, (need / Math.max(stock, need)) * 100);
          return (
            <div key={set.id} style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
              {/* a swatch, not a PackArt — the pack's name label overflows at thumbnail size */}
              <div style={{
                width: 30, height: 40, borderRadius: 7, flexShrink: 0,
                background: `linear-gradient(150deg, ${set.c1}, ${set.c2})`,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                boxShadow: 'inset 0 0 0 1px rgba(0,0,0,0.12)',
              }}>
                <Icon name={set.icon} size={15} color="rgba(255,255,255,0.92)" />
              </div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 8 }}>
                  <span style={{ fontWeight: 700, fontSize: 13.5, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{set.name}</span>
                  <span className="mono" style={{ fontSize: 12, fontWeight: 700, color: short ? 'var(--accent)' : 'var(--ink-2)', flexShrink: 0 }}>
                    {need} / {stock}
                  </span>
                </div>
                <div className="track" style={{ height: 6, marginTop: 5 }}>
                  <span style={{ width: pct + '%', background: short ? 'var(--accent)' : 'var(--good)' }} />
                </div>
              </div>
            </div>
          );
        })}
      </div>
      {shortfall.length > 0 && (
        <p className="muted" style={{ fontSize: 12, lineHeight: 1.45, margin: '14px 0 0' }}>
          Short on {shortfall.map(r => r.set.name).join(', ')} — source before the {DELIVERY_DAYS[0].full} run or refund those lines.
        </p>
      )}
    </OpsPanel>
  );
}

/* ───────────── route ───────────── */

function OpsRoute({ day }) {
  const target = day === 'all' ? DELIVERY_DAYS[0].id : day;
  const dayObj = DELIVERY_DAYS.find(d => d.id === target) || DELIVERY_DAYS[0];
  const stops = NEIGHBORHOODS
    .filter(n => n.days.includes(target))
    .map(n => {
      const orders = OPS_ORDERS.filter(o => o.zone === n.id && o.day === target);
      return { zone: n, orders, packs: orders.reduce((s, o) => s + opsOrderPacks(o), 0) };
    })
    .filter(s => s.orders.length > 0);
  const totalPacks = stops.reduce((s, x) => s + x.packs, 0);

  return (
    <OpsPanel kicker={dayObj.full} title="Delivery run"
      action={<span className="badge badge-accent">{stops.length} stop{stops.length === 1 ? '' : 's'}</span>}>
      {stops.length === 0 ? (
        <div className="muted" style={{ fontSize: 13, padding: '10px 0' }}>Nothing to run on {dayObj.day} yet.</div>
      ) : (
        <>
          <div className="timeline">
            {stops.map((s, i) => (
              <div className="tl-row" key={s.zone.id}>
                <div className="tl-dot" style={{ background: i === 0 ? 'var(--accent)' : 'var(--ink-3)' }} />
                <div className="tl-line" />
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', gap: 8 }}>
                    <span style={{ fontWeight: 700, fontSize: 14 }}>{s.zone.name}</span>
                    <span className="mono" style={{ fontSize: 11.5, color: 'var(--ink-3)', flexShrink: 0 }}>{WINDOWS[i % WINDOWS.length]}</span>
                  </div>
                  <div className="muted" style={{ fontSize: 12, marginTop: 2 }}>
                    {s.orders.length} order{s.orders.length === 1 ? '' : 's'} · {s.packs} packs · {s.orders.map(o => o.who).join(', ')}
                  </div>
                </div>
              </div>
            ))}
          </div>
          <div style={{ display: 'flex', gap: 8, marginTop: 16, paddingTop: 14, borderTop: '1px solid var(--line)' }}>
            <span className="mono" style={{ fontSize: 12, color: 'var(--ink-2)' }}>{totalPacks} packs across {stops.length} stops</span>
          </div>
        </>
      )}
    </OpsPanel>
  );
}

/* ───────────── sourcing pipeline ───────────── */
// The buy-local/sell-national side. Return on capital is roughly flat across
// collections; return on labour is not — so hours are shown next to every lot.

function OpsPipeline() {
  const [stage, setStage] = React.useState('all');
  const shown = OPS_PIPELINE.filter(c => stage === 'all' || c.stage === stage);
  const live = OPS_PIPELINE.filter(c => c.stage !== 'bought');
  const outstanding = OPS_PIPELINE.filter(c => c.stage === 'offered').reduce((s, c) => s + c.offer, 0);

  return (
    <OpsPanel kicker="Buy local · sell national" title="Sourcing pipeline" wide
      action={<span className="mono" style={{ fontSize: 12, color: 'var(--ink-2)' }}>{money0(outstanding)} in open offers</span>}>
      <div className="rail" style={{ padding: '0 0 14px', gap: 8 }}>
        <button className={'chip' + (stage === 'all' ? ' on' : '')} onClick={() => setStage('all')}>All ({OPS_PIPELINE.length})</button>
        {PIPELINE_STAGES.map(s => {
          const n = OPS_PIPELINE.filter(c => c.stage === s.id).length;
          return <button key={s.id} className={'chip' + (stage === s.id ? ' on' : '')} onClick={() => setStage(s.id)}>{s.label} ({n})</button>;
        })}
      </div>

      <div className="ops-pipegrid">
        {shown.map(c => {
          const profit = c.market * 0.77 - c.offer;   // ~23% marketplace + shipping drag
          const roc = (profit / c.offer) * 100;
          const perHour = profit / c.hrs;
          const good = perHour >= 30;
          return (
            <article key={c.id} className="card hairline ops-lot">
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 10 }}>
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontFamily: 'var(--ff-display)', fontWeight: 800, fontSize: 16, letterSpacing: '-0.01em' }}>{c.who}</div>
                  <div className="muted" style={{ fontSize: 11.5, marginTop: 2 }}>{c.zone} · PCS {c.pcs}</div>
                </div>
                <span className={'badge ' + (c.stage === 'bought' ? 'badge-good' : c.stage === 'offered' ? 'badge-gold' : 'badge-accent')}>
                  {(PIPELINE_STAGES.find(s => s.id === c.stage) || {}).label}
                </span>
              </div>

              <p className="muted" style={{ fontSize: 12, lineHeight: 1.4, margin: '10px 0 12px' }}>{c.note}</p>

              <div className="ops-lot-nums">
                <div><div className="kicker">Market</div><div className="ops-num">{money0(c.market)}</div></div>
                <div><div className="kicker">Offer</div><div className="ops-num">{money0(c.offer)}</div></div>
                <div><div className="kicker">Net</div><div className="ops-num" style={{ color: 'var(--good)' }}>{money0(profit)}</div></div>
                <div><div className="kicker">ROC</div><div className="ops-num">{Math.round(roc)}%</div></div>
                <div><div className="kicker">Hours</div><div className="ops-num">{c.hrs}h</div></div>
                <div>
                  <div className="kicker">Per hour</div>
                  <div className="ops-num" style={{ color: good ? 'var(--good)' : 'var(--gold)' }}>{money0(perHour)}</div>
                </div>
              </div>
            </article>
          );
        })}
      </div>

      <p className="muted" style={{ fontSize: 12, lineHeight: 1.5, margin: '16px 0 0' }}>
        Return on capital is roughly flat across lots — return on <i>labour</i> is not. {live.length} live lead{live.length === 1 ? '' : 's'};
        decline the bulk-heavy ones and the hours go where they earn.
      </p>
    </OpsPanel>
  );
}

/* ───────────── capital ───────────── */

function OpsCapital({ revenue }) {
  const c = OPS_CAPITAL;
  const inPipeline = OPS_PIPELINE.filter(x => x.stage === 'offered' || x.stage === 'bought').reduce((s, x) => s + x.offer, 0);
  const free = c.float - c.committed - inPipeline;
  const used = ((c.committed + inPipeline) / c.float) * 100;
  return (
    <OpsPanel kicker="Working capital" title="Cash position"
      action={<span className={'badge ' + (free < 500 ? 'badge-accent' : 'badge-good')}>{money0(free)} free</span>}>
      <div className="track" style={{ height: 12 }}>
        <span style={{ width: Math.min(100, used) + '%', background: free < 500 ? 'var(--accent)' : 'linear-gradient(90deg, var(--gold), var(--accent))' }} />
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 9, marginTop: 16 }}>
        {[
          ['Float', money0(c.float), 'var(--ink)'],
          ['Committed to packs', money0(c.committed), 'var(--ink-2)'],
          ['In collections', money0(inPipeline), 'var(--ink-2)'],
          ['Revenue, open drop', money0(revenue), 'var(--good)'],
        ].map(([label, val, color]) => (
          <div key={label} style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13 }}>
            <span className="muted">{label}</span>
            <span className="mono" style={{ fontWeight: 700, color }}>{val}</span>
          </div>
        ))}
      </div>
      <p className="muted" style={{ fontSize: 11.5, lineHeight: 1.45, margin: '14px 0 0' }}>
        Being cash-out in June is the expensive failure mode — that's peak PCS liquidation, when the good lots appear.
      </p>
    </OpsPanel>
  );
}

/* ───────────── the screen ───────────── */

function OpsScreen({ t, openScan }) {
  const [day, setDay] = React.useState('all');
  const [view, setView] = React.useState('drop');

  const nav = (
    <div className="subtabs ops-viewtabs">
      {[['drop', 'The drop'], ['inventory', 'Inventory']].map(([id, label]) => (
        <button key={id} className={'subtab' + (view === id ? ' on' : '')} onClick={() => setView(id)}>{label}</button>
      ))}
    </div>
  );

  if (view === 'inventory') {
    return <div className="ops">{nav}<InventoryScreen openScan={openScan} /></div>;
  }
  return <div className="ops">{nav}<OpsDrop t={t} day={day} setDay={setDay} /></div>;
}

function OpsDrop({ t, day, setDay }) {
  const orders = OPS_ORDERS;
  const packs = orders.reduce((s, o) => s + opsOrderPacks(o), 0);
  const revenue = orders.reduce((s, o) => s + opsOrderTotal(o, t.markup), 0);
  const unpaid = orders.filter(o => !o.paid);
  const short = opsPickList().filter(r => r.need > r.stock).length;

  return (
    <div className="fade-up">
      <header className="ops-hd">
        <div>
          <div className="kicker" style={{ marginBottom: 7 }}>Ops · Rook only</div>
          <h1 style={{ fontFamily: 'var(--ff-display)', fontWeight: 800, fontSize: 34, letterSpacing: '-0.03em', lineHeight: 1, margin: 0 }}>
            This week's drop
          </h1>
          <p className="muted" style={{ fontSize: 13.5, margin: '9px 0 0' }}>
            Orders close Sunday 8 PM · {DELIVERY_DAYS.length} delivery days · {NEIGHBORHOODS.length} zones
          </p>
        </div>
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
          {short > 0 && <span className="badge badge-accent" style={{ fontSize: 11.5 }}>{short} set{short === 1 ? '' : 's'} short</span>}
          {unpaid.length > 0 && <span className="badge badge-low" style={{ fontSize: 11.5 }}>{unpaid.length} unpaid</span>}
        </div>
      </header>

      <div className="ops-stats">
        <OpsStat label="Open orders" value={orders.length} sub={unpaid.length + ' awaiting payment'} />
        <OpsStat label="Packs committed" value={packs} sub={short > 0 ? short + ' set(s) short' : 'stock covers it'} tone={short > 0 ? 'accent' : 'good'} />
        <OpsStat label="Revenue, this drop" value={money0(revenue)} sub={'at ' + Math.round(t.markup * 100) + '% over MSRP'} tone="good" />
        <OpsStat label="Avg order" value={money(revenue / Math.max(orders.length, 1))} sub={(packs / Math.max(orders.length, 1)).toFixed(1) + ' packs each'} />
      </div>

      <div className="ops-grid">
        <OpsOrderBook t={t} day={day} setDay={setDay} />
        <OpsPickList />
        <OpsRoute day={day} />
        <OpsCapital revenue={revenue} />
        <OpsPipeline />
      </div>

      <div style={{ height: 28 }} />
    </div>
  );
}

Object.assign(window, { OpsScreen, OpsDrop, OpsStat, OpsPanel });
