// Phase 02 · LIVE intake — real coach conversation + real ledger writes.
//
// Solo: the user plays party A by default; seat toggle is available at the top bar.
// Multiplayer: each seat gets its own intake conversation, firewalled from the other.
//
// Reads/writes CG.threads[seat] (private conversation) and CG.ledger[seat] (auto observations).
// Submit button sets `shared.openings[seat]._intakeSubmitted = true` (stored on shared state
// so the partner sees submission status without seeing the contents).

window.LiveIntakePhase = function LiveIntakePhase({ seat, onPhase }) {
  const [, tick] = React.useState(0);
  React.useEffect(() => CG.session.onState(() => tick(t => t + 1)), []);
  React.useEffect(() => CG.threads.subscribe(() => tick(t => t + 1)), []);
  React.useEffect(() => CG.ledger.subscribe(() => tick(t => t + 1)), []);

  const shared = CG.session.shared || {};
  const names = (CG.session.getNames && CG.session.getNames()) || {};
  const mp = CG.session.isMultiplayer && CG.session.isMultiplayer();
  const otherSeat = seat === 'A' ? 'B' : 'A';
  const myName = names[seat] || (seat === 'A' ? 'host' : 'guest');
  const otherName = names[otherSeat] || (otherSeat === 'A' ? 'host' : 'guest');

  const [thread, setThread] = React.useState([]);
  const [ledger, setLedger] = React.useState([]);
  const [input, setInput] = React.useState('');
  const [sending, setSending] = React.useState(false);
  const [error, setError] = React.useState('');
  const [doneSignal, setDoneSignal] = React.useState(null); // { ready, good_outcome }
  const [autoStarted, setAutoStarted] = React.useState(false);
  const threadBoxRef = React.useRef(null);

  // Load thread + ledger on mount + when storage changes.
  React.useEffect(() => {
    let alive = true;
    (async () => {
      const [t, l] = await Promise.all([CG.threads.read(seat), CG.ledger.read(seat)]);
      if (!alive) return;
      setThread(t);
      setLedger(l);
    })();
    return () => { alive = false; };
  }, [seat]);

  React.useEffect(() => {
    let alive = true;
    const refresh = async () => {
      const [t, l] = await Promise.all([CG.threads.read(seat), CG.ledger.read(seat)]);
      if (!alive) return;
      setThread(t);
      setLedger(l);
    };
    const u1 = CG.threads.subscribe(refresh);
    const u2 = CG.ledger.subscribe(refresh);
    return () => { alive = false; u1(); u2(); };
  }, [seat]);

  // Auto-scroll
  React.useEffect(() => {
    const el = threadBoxRef.current;
    if (el) el.scrollTop = el.scrollHeight;
  }, [thread.length, sending]);

  // Seed the opening coach turn once, if the thread is empty.
  React.useEffect(() => {
    if (autoStarted) return;
    if (thread.length > 0) { setAutoStarted(true); return; }
    setAutoStarted(true);
    (async () => {
      setSending(true);
      try {
        const r = await CG.agents.intakeCoach.next(seat, null);
        setDoneSignal(r.done_signal);
      } catch (e) {
        setError(String(e.message || e));
      } finally {
        setSending(false);
      }
    })();
  }, [seat, thread.length, autoStarted]);

  const submittedKey = `_intakeSubmitted_${seat}`;
  const otherSubmittedKey = `_intakeSubmitted_${otherSeat}`;
  const youSubmitted = !!(shared.openings && shared.openings[seat] && shared.openings[seat]._intakeSubmitted);
  const otherSubmitted = !!(shared.openings && shared.openings[otherSeat] && shared.openings[otherSeat]._intakeSubmitted);
  const bothSubmitted = youSubmitted && (mp ? otherSubmitted : true);

  // Presence: broadcast what this user is doing
  React.useEffect(() => {
    let activity;
    if (bothSubmitted) activity = 'reviewing · ready';
    else if (youSubmitted) activity = 'waiting on partner';
    else if (sending) activity = 'chatting with coach';
    else if (thread.length < 2) activity = 'starting intake';
    else activity = 'chatting with coach';
    try { CG.session.setCursor && CG.session.setCursor({ activity }); } catch (e) {}
  }, [youSubmitted, bothSubmitted, sending, thread.length]);

  const submitIntake = () => {
    const openings = { ...(shared.openings || { A: null, B: null }) };
    const good = (doneSignal && doneSignal.good_outcome) || null;
    openings[seat] = { ...(openings[seat] || {}), _intakeSubmitted: true, good_outcome: good };
    // In solo mode, also mark the partner's side submitted so the UI can proceed.
    if (!mp) openings[otherSeat] = { ...(openings[otherSeat] || {}), _intakeSubmitted: true };
    CG.session.setShared({ openings });
  };

  const sendTurn = async () => {
    const text = input.trim();
    if (!text || sending || youSubmitted) return;
    setSending(true);
    setError('');
    const prev = input;
    setInput('');
    try {
      const r = await CG.agents.intakeCoach.next(seat, text);
      setDoneSignal(r.done_signal);
    } catch (e) {
      setError(String(e.message || e));
      setInput(prev);      // restore user's draft on failure
    } finally {
      setSending(false);
    }
  };

  return (
    <div style={{ padding: '22px 40px 60px', maxWidth: 1100, margin: '0 auto' }}>
      <div className="tiny">phase 02 · pretext · private + parallel · live</div>
      <h1 style={{ marginTop: 6, marginBottom: 6 }}>
        two rooms. one conversation with yourself, not them.
      </h1>
      <p style={{ maxWidth: 680, color: 'var(--ink-2)', marginBottom: 14, lineHeight: 1.5 }}>
        nothing posted. your coach asks open questions and quietly writes to your private ledger as you talk.{' '}
        <span className="hand" style={{ color: 'var(--blue)' }}>
          nobody else sees this — not {otherName}, not the mediator. not now, not later.
        </span>
      </p>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 300px', gap: 18 }}>
        {/* LEFT · your intake */}
        <div className="paper-card p-4">
          <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 10 }}>
            <div className="tiny">intake · {myName} · your room</div>
            <AgentBadge agent={seat === 'B' ? 'coachB' : 'coachA'} />
          </div>

          <div
            ref={threadBoxRef}
            style={{
              display: 'flex', flexDirection: 'column', gap: 10,
              minHeight: 280, maxHeight: 420, overflowY: 'auto',
              paddingRight: 4,
            }}
          >
            {thread.length === 0 && !sending && (
              <div className="micro" style={{ color: 'var(--ink-3)', fontStyle: 'italic' }}>
                coach is thinking of a first question…
              </div>
            )}
            {thread.map((m, i) => (
              <div key={i} className="fade-up" style={{
                padding: '10px 12px',
                background: m.role === 'user' ? 'var(--paper-2)' : 'transparent',
                borderLeft: m.role === 'coach' ? '2px solid var(--ink-3)' : '0',
                fontStyle: m.role === 'user' ? 'italic' : 'normal',
              }}>
                <div className="micro mb-1">{m.role === 'coach' ? 'coach' : myName}</div>
                <div style={{ lineHeight: 1.45 }}>{m.content}</div>
              </div>
            ))}
            {sending && (
              <div style={{ padding: '6px 12px' }}>
                <div className="micro mb-1">coach</div>
                <ThinkingInk label="reading what you wrote…" />
              </div>
            )}
            {error && (
              <div className="paper-card p-2" style={{ background: 'var(--red-soft)', borderLeft: '2px solid var(--red)' }}>
                <div className="micro" style={{ color: 'var(--red)' }}>error</div>
                <div style={{ fontSize: '0.85rem' }}>{error}</div>
              </div>
            )}
          </div>

          <div className="dashed" style={{ margin: '14px 0 10px' }} />
          <div className="tiny mb-2">your turn · still private</div>
          <textarea
            className="paper-input"
            rows={2}
            placeholder={youSubmitted ? '— submitted —' : 'keep going, or stop here and submit…'}
            value={input}
            onChange={e => setInput(e.target.value)}
            disabled={youSubmitted || sending}
            onKeyDown={e => {
              if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) { e.preventDefault(); sendTurn(); }
            }}
          />
          <div style={{ display: 'flex', gap: 8, marginTop: 10, alignItems: 'center' }}>
            <button
              className="btn btn-sm btn-primary"
              disabled={!input.trim() || sending || youSubmitted}
              onClick={sendTurn}
            >{sending ? 'sending…' : 'send to coach'}</button>
            <button
              className="btn btn-sm"
              disabled={youSubmitted || thread.length < 2}
              onClick={submitIntake}
            >
              {youSubmitted ? '✓ submitted' : 'i\'m done · submit intake'}
            </button>
            <div style={{ flex: 1 }} />
            {doneSignal && doneSignal.ready && !youSubmitted && (
              <span className="stamp stamp-green" style={{ fontSize: '0.6rem' }}>coach: ready to submit</span>
            )}
          </div>

          {doneSignal && doneSignal.good_outcome && (
            <div className="fade-up">
              <div className="dashed" style={{ margin: '16px 0 10px' }} />
              <div className="tiny mb-2">what a good outcome looks like · in your own words</div>
              <div style={{ fontFamily: 'var(--font-hand)', fontSize: '1.2rem', lineHeight: 1.2, color: 'var(--blue)' }}>
                "{doneSignal.good_outcome}"
              </div>
            </div>
          )}
        </div>

        {/* RIGHT · partner status + submit gate */}
        <div>
          <div className="paper-card p-3" style={{ position: 'sticky', top: 10 }}>
            <div className="tiny mb-2">{otherName}'s room · firewalled</div>
            <div style={{
              minHeight: 90,
              background: 'repeating-linear-gradient(135deg, transparent 0 8px, var(--paper-3) 8px 9px)',
              padding: 12, marginBottom: 10,
            }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 }}>
                <Icons.Lock size={11} /><span className="micro">sealed</span>
              </div>
              <div className="hand" style={{ fontSize: '0.95rem', color: 'var(--ink-3)', lineHeight: 1.3 }}>
                you only see whether they've submitted.
              </div>
            </div>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <span className="mono" style={{ fontSize: '0.7rem', color: 'var(--ink-3)' }}>status</span>
              {otherSubmitted
                ? <span className="stamp stamp-green" style={{ fontSize: '0.6rem' }}>submitted</span>
                : <span className="mono" style={{ fontSize: '0.7rem' }}>{mp ? 'in progress…' : 'solo · auto'}</span>}
            </div>
            {mp && otherSubmitted && !youSubmitted && (
              <div style={{ marginTop: 10, padding: '7px 9px', background: 'oklch(96% 0.04 240)', borderLeft: '2px solid var(--blue)', fontSize: '0.8rem', color: 'var(--ink-2)', lineHeight: 1.4 }}>
                {otherName} has submitted — they're waiting on you.
              </div>
            )}
          </div>

          {/* your ledger (private, visible to you) */}
          <div className="paper-card p-3 mt-3">
            <div className="tiny mb-2">your private ledger · {ledger.length} {ledger.length === 1 ? 'entry' : 'entries'}</div>
            <div className="micro mb-2" style={{ textTransform: 'none', letterSpacing: 0, color: 'var(--ink-3)' }}>
              the coach writes these automatically as they listen. this is your own running notes. {otherName} never sees it.
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6, maxHeight: 220, overflowY: 'auto' }}>
              {ledger.length === 0 && (
                <div className="mono" style={{ fontSize: '0.72rem', color: 'var(--ink-4)' }}>
                  no entries yet — the coach only logs substantive observations.
                </div>
              )}
              {ledger.slice().reverse().map(e => (
                <div key={e.id} style={{
                  fontSize: '0.78rem',
                  padding: '6px 8px',
                  borderLeft: `2px solid ${ledgerKindColor(e.kind)}`,
                  background: 'var(--paper-2)',
                  lineHeight: 1.4,
                }}>
                  <div className="mono" style={{ fontSize: '0.62rem', color: 'var(--ink-3)', letterSpacing: '0.05em', textTransform: 'uppercase', marginBottom: 2 }}>
                    {e.kind} · {e.severity}
                  </div>
                  {e.text}
                </div>
              ))}
            </div>
          </div>

          {/* continue gate */}
          <div className="paper-card p-3 mt-3" style={{
            background: bothSubmitted ? 'var(--green-soft)' : 'var(--paper-2)',
            borderLeft: `2px solid ${bothSubmitted ? 'var(--green)' : 'var(--rule)'}`,
          }}>
            <div className="tiny mb-2">continue</div>
            {bothSubmitted
              ? <button className="btn btn-sm btn-primary" onClick={() => onPhase && onPhase('opening')}>
                  → phase 03 · blind opening <Icons.Arrow size={10} />
                </button>
              : <div className="mono" style={{ fontSize: '0.72rem', color: 'var(--ink-3)' }}>
                  {youSubmitted
                    ? `waiting on ${otherName} to submit.`
                    : otherSubmitted
                      ? `${otherName} is ready — submit yours to continue.`
                      : 'both of you need to submit to continue.'}
                </div>}
          </div>
        </div>
      </div>
    </div>
  );
};

function ledgerKindColor(kind) {
  switch (kind) {
    case 'pattern':       return 'var(--ink-3)';
    case 'contradiction': return 'oklch(55% 0.15 30)';   // terracotta
    case 'strength':      return 'oklch(50% 0.14 145)';  // ink-green
    case 'risk':          return 'oklch(55% 0.18 30)';
    default:              return 'var(--ink-4)';
  }
}

console.log('[phases-intake-live] loaded');
