// Phase 00 · Style Lock — host picks conversation style, guest co-signs.
// Sets `shared.style = { voice, asymmetry, directness, signedA, signedB, signedAt }`.
// Once both sign, style is immutable for the session.
// Depends on: CG, Icons

const STYLE_OPTIONS = {
  voice: [
    { v: 'warm-informal', label: 'warm · informal',  hint: 'wise friend · plain, lowercase-ish · "what\'s actually going on here?"' },
    { v: 'warm-clinical', label: 'warm · clinical',  hint: 'steady therapist · measured, named feelings · "it sounds like there\'s a pattern."' },
    { v: 'dry-neutral',   label: 'dry · neutral',    hint: 'court reporter with opinions · short, no flourish · "the asymmetry is on record."' },
  ],
  asymmetry: [
    { v: 'truth-seeking', label: 'truth-seeking',    hint: 'if one party is more responsible, the mediator will name it. no forced balance.' },
    { v: 'symmetric',     label: 'symmetric',        hint: 'both sides treated equally in tone & framing. fault is not weighed.' },
    { v: 'hybrid',        label: 'hybrid',           hint: 'asymmetry may be named — but only when both of you would co-sign that observation.' },
  ],
  directness: [
    { v: 'soften',    label: 'soften the edges',     hint: 'hard truths only after gentle setup. the coach will never bluntly contradict you.' },
    { v: 'plain',     label: 'plain',                hint: 'the coach says what it sees without padding. no escalation either.' },
    { v: 'challenge', label: 'challenge me',         hint: 'the coach will push back on characterizations and kitchen-sinking directly.' },
  ],
};

const STYLE_DEFAULTS = { voice: 'warm-informal', asymmetry: 'hybrid', directness: 'plain' };

function StyleLockPhase({ seat, onPhase }) {
  const [, forceTick] = React.useState(0);
  React.useEffect(() => CG.session.onState(() => forceTick(t => t + 1)), []);
  React.useEffect(() => CG.onStatus(() => forceTick(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 isGuest = mp && seat === 'B';

  const nameA = names.A || (mp ? 'host' : 'host');
  const nameB = names.B || (mp ? 'guest' : 'guest');

  // Host-side draft (pre-sign). Seeded from shared.style if partially set, else defaults.
  const [draft, setDraft] = React.useState(() => {
    if (shared.style) return { voice: shared.style.voice, asymmetry: shared.style.asymmetry, directness: shared.style.directness };
    return { ...STYLE_DEFAULTS };
  });

  // The locked/signed style lives in shared.style. A null style means nothing proposed yet.
  const proposed = shared.style;                 // { voice, asymmetry, directness, signedA, signedB, ... } | null
  const hostSigned = !!(proposed && proposed.signedA);
  const guestSigned = !!(proposed && proposed.signedB);
  const bothSigned = hostSigned && guestSigned;

  // Host · propose & sign (in solo, also auto-co-sign so user can proceed)
  const hostPropose = () => {
    const style = {
      voice: draft.voice,
      asymmetry: draft.asymmetry,
      directness: draft.directness,
      signedA: true,
      signedB: !mp, // solo: auto-co-sign as "both parties"
      signedAt: new Date().toISOString(),
    };
    CG.session.setShared({ style });
  };

  // Guest · co-sign what host proposed
  const guestCosign = () => {
    if (!proposed) return;
    // Guest sends a patch up to host; host-authoritative setShared also runs via data channel.
    CG.session.setShared({
      style: { ...proposed, signedB: true, signedAt: proposed.signedAt },
    });
  };

  // Guest · request a change (wipes host signature so host can re-propose)
  const guestRequestChange = () => {
    if (!proposed) return;
    CG.session.setShared({ style: null });
  };

  const continueToTopic = () => { onPhase && onPhase('topic'); };

  // Presence: broadcast what this user is doing within the style phase
  React.useEffect(() => {
    let activity = 'drafting style';
    if (bothSigned) activity = 'reviewing · locked';
    else if (isHost && hostSigned && !guestSigned) activity = `waiting on ${nameB}`;
    else if (isGuest && hostSigned && !guestSigned) activity = 'reviewing proposal';
    else if (isGuest && !hostSigned) activity = `waiting on ${nameA}`;
    else if (isHost && !hostSigned) activity = 'drafting style';
    try { CG.session.setCursor && CG.session.setCursor({ activity }); } catch (e) {}
  }, [bothSigned, hostSigned, guestSigned, isHost, isGuest, nameA, nameB]);

  // ---- VIEWS ----

  if (bothSigned) {
    return (
      <StyleLockedCard style={proposed} nameA={nameA} nameB={nameB} onContinue={continueToTopic} />
    );
  }

  // Solo (no peer yet) or host seat · host proposes
  if (isHost && !hostSigned) {
    return (
      <HostProposeView
        draft={draft}
        setDraft={setDraft}
        onSign={hostPropose}
        mp={mp}
        nameA={nameA}
        nameB={nameB}
      />
    );
  }

  // Host has signed, waiting on guest (but we're host)
  if (isHost && hostSigned && !guestSigned) {
    return (
      <HostWaitingView style={proposed} nameA={nameA} nameB={nameB} onWithdraw={guestRequestChange} />
    );
  }

  // Guest view · waiting for host to propose
  if (isGuest && !proposed) {
    return <GuestWaitingView nameA={nameA} />;
  }

  // Guest view · host has proposed, guest decides
  if (isGuest && proposed && !guestSigned) {
    return (
      <GuestCosignView style={proposed} nameA={nameA} nameB={nameB} onCosign={guestCosign} onRequestChange={guestRequestChange} />
    );
  }

  // Fallback
  return <div style={{ padding: 40 }}>loading…</div>;
}

// ---------- HOST · PROPOSE ----------

function HostProposeView({ draft, setDraft, onSign, mp, nameA, nameB }) {
  const canSign = draft.voice && draft.asymmetry && draft.directness;

  return (
    <div style={{ padding: '28px 40px 60px', maxWidth: 920, margin: '0 auto' }}>
      <div className="tiny">phase 00 · pre-room · style</div>
      <h1 style={{ marginTop: 6, marginBottom: 6 }}>set the tone before you start.</h1>
      <p style={{ maxWidth: 640, color: 'var(--ink-2)', marginBottom: 22, lineHeight: 1.5 }}>
        three choices shape how the agents in this session talk. pick them now, together, once.{' '}
        <span className="hand" style={{ color: 'var(--blue)' }}>
          once co-signed, the style is locked for the whole session — no quiet mid-argument edits.
        </span>
      </p>

      <StyleKnobGroup title="voice" k="voice" value={draft.voice} onChange={v => setDraft({ ...draft, voice: v })} />
      <StyleKnobGroup title="asymmetry policy" k="asymmetry" value={draft.asymmetry} onChange={v => setDraft({ ...draft, asymmetry: v })} />
      <StyleKnobGroup title="directness" k="directness" value={draft.directness} onChange={v => setDraft({ ...draft, directness: v })} />

      <div className="dashed" style={{ margin: '20px 0' }} />
      <div className="paper-card p-3" style={{ background: 'var(--paper-2)', marginBottom: 18 }}>
        <div className="tiny mb-2">what this produces</div>
        <StylePreamblePreview draft={draft} />
      </div>

      <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
        <button className="btn btn-primary" disabled={!canSign} onClick={onSign}>
          <Icons.Stamp size={12} /> sign as {nameA} {mp ? `· send to ${nameB}` : '· continue'}
        </button>
        <div className="micro" style={{ textTransform: 'none', letterSpacing: 0, color: 'var(--ink-3)' }}>
          {mp
            ? <>{nameB} will see your proposal and can co-sign or request a change.</>
            : <>solo mode · you're co-signing on both parties' behalf.</>}
        </div>
      </div>
    </div>
  );
}

// ---------- HOST · WAITING ----------

function HostWaitingView({ style, nameA, nameB, onWithdraw }) {
  return (
    <div style={{ padding: '40px', maxWidth: 760, margin: '0 auto' }}>
      <div className="tiny">phase 00 · waiting on {nameB}</div>
      <h1 style={{ marginTop: 6, marginBottom: 6, fontWeight: 500 }}>signed · waiting for {nameB} to co-sign.</h1>
      <p style={{ color: 'var(--ink-2)', maxWidth: 600 }}>
        they see your proposal below. if they request a change, you can re-propose.
      </p>
      <div className="dashed" style={{ margin: '18px 0' }} />
      <StyleSummaryCard style={style} />
      <div className="dashed" style={{ margin: '18px 0' }} />
      <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
        <span className="stamp stamp-green">signed · {nameA}</span>
        <span className="mono" style={{ color: 'var(--ink-3)' }}>waiting on {nameB}…</span>
        <div style={{ flex: 1 }} />
        <button className="btn btn-sm" onClick={onWithdraw}>withdraw &amp; edit</button>
      </div>
    </div>
  );
}

// ---------- GUEST · WAITING ----------

function GuestWaitingView({ nameA }) {
  return (
    <div style={{ padding: '40px', maxWidth: 720, margin: '0 auto' }}>
      <div className="tiny">phase 00 · waiting on {nameA}</div>
      <h1 style={{ marginTop: 6, marginBottom: 6, fontWeight: 500 }}>{nameA} is setting the tone.</h1>
      <p style={{ color: 'var(--ink-2)', maxWidth: 600, lineHeight: 1.55 }}>
        before the room opens, the host picks three knobs — voice, asymmetry policy, directness — and proposes them to you. you co-sign, or request a change. neither of you can edit mid-session.
      </p>
      <div className="paper-card p-3 mt-3" style={{ background: 'var(--paper-2)', maxWidth: 520 }}>
        <div className="tiny">status</div>
        <div className="mono" style={{ fontSize: '0.85rem', color: 'var(--ink-3)', marginTop: 4 }}>
          waiting for proposal…
        </div>
      </div>
    </div>
  );
}

// ---------- GUEST · CO-SIGN ----------

function GuestCosignView({ style, nameA, nameB, onCosign, onRequestChange }) {
  return (
    <div style={{ padding: '28px 40px 60px', maxWidth: 920, margin: '0 auto' }}>
      <div className="tiny">phase 00 · pre-room · co-sign</div>
      <h1 style={{ marginTop: 6, marginBottom: 6 }}>{nameA} proposes this style.</h1>
      <p style={{ maxWidth: 640, color: 'var(--ink-2)', marginBottom: 22, lineHeight: 1.5 }}>
        read what this will actually do to the agents (below), and either co-sign as {nameB} or send it back for a rework.
      </p>

      <StyleSummaryCard style={style} highlight />

      <div className="paper-card p-3" style={{ background: 'var(--paper-2)', marginTop: 18, marginBottom: 22 }}>
        <div className="tiny mb-2">what the agents will be told</div>
        <StylePreamblePreview draft={style} />
      </div>

      <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
        <button className="btn btn-primary" onClick={onCosign}>
          <Icons.Stamp size={12} /> co-sign as {nameB}
        </button>
        <button className="btn" onClick={onRequestChange}>
          request change · send back to {nameA}
        </button>
      </div>
    </div>
  );
}

// ---------- LOCKED ----------

function StyleLockedCard({ style, nameA, nameB, onContinue }) {
  return (
    <div style={{ padding: '40px', maxWidth: 820, margin: '0 auto' }}>
      <div className="ink-in paper-card p-4" style={{ position: 'relative', background: 'var(--paper-2)' }}>
        <div className="tape" style={{ top: -8, left: 36, transform: 'rotate(-3deg)' }} />
        <div className="tape" style={{ top: -8, right: 50, transform: 'rotate(2deg)' }} />
        <div style={{ textAlign: 'center' }}>
          <div className="tiny" style={{ color: 'var(--green)' }}>style locked</div>
          <div style={{ maxWidth: 520, margin: '14px auto 0' }}>
            <StyleSummaryCard style={style} center />
          </div>
          <div style={{ display: 'flex', gap: 10, justifyContent: 'center', marginTop: 18 }}>
            <span className="stamp stamp-green">signed · {nameA}</span>
            <span className="stamp stamp-green">signed · {nameB}</span>
          </div>
          <div className="hand" style={{ color: 'var(--blue)', fontSize: '1.15rem', marginTop: 20 }}>
            the agents now speak in your agreed voice. on to the topic.
          </div>
          <button className="btn btn-primary mt-3" onClick={onContinue}>
            continue → phase 01 · lock the topic <Icons.Arrow size={10} />
          </button>
        </div>
      </div>
    </div>
  );
}

// ---------- atoms ----------

function StyleKnobGroup({ title, k, value, onChange }) {
  const opts = STYLE_OPTIONS[k] || [];
  return (
    <div style={{ marginBottom: 18 }}>
      <div className="tiny mb-2">{title}</div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10 }}>
        {opts.map(o => {
          const active = value === o.v;
          return (
            <div
              key={o.v}
              onClick={() => onChange(o.v)}
              style={{
                cursor: 'pointer',
                padding: 12,
                border: active ? '1.5px solid var(--ink)' : '1px dashed var(--rule)',
                background: active ? 'var(--paper-2)' : 'transparent',
                transition: 'all 0.15s',
                position: 'relative',
              }}
            >
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
                <div className="mono" style={{ fontSize: '0.75rem', letterSpacing: '0.04em', textTransform: 'uppercase' }}>
                  {o.label}
                </div>
                {active && <ScribbleCheck />}
              </div>
              <div className="micro" style={{ textTransform: 'none', letterSpacing: 0, marginTop: 6, color: 'var(--ink-3)', lineHeight: 1.4 }}>
                {o.hint}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function StyleSummaryCard({ style, highlight, center }) {
  const voice = STYLE_OPTIONS.voice.find(o => o.v === style.voice);
  const asym = STYLE_OPTIONS.asymmetry.find(o => o.v === style.asymmetry);
  const direct = STYLE_OPTIONS.directness.find(o => o.v === style.directness);
  const rows = [
    { k: 'voice', v: voice },
    { k: 'asymmetry', v: asym },
    { k: 'directness', v: direct },
  ];
  return (
    <div className="paper-card p-3" style={{ borderLeft: highlight ? '3px solid var(--ink)' : undefined, textAlign: center ? 'center' : 'left' }}>
      {rows.map((r, i) => (
        <div key={r.k} style={{
          display: center ? 'block' : 'grid',
          gridTemplateColumns: '130px 1fr',
          gap: 12,
          padding: '6px 0',
          borderTop: i === 0 ? 'none' : '1px dashed var(--rule)',
        }}>
          <div className="mono" style={{ fontSize: '0.7rem', letterSpacing: '0.05em', textTransform: 'uppercase', color: 'var(--ink-3)' }}>
            {r.k}
          </div>
          <div style={{ fontSize: '0.92rem' }}>
            <b>{r.v ? r.v.label : '—'}</b>
            {r.v && <span className="micro" style={{ textTransform: 'none', letterSpacing: 0, color: 'var(--ink-3)', marginLeft: center ? 0 : 8, display: center ? 'block' : 'inline', marginTop: center ? 2 : 0 }}>
              — {r.v.hint}
            </span>}
          </div>
        </div>
      ))}
    </div>
  );
}

function StylePreamblePreview({ draft }) {
  const text = CG.buildStylePreamble
    ? CG.buildStylePreamble({ ...draft, signedA: true, signedB: true })
    : '';
  return (
    <pre style={{
      fontFamily: 'var(--font-mono)',
      fontSize: '0.72rem',
      lineHeight: 1.5,
      color: 'var(--ink-2)',
      whiteSpace: 'pre-wrap',
      margin: 0,
    }}>
      {text.trim() || '(pick all three to preview)'}
    </pre>
  );
}

Object.assign(window, { StyleLockPhase });
console.log('[phases-style] loaded');
