// Phase 04 · LIVE steel-man gate.
//
// Each party must restate the OTHER party's posted synthesis fairly before the room unlocks.
// Per direction: (attempter → subject)
//   1. attempter writes an attempt. judge (their coach, private) scores 1..5.
//   2. if score ≥ 4, attempt is sent to subject. subject can ACCEPT ("yes, you got me") or
//      PUSH BACK with one line of what was missed.
//   3. if subject accepts, that direction is 'accepted'.
//   4. both directions must be 'accepted' to unlock phase 05.
//
// shared.steelman shape (live mode; new top-level field on shared state):
//   {
//     A_attempts: [{ text, score, got_right, missed, added_your_own, verdict, status, push_back }],
//     B_attempts: [{ text, score, got_right, missed, added_your_own, verdict, status, push_back }],
//   }
// status ∈ 'needs_review' | 'accepted' | 'pushback'
// Each party writes their OWN attempts array. Each party writes the status/push_back on the
// array that describes attempts about THEM (because they are the subject).
//
// Session whitelist: we extend _applyGuestProposal via the 'openings.B' / cursor.B pattern
// by piggybacking on a new opt-in key 'steelman' (see below) — but we don't actually need to
// touch cg-session here because `setShared` on host applies directly, and guest writes go
// through _applyGuestProposal which already merges whitelisted keys. We'll add 'steelman' to
// the whitelist in cg-session.

(function () {
  const { useState, useEffect } = React;

  window.LiveSteelmanPhase = function LiveSteelmanPhase({ seat, onPhase }) {
    const [, tick] = useState(0);
    useEffect(() => CG.session.onState(() => 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 isHost = !mp || seat === 'A';
    const otherSeat = seat === 'A' ? 'B' : 'A';
    const myName = names[seat] || (seat === 'A' ? 'host' : 'guest');
    const otherName = names[otherSeat] || (otherSeat === 'A' ? 'host' : 'guest');

    const myPostedSynthesis   = shared.openings?.[seat]?.synthesis || '';
    const theirPostedSynthesis = shared.openings?.[otherSeat]?.synthesis || '';

    // Guard: if openings aren't posted, bail.
    const myPosted    = shared.openings?.[seat]?.step === 'posted';
    const theirPosted = shared.openings?.[otherSeat]?.step === 'posted';
    if (!myPosted || !theirPosted) {
      return (
        <div style={{ padding: '40px', maxWidth: 720, margin: '0 auto' }}>
          <div className="tiny">phase 04 · steel-man gate</div>
          <h1 style={{ marginTop: 6 }}>not ready.</h1>
          <p style={{ color: 'var(--ink-2)', lineHeight: 1.55 }}>
            both openings must be posted before the steel-man gate opens.{' '}
            <a onClick={() => onPhase && onPhase('opening')} style={{ color: 'var(--blue)', cursor: 'pointer' }}>← back to phase 03</a>
          </p>
        </div>
      );
    }

    // shared.steelman is the live record
    const steel = shared.steelman || {};
    const myAttemptsKey = `${seat}_attempts`;           // attempts I've made about OTHER
    const theirAttemptsKey = `${otherSeat}_attempts`;   // attempts OTHER has made about ME
    const myAttempts = steel[myAttemptsKey] || [];
    const theirAttempts = steel[theirAttemptsKey] || [];

    const latestMine = myAttempts[myAttempts.length - 1];
    const latestTheirs = theirAttempts[theirAttempts.length - 1];

    // direction A: I restate them. Gate passes when some attempt in myAttempts has status 'accepted'.
    const meDoneSteelmanning = myAttempts.some(a => a.status === 'accepted');
    // direction B: they restate me. Gate passes when some attempt in theirAttempts has status 'accepted'.
    const theyDoneSteelmanning = theirAttempts.some(a => a.status === 'accepted');
    const bothDone = meDoneSteelmanning && theyDoneSteelmanning;

    // Presence: steelman activity label
    useEffect(() => {
      let activity;
      if (bothDone) activity = 'gate passed';
      else if (meDoneSteelmanning && !theyDoneSteelmanning) activity = `waiting on ${otherName}`;
      else if (!meDoneSteelmanning && theyDoneSteelmanning) activity = `steel-manning ${otherName}`;
      else if (latestTheirs && latestTheirs.status === 'needs_review') activity = 'reviewing their restatement';
      else activity = `steel-manning ${otherName}`;
      try { CG.session.setCursor && CG.session.setCursor({ activity }); } catch (e) {}
    }, [bothDone, meDoneSteelmanning, theyDoneSteelmanning, latestTheirs?.status, otherName]);

    const [attempt, setAttempt] = useState('');
    const [scoring, setScoring] = useState(false);
    const [scoreResult, setScoreResult] = useState(null); // latest judge result for UI (before send)
    const [error, setError] = useState('');

    // Hydrate attempt box with latest draft that hasn't been sent yet
    useEffect(() => {
      (async () => {
        const saved = await CG.store.get(`steelman_draft_${seat}`);
        if (saved && typeof saved === 'string') setAttempt(saved);
      })();
    }, [seat]);
    useEffect(() => {
      CG.store.set(`steelman_draft_${seat}`, attempt);
    }, [attempt, seat]);

    const writeSteelman = (patchFn) => {
      const next = { ...(shared.steelman || {}) };
      patchFn(next);
      CG.session.setShared({ steelman: next });
    };

    const runJudge = async () => {
      const t = attempt.trim();
      if (!t || scoring) return;
      setScoring(true);
      setError('');
      try {
        const r = await CG.agents.steelmanJudge.score(seat, theirPostedSynthesis, t);
        setScoreResult(r);
      } catch (e) {
        setError(String(e.message || e));
      } finally {
        setScoring(false);
      }
    };

    const sendAttempt = () => {
      if (!scoreResult) return;
      writeSteelman(s => {
        const arr = s[myAttemptsKey] || [];
        s[myAttemptsKey] = [...arr, {
          text: attempt.trim(),
          score: scoreResult.score,
          got_right: scoreResult.got_right,
          missed: scoreResult.missed,
          added_your_own: scoreResult.added_your_own,
          verdict: scoreResult.verdict,
          status: 'needs_review',
          ts: Date.now(),
        }];
      });
      setScoreResult(null);
      setAttempt('');
      CG.store.set(`steelman_draft_${seat}`, '');
    };

    // Subject actions on THEIR attempts (the ones OTHER made about me).
    const acceptAttempt = (idx) => {
      writeSteelman(s => {
        const arr = [...(s[theirAttemptsKey] || [])];
        arr[idx] = { ...arr[idx], status: 'accepted' };
        s[theirAttemptsKey] = arr;
      });
    };
    const pushbackAttempt = (idx, pushText) => {
      writeSteelman(s => {
        const arr = [...(s[theirAttemptsKey] || [])];
        arr[idx] = { ...arr[idx], status: 'pushback', push_back: pushText };
        s[theirAttemptsKey] = arr;
      });
    };

    // Solo simulation · let solo users complete the flow by auto-accepting after a short delay.
    useEffect(() => {
      if (mp) return;
      if (!latestMine) return;
      if (latestMine.status !== 'needs_review') return;
      const t = setTimeout(() => {
        writeSteelman(s => {
          const arr = [...(s[myAttemptsKey] || [])];
          arr[arr.length - 1] = { ...arr[arr.length - 1], status: 'accepted' };
          s[myAttemptsKey] = arr;
        });
      }, 1500);
      return () => clearTimeout(t);
    }, [mp, latestMine?.status]);

    useEffect(() => {
      if (mp) return;
      if (theyDoneSteelmanning) return;
      if (!meDoneSteelmanning) return;
      // Auto-insert a solo "partner also steelmanned you" accepted record.
      writeSteelman(s => {
        const arr = s[theirAttemptsKey] || [];
        if (arr.some(a => a.status === 'accepted')) return;
        s[theirAttemptsKey] = [...arr, {
          text: `(solo mode · ${otherName} did not participate. auto-accepted to let you walk the flow.)`,
          score: 5,
          got_right: [], missed: [], added_your_own: [],
          verdict: 'solo auto-accept',
          status: 'accepted',
          ts: Date.now(),
        }];
      });
    }, [mp, meDoneSteelmanning, theyDoneSteelmanning]);

    return (
      <div style={{ padding: '22px 40px 60px', maxWidth: 1100, margin: '0 auto' }}>
        <div className="tiny">phase 04 · steel-man gate · live</div>
        <h1 style={{ marginTop: 6, marginBottom: 6 }}>
          prove you heard them. they grade you. nobody moves until they say yes.
        </h1>
        <p style={{ maxWidth: 720, color: 'var(--ink-2)', marginBottom: 14, lineHeight: 1.5 }}>
          restate {otherName}'s posted synthesis in your own words — fairly, charitably, without slipping into your own frame.{' '}
          <span className="hand" style={{ color: 'var(--blue)' }}>
            {otherName} confirms you got them. you do the same. then the room opens.
          </span>
        </p>

        <DirectionBanner
          meDone={meDoneSteelmanning}
          theyDone={theyDoneSteelmanning}
          myName={myName}
          otherName={otherName}
        />

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 18, marginTop: 16 }}>
          {/* LEFT · ME steelmanning THEM */}
          <div className="paper-card p-4">
            <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 10 }}>
              <div className="tiny">your steel-man of {otherName}</div>
              <AgentBadge agent={seat === 'B' ? 'coachB' : 'coachA'} />
            </div>

            <div className="micro mb-2" style={{ textTransform: 'none', letterSpacing: 0, color: 'var(--ink-3)', lineHeight: 1.5 }}>
              their posted synthesis (your target to restate):
            </div>
            <div className="paper-card p-3 mb-3" style={{ background: 'var(--paper-2)', fontSize: '0.9rem', lineHeight: 1.55, whiteSpace: 'pre-wrap' }}>
              {theirPostedSynthesis}
            </div>

            {!meDoneSteelmanning && (
              <MyAttemptWriter
                attempt={attempt}
                setAttempt={setAttempt}
                onJudge={runJudge}
                scoring={scoring}
                scoreResult={scoreResult}
                onSend={sendAttempt}
                onDiscardScore={() => setScoreResult(null)}
                error={error}
                history={myAttempts}
                otherName={otherName}
              />
            )}
            {meDoneSteelmanning && (
              <div className="paper-card p-3" style={{ background: 'var(--green-soft)', borderLeft: '2px solid var(--green)' }}>
                <div className="tiny mb-1" style={{ color: 'var(--green)' }}>accepted by {otherName}</div>
                <div style={{ fontSize: '0.95rem', lineHeight: 1.55, whiteSpace: 'pre-wrap' }}>
                  {myAttempts.find(a => a.status === 'accepted')?.text}
                </div>
              </div>
            )}
            {meDoneSteelmanning && !theyDoneSteelmanning && mp && (
              <div style={{ marginTop: 8, padding: '7px 9px', background: 'var(--paper-2)', borderLeft: '2px solid var(--ink-3)', fontSize: '0.8rem', color: 'var(--ink-2)', lineHeight: 1.4 }}>
                waiting on {otherName} to restate your opening — you'll grade theirs when it arrives.
              </div>
            )}
          </div>

          {/* RIGHT · THEM steelmanning ME (subject view) */}
          <div className="paper-card p-4">
            <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 10 }}>
              <div className="tiny">{otherName}'s steel-man of you · you grade</div>
              <AgentBadge agent="mediator" />
            </div>

            <div className="micro mb-2" style={{ textTransform: 'none', letterSpacing: 0, color: 'var(--ink-3)', lineHeight: 1.5 }}>
              {otherName} is trying to restate YOUR posted synthesis. you accept or push back.
            </div>

            {theirAttempts.length === 0 && (
              <div className="paper-card p-3" style={{
                background: 'repeating-linear-gradient(135deg, transparent 0 8px, var(--paper-3) 8px 9px)',
                minHeight: 100, display: 'flex', alignItems: 'center', justifyContent: 'center',
              }}>
                <div className="hand" style={{ fontSize: '0.95rem', color: 'var(--ink-3)' }}>
                  {mp ? `waiting for ${otherName}…` : `in solo mode, this auto-completes after you finish yours.`}
                </div>
              </div>
            )}

            {theirAttempts.map((a, i) => (
              <SubjectReviewCard
                key={i}
                attempt={a}
                idx={i}
                isLatest={i === theirAttempts.length - 1}
                onAccept={() => acceptAttempt(i)}
                onPushback={(text) => pushbackAttempt(i, text)}
              />
            ))}
          </div>
        </div>

        {bothDone && (
          <div className="fade-up paper-card p-4 mt-4" style={{ background: 'var(--green-soft)', borderLeft: '2px solid var(--green)', textAlign: 'center' }}>
            <div className="tiny mb-2" style={{ color: 'var(--green)' }}>gate unlocked</div>
            <div className="hand mb-3" style={{ fontSize: '1.3rem', color: 'var(--ink-2)' }}>
              each of you confirmed the other got them. the room opens.
            </div>
            <button className="btn btn-primary" onClick={() => onPhase && onPhase('room')}>
              → phase 05 · the room <Icons.Arrow size={10} />
            </button>
          </div>
        )}
      </div>
    );
  };

  // ---- subcomponents ----

  function DirectionBanner({ meDone, theyDone, myName, otherName }) {
    const pill = (label, done) => (
      <div style={{
        display: 'inline-flex', alignItems: 'center', gap: 6,
        padding: '4px 10px',
        background: done ? 'var(--green-soft)' : 'var(--paper-2)',
        border: `1px solid ${done ? 'var(--green)' : 'var(--rule)'}`,
        fontSize: '0.8rem',
      }}>
        {done ? '✓' : '○'} {label}
      </div>
    );
    return (
      <div style={{ display: 'flex', gap: 10, alignItems: 'center', padding: '10px 14px', border: '1px dashed var(--rule)' }}>
        <span className="mono" style={{ fontSize: '0.72rem', color: 'var(--ink-3)', marginRight: 4 }}>gate</span>
        {pill(`${myName} restates ${otherName}`, meDone)}
        {pill(`${otherName} restates ${myName}`, theyDone)}
      </div>
    );
  }

  function MyAttemptWriter({ attempt, setAttempt, onJudge, scoring, scoreResult, onSend, onDiscardScore, error, history, otherName }) {
    return (
      <div>
        {history.length > 0 && (
          <details style={{ marginBottom: 10 }}>
            <summary className="mono" style={{ fontSize: '0.72rem', color: 'var(--ink-3)', cursor: 'pointer' }}>
              previous attempts ({history.length})
            </summary>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginTop: 8 }}>
              {history.map((a, i) => (
                <div key={i} className="paper-card p-2" style={{ background: 'var(--paper-3)', fontSize: '0.82rem' }}>
                  <div className="mono mb-1" style={{ fontSize: '0.66rem', color: 'var(--ink-3)' }}>
                    #{i + 1} · judge {a.score}/5 · {a.status}
                  </div>
                  <div style={{ whiteSpace: 'pre-wrap', lineHeight: 1.45 }}>{a.text}</div>
                  {a.push_back && (
                    <div className="mt-1" style={{ borderLeft: '2px solid var(--red)', paddingLeft: 8, fontStyle: 'italic' }}>
                      {otherName} pushed back: {a.push_back}
                    </div>
                  )}
                </div>
              ))}
            </div>
          </details>
        )}

        <textarea
          className="paper-input"
          rows={6}
          placeholder={`restate ${otherName}'s synthesis in your own words. no sneering, no caricature. try to pass their test.`}
          value={attempt}
          onChange={e => setAttempt(e.target.value)}
          disabled={scoring || !!scoreResult}
        />
        <div style={{ display: 'flex', gap: 8, marginTop: 10, alignItems: 'center' }}>
          {!scoreResult && (
            <button
              className="btn btn-sm btn-primary"
              disabled={!attempt.trim() || scoring}
              onClick={onJudge}
            >{scoring ? 'judge reading…' : 'coach · score my attempt'}</button>
          )}
          <span className="mono" style={{ fontSize: '0.7rem', color: 'var(--ink-3)' }}>
            {attempt.trim().split(/\s+/).filter(Boolean).length} words
          </span>
        </div>

        {error && (
          <div className="paper-card p-2 mt-3" 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>
        )}

        {scoreResult && (
          <JudgeCard
            result={scoreResult}
            onSend={onSend}
            onRevise={onDiscardScore}
          />
        )}
      </div>
    );
  }

  function JudgeCard({ result, onSend, onRevise }) {
    const color = result.score >= 4 ? 'var(--green)' : result.score >= 3 ? 'var(--blue)' : 'oklch(55% 0.18 30)';
    const bg    = result.score >= 4 ? 'var(--green-soft)' : 'var(--paper-2)';
    return (
      <div className="fade-up paper-card p-3 mt-3" style={{ borderLeft: `2px solid ${color}`, background: bg }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8 }}>
          <div style={{ fontSize: '1.4rem', fontWeight: 600, color }}>{result.score}/5</div>
          <div className="mono" style={{ fontSize: '0.72rem', color: 'var(--ink-3)' }}>
            {result.score >= 4 ? 'eligible to send' : result.score >= 3 ? 'close · consider revising' : 'revise before sending'}
          </div>
        </div>
        <div style={{ fontStyle: 'italic', fontSize: '0.92rem', marginBottom: 10 }}>{result.verdict}</div>

        {result.got_right.length > 0 && (
          <div style={{ marginBottom: 8 }}>
            <div className="micro mb-1" style={{ color: 'var(--green)' }}>got right</div>
            <ul style={{ margin: 0, paddingLeft: 18, fontSize: '0.85rem', lineHeight: 1.5 }}>
              {result.got_right.map((x, i) => <li key={i}>{x}</li>)}
            </ul>
          </div>
        )}
        {result.missed.length > 0 && (
          <div style={{ marginBottom: 8 }}>
            <div className="micro mb-1" style={{ color: 'oklch(55% 0.18 30)' }}>missed</div>
            <ul style={{ margin: 0, paddingLeft: 18, fontSize: '0.85rem', lineHeight: 1.5 }}>
              {result.missed.map((x, i) => <li key={i}>{x}</li>)}
            </ul>
          </div>
        )}
        {result.added_your_own.length > 0 && (
          <div style={{ marginBottom: 8 }}>
            <div className="micro mb-1" style={{ color: 'oklch(55% 0.18 60)' }}>slipped back into your own frame</div>
            <ul style={{ margin: 0, paddingLeft: 18, fontSize: '0.85rem', lineHeight: 1.5 }}>
              {result.added_your_own.map((x, i) => <li key={i}>{x}</li>)}
            </ul>
          </div>
        )}

        <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
          <button className="btn btn-sm btn-primary" onClick={onSend}>
            send this version to them
          </button>
          <button className="btn btn-sm" onClick={onRevise}>
            revise before sending
          </button>
        </div>
      </div>
    );
  }

  function SubjectReviewCard({ attempt, idx, isLatest, onAccept, onPushback }) {
    const [showPushback, setShowPushback] = useState(false);
    const [pushText, setPushText] = useState('');
    const bg = attempt.status === 'accepted' ? 'var(--green-soft)'
             : attempt.status === 'pushback'  ? 'var(--red-soft)'
             : 'var(--paper-2)';
    const border = attempt.status === 'accepted' ? 'var(--green)'
                : attempt.status === 'pushback'  ? 'var(--red)'
                : 'var(--rule)';
    return (
      <div className="paper-card p-3 mb-2" style={{ background: bg, borderLeft: `2px solid ${border}` }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
          <div className="mono" style={{ fontSize: '0.7rem', color: 'var(--ink-3)' }}>attempt #{idx + 1} · judge {attempt.score}/5</div>
          {attempt.status === 'accepted' && <span className="stamp stamp-green" style={{ fontSize: '0.58rem' }}>accepted</span>}
          {attempt.status === 'pushback' && <span className="stamp" style={{ fontSize: '0.58rem', background: 'var(--red)' }}>pushback</span>}
          {attempt.status === 'needs_review' && <span className="mono" style={{ fontSize: '0.66rem' }}>your turn</span>}
        </div>
        <div style={{ fontSize: '0.95rem', lineHeight: 1.55, whiteSpace: 'pre-wrap', marginBottom: 10 }}>{attempt.text}</div>
        {attempt.push_back && (
          <div className="mt-2" style={{ borderLeft: '2px solid var(--red)', paddingLeft: 8, fontStyle: 'italic', fontSize: '0.85rem' }}>
            you pushed back: {attempt.push_back}
          </div>
        )}

        {isLatest && attempt.status === 'needs_review' && (
          <div>
            {!showPushback ? (
              <div style={{ display: 'flex', gap: 8, marginTop: 8 }}>
                <button className="btn btn-sm btn-primary" onClick={onAccept}>yes · you got me</button>
                <button className="btn btn-sm" onClick={() => setShowPushback(true)}>push back · they missed something</button>
              </div>
            ) : (
              <div style={{ marginTop: 8 }}>
                <textarea
                  className="paper-input"
                  rows={2}
                  placeholder="one line · what did they miss? they'll try again."
                  value={pushText}
                  onChange={e => setPushText(e.target.value)}
                />
                <div style={{ display: 'flex', gap: 8, marginTop: 8 }}>
                  <button className="btn btn-sm btn-primary" disabled={!pushText.trim()} onClick={() => onPushback(pushText.trim())}>
                    send pushback
                  </button>
                  <button className="btn btn-sm" onClick={() => { setShowPushback(false); setPushText(''); }}>cancel</button>
                </div>
              </div>
            )}
          </div>
        )}
      </div>
    );
  }

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