// Pack Out Session — worker boxes assembled units, moving them to Staged inventory
const { useState: useStatePO, useEffect: useEffectPO } = React;

function PackOutSession({ wo, user, sessionId, onExit, onComplete }) {
  const [actualQty, setActualQty] = useStatePO(wo.qty || 1);
  const [elapsed, setElapsed] = useStatePO(0);
  const [pauseModal, setPauseModal] = useStatePO(false);
  const [done, setDone] = useStatePO(false);

  // Packaging materials from inventory data
  const invItem = (window.INVENTORY || []).find(i => i.sku === wo.sku);
  const pkgBom = invItem?.packaging_bom || [];
  const assembledAvail = invItem?.qty_wip || 0;

  useEffectPO(() => {
    const t = setInterval(() => setElapsed(e => e + 1), 1000);
    return () => clearInterval(t);
  }, []);

  function fmt(s) {
    const h = Math.floor(s / 3600);
    const m = Math.floor((s % 3600) / 60);
    const sec = s % 60;
    return `${String(h).padStart(2,'0')}:${String(m).padStart(2,'0')}:${String(sec).padStart(2,'0')}`;
  }

  async function handleComplete() {
    try {
      await fetch(`/api/work-orders/${wo.id}/complete`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Idempotency-Key': `complete:${wo.id}:${sessionId || 'na'}`, // GPS-006
        },
        body: JSON.stringify({ session_id: sessionId, qty_built: actualQty }),
      });
    } catch (_) {}
    setDone(true);
    onComplete && onComplete({ qty_staged: actualQty });
  }

  if (done) {
    return (
      <div className="min-h-screen bg-[#09090b] text-zinc-100 flex flex-col items-center justify-center gap-6">
        <div className="text-emerald-400 text-[72px]">📦</div>
        <div className="font-display text-[48px] tracking-wide text-emerald-400">STAGED</div>
        <div className="text-zinc-400 text-[18px]">{actualQty} unit{actualQty !== 1 ? 's' : ''} staged and ready to pull</div>
        <button onClick={onExit}
          className="mt-4 h-14 px-10 rounded-xl bg-zinc-800 border border-zinc-700 text-zinc-200 font-display text-[20px] tracking-wider hover:bg-zinc-700">
          BACK TO QUEUE
        </button>
      </div>
    );
  }

  return (
    <div className="min-h-screen bg-[#09090b] text-zinc-100 flex flex-col">
      {/* Header */}
      <header className="flex-shrink-0 h-[60px] px-6 flex items-center justify-between border-b border-zinc-800">
        <div className="flex items-center gap-4">
          <button onClick={onExit} className="text-zinc-500 hover:text-zinc-300 text-[13px]">✕ Exit</button>
          <span className="font-display text-[20px] tracking-wide">PACK OUT</span>
          <span className="text-zinc-600 text-[13px]">{wo.name}</span>
        </div>
        <div className="flex items-center gap-4">
          <button onClick={() => setPauseModal(true)}
            className="h-8 px-3 rounded-lg bg-zinc-800 border border-zinc-700 text-zinc-300 text-[12px] hover:bg-zinc-700">
            Pause
          </button>
          <span className="font-mono text-zinc-500 text-[13px]">{fmt(elapsed)}</span>
        </div>
      </header>

      <div className="flex-1 flex flex-col items-center justify-center px-8 py-6">
        <div className="w-full max-w-[520px] space-y-5">

          {/* Part info */}
          <div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-6">
            <div className="text-[11px] uppercase tracking-wider text-zinc-500 mb-1">Pack Out</div>
            <div className="font-display text-[32px] leading-tight">{wo.name}</div>
            <div className="font-mono text-[13px] text-zinc-500 mt-1">{wo.sku}</div>
            <div className="mt-3 text-[13px] text-violet-300">
              {assembledAvail} assembled available to stage
            </div>
          </div>

          {/* Packaging materials needed */}
          {pkgBom.length > 0 && (
            <div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-5">
              <div className="text-[11px] uppercase tracking-wider text-zinc-500 mb-3">Materials needed per {actualQty} unit{actualQty !== 1 ? 's' : ''}</div>
              <div className="space-y-2">
                {pkgBom.map((line, i) => {
                  const mat = (window.INVENTORY || []).find(inv => inv.sku === line.child_sku);
                  const needed = line.qty * actualQty;
                  const have = mat?.qty || 0;
                  const short = have < needed;
                  return (
                    <div key={i} className={`flex items-center justify-between text-[13px] px-3 py-2 rounded-lg ${short ? 'bg-red-500/10 border border-red-500/30' : 'bg-zinc-800/60'}`}>
                      <div>
                        <span className="text-zinc-200">{mat?.name || line.child_sku}</span>
                        <span className="font-mono text-zinc-500 text-[11px] ml-2">{line.child_sku}</span>
                      </div>
                      <div className={`font-mono text-[13px] ${short ? 'text-red-400' : 'text-zinc-300'}`}>
                        ×{needed} {short ? <span className="text-[11px]">(only {have})</span> : ''}
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          )}

          {/* Qty to stage */}
          <div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-5">
            <div className="text-[11px] uppercase tracking-wider text-zinc-500 mb-3">Units staged</div>
            <div className="flex items-center gap-3">
              <button onClick={() => setActualQty(q => Math.max(1, q - 1))}
                className="h-14 w-14 flex-shrink-0 rounded-xl bg-zinc-800 border border-zinc-700 text-zinc-200 text-[24px] hover:bg-zinc-700">−</button>
              <input type="number" value={actualQty} min={1} max={assembledAvail || 999}
                onChange={e => setActualQty(Math.max(1, parseInt(e.target.value) || 1))}
                className="flex-1 h-14 bg-zinc-950 border border-zinc-700 rounded-xl px-4 text-center font-display text-[42px] outline-none focus:border-zinc-500 text-violet-300"/>
              <button onClick={() => setActualQty(q => Math.min(assembledAvail || 999, q + 1))}
                className="h-14 w-14 flex-shrink-0 rounded-xl bg-zinc-800 border border-zinc-700 text-zinc-200 text-[24px] hover:bg-zinc-700">+</button>
            </div>
            {assembledAvail > 0 && (
              <button onClick={() => setActualQty(Math.min(wo.qty, assembledAvail))}
                className="w-full mt-2 h-9 rounded-lg bg-zinc-800 border border-zinc-700 text-zinc-400 text-[12px] hover:bg-zinc-700">
                Use target ({Math.min(wo.qty, assembledAvail)})
              </button>
            )}
          </div>

          {/* Complete */}
          <window.HoldButton
            onComplete={handleComplete}
            color="emerald"
            className="w-full h-[80px] text-[24px]"
            subText="hold to confirm staging complete">
            STAGE {actualQty} UNIT{actualQty !== 1 ? 'S' : ''} →
          </window.HoldButton>

        </div>
      </div>

      {/* Pause modal */}
      {pauseModal && (
        <window.PauseModal
          onResume={() => setPauseModal(false)}
          onPause={(reason, note) => {
            setPauseModal(false);
            onExit();
          }}
        />
      )}
    </div>
  );
}

window.PackOutSession = PackOutSession;

// ── PackSession — the ship-alone pack step after a product build ───────────────
// Runs after a KITTING/ASSY build completes: pick the box (suggested = last-used for this
// product, else the recipe box; override allowed and becomes the new default), confirm the
// pack materials, and stage. Consuming the pack is the single packaging-write path
// (POST /pack → packWorkOrder): atomic, idempotent, never negative.
function PackSession({ wo, user, sessionId, qtyBuilt, onDone, onExit }) {
  const [info, setInfo] = useStatePO(null);
  const [boxSku, setBoxSku] = useStatePO('');
  const [busy, setBusy] = useStatePO(false);
  const qty = qtyBuilt || (wo && wo.qty) || 1;

  useEffectPO(() => {
    let alive = true;
    fetch(`/api/work-orders/${wo.id}/pack-info`)
      .then(r => r.ok ? r.json() : Promise.reject())
      .then(d => {
        if (!alive) return;
        // Already packed (idempotent replay / re-entry), or nothing to pack → skip the step.
        if (d.packed_at || (!d.pack_lines || d.pack_lines.length === 0)) { onDone && onDone(); return; }
        setInfo(d);
        setBoxSku(d.suggested_box || '');
      })
      .catch(() => { onDone && onDone(); });   // info unavailable → don't strand the worker
    return () => { alive = false; };
  }, []);

  async function handlePack() {
    if (busy) return;
    setBusy(true);
    try {
      const r = await fetch(`/api/work-orders/${wo.id}/pack`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Idempotency-Key': `pack:${wo.id}:${sessionId || 'na'}` },
        body: JSON.stringify({ box_sku: boxSku || null, qty }),
      });
      const d = await r.json().catch(() => ({}));
      if (r.ok && d.shortages && d.shortages.length) {
        const list = d.shortages.map(s => `${s.sku} (need ${s.needed}, had ${s.have})`).join(', ');
        window.gpsToast && window.gpsToast({ message: `Packed short: ${list}`, tone: 'warn' });
      } else if (!r.ok) {
        window.gpsToast && window.gpsToast({ message: d.error || "Couldn't record pack", tone: 'warn' });
      }
    } catch (_) {
      window.gpsToast && window.gpsToast({ message: 'Could not reach server — pack not recorded', tone: 'warn' });
    }
    onDone && onDone();
  }

  if (!info) {
    return (
      <div className="min-h-screen bg-[#09090b] text-zinc-100 flex items-center justify-center">
        <div className="text-zinc-500 text-[14px]">Preparing pack…</div>
      </div>
    );
  }

  const boxes = info.boxes || [];
  const packaging = info.packaging || [];
  // If no part is flagged as a box yet, fall back to all packaging so a box is always selectable.
  const boxOptions = boxes.length ? boxes : packaging;
  const usingFallback = boxes.length === 0 && packaging.length > 0;
  const others = info.other_lines || [];
  const learned = info.suggested_box && boxes.some(b => b.sku === info.suggested_box);

  return (
    <div className="min-h-screen bg-[#09090b] text-zinc-100 flex flex-col">
      <header className="flex-shrink-0 h-[60px] px-6 flex items-center justify-between border-b border-zinc-800">
        <div className="flex items-center gap-4">
          <button onClick={() => (onDone ? onDone() : onExit && onExit())} className="text-zinc-500 hover:text-zinc-300 text-[13px]">Skip for now</button>
          <span className="font-display text-[20px] tracking-wide">PACK</span>
          <span className="text-zinc-600 text-[13px]">{wo.name}</span>
        </div>
        <span className="text-zinc-600 text-[12px] font-mono">{wo.sku}</span>
      </header>

      <div className="flex-1 flex flex-col items-center justify-center px-8 py-6">
        <div className="w-full max-w-[520px] space-y-5">

          {/* Box pick — suggested = last used for this product, override allowed */}
          <div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-5">
            <div className="text-[11px] uppercase tracking-wider text-zinc-500 mb-3">Box</div>
            {boxOptions.length > 0 ? (
              <select value={boxSku} onChange={e => setBoxSku(e.target.value)}
                className="w-full h-14 bg-zinc-950 border border-zinc-700 rounded-xl px-4 text-[18px] outline-none focus:border-zinc-500 text-zinc-100">
                <option value="">— no box —</option>
                {boxOptions.map(b => (
                  <option key={b.sku} value={b.sku}>{b.name} ({b.sku})</option>
                ))}
              </select>
            ) : (
              <div className="text-[13px] text-zinc-500">
                No packaging parts in boxd yet — add one in the BOM editor to pick a box here.
              </div>
            )}
            <div className="mt-2 text-[12px] text-zinc-500">
              {usingFallback
                ? 'Showing all packaging — flag your boxes (BOM editor → part → "Shippable box") for cleaner suggestions. '
                : (learned ? 'Suggested = last box used for this product. ' : '')}
              Your choice becomes the new default.
            </div>
          </div>

          {/* Pack materials (bubble, goodie, …) */}
          {others.length > 0 && (
            <div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-5">
              <div className="text-[11px] uppercase tracking-wider text-zinc-500 mb-3">In the pack (×{qty})</div>
              <div className="space-y-2">
                {others.map((l, i) => (
                  <div key={i} className="flex items-center justify-between text-[13px] px-3 py-2 rounded-lg bg-zinc-800/60">
                    <span className="text-zinc-200">{l.child_sku}</span>
                    <span className="font-mono text-zinc-400">×{l.qty * qty}</span>
                  </div>
                ))}
              </div>
              <div className="mt-3 text-[12px] text-emerald-300/80">Goodie bag: one per shipment (already in the ship-alone pack).</div>
            </div>
          )}

          <window.HoldButton
            onComplete={handlePack}
            color="emerald"
            className="w-full h-[80px] text-[24px]"
            subText="hold to confirm packed & staged">
            PACK & STAGE →
          </window.HoldButton>
        </div>
      </div>
    </div>
  );
}

window.PackSession = PackSession;
