// Invite / join UI — room code generation, pasting, connection status.
// Depends on: CG.peer, CG.session, CG.newRoomCode

function RoomChip({ onClick }) {
  const [, force] = React.useState(0);
  React.useEffect(() => {
    const u1 = CG.peer.onStatus(() => force(t => t + 1));
    const u2 = CG.session.onState(() => force(t => t + 1));
    return () => { u1(); u2(); };
  }, []);
  const s = CG.peer.status();
  const seat = CG.session.getSeat();
  const myName = CG.session.getMyName() || (seat === 'A' ? 'maya' : 'jordan');

  let label, color, dot;
  if (s.state === 'connected') {
    label = (seat === 'A' ? 'hosting · ' : 'joined · ') + myName;
    color = seat === 'A' ? 'var(--ink)' : 'oklch(42% 0.12 240)';
    dot = 'var(--green)';
  } else if (s.state === 'waiting') {
    label = 'waiting for partner…';
    color = 'var(--ink)'; dot = 'var(--amber, oklch(65% 0.17 75))';
  } else if (s.state === 'connecting' || s.state === 'opening' || s.state === 'reconnecting') {
    label = s.state;
    color = 'var(--ink-3)'; dot = 'var(--ink-3)';
  } else if (s.state === 'error') {
    label = 'room error';
    color = 'var(--red)'; dot = 'var(--red)';
  } else {
    label = 'host or join a room';
    color = 'var(--ink)'; dot = 'var(--ink-3)';
  }

  return (
    <button
      className="btn btn-sm"
      onClick={onClick}
      title={s.state === 'connected' ? 'room code ' + s.roomCode : 'open room modal'}
      style={{ borderColor: color, color }}
    >
      <span style={{
        width: 7, height: 7, borderRadius: '50%',
        background: dot, display: 'inline-block',
        boxShadow: s.state === 'connected' ? `0 0 0 2px ${dot}33` : 'none',
      }} />
      {label}
    </button>
  );
}

function RoomModal({ open, onClose }) {
  const [, force] = React.useState(0);
  React.useEffect(() => {
    const u1 = CG.peer.onStatus(() => force(t => t + 1));
    const u2 = CG.session.onState(() => force(t => t + 1));
    return () => { u1(); u2(); };
  }, []);
  const [joinCode, setJoinCode] = React.useState('');
  const [hostName, setHostName] = React.useState(() => CG.session.myName || '');
  const [guestName, setGuestName] = React.useState(() => CG.session.myName || '');
  const [copied, setCopied] = React.useState(false);
  const lastRoom = CG.session.getLastRoom();

  if (!open) return null;
  const s = CG.peer.status();
  const connected = s.state === 'connected';
  const names = CG.session.getNames();

  const onHost = async () => {
    if (!CG.hasKey()) { alert('connect your Anthropic key first · click "connect claude"'); return; }
    const name = hostName.trim();
    if (!name) { alert('enter your name first'); return; }
    await CG.resume.hardReset(); // clear shared + ledger + threads + logs + phase
    CG.session.setMyName(name);
    const code = CG.newRoomCode();
    await CG.peer.host(code);
  };
  const onResume = async () => {
    if (!CG.hasKey()) { alert('connect your Anthropic key first · click "connect claude"'); return; }
    const name = hostName.trim();
    if (!name) { alert('enter your name first'); return; }
    if (!lastRoom) return;
    CG.session.setMyName(name);
    CG.session.restoreShared(lastRoom.code);
    await CG.peer.host(lastRoom.code);
  };
  const onJoin = async () => {
    const name = guestName.trim();
    if (!name) { alert('enter your name first'); return; }
    const c = joinCode.trim().toLowerCase();
    if (!c) return;
    await CG.resume.hardReset(); // clear stale ledger/threads/shared — host's sync will arrive shortly
    CG.session.setMyName(name);
    await CG.peer.join(c);
  };
  const onCopy = async () => {
    try { await navigator.clipboard.writeText(s.roomCode); setCopied(true); setTimeout(() => setCopied(false), 1500); } catch {}
  };
  const onLeave = () => { CG.peer.disconnect(); };

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, zIndex: 50,
      background: 'oklch(20% 0.02 60 / 0.35)',
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 24,
    }}>
      <div onClick={e => e.stopPropagation()} className="paper-card" style={{ maxWidth: 540, width: '100%', padding: 28, position: 'relative' }}>
        <div className="tape" style={{ top: -8, left: 36, transform: 'rotate(-3deg)' }} />
        <div className="tiny" style={{ marginBottom: 4 }}>two-browser session</div>
        <h2 style={{ margin: '0 0 4px', fontSize: '1.4rem' }}>invite your partner into the room.</h2>
        <p className="micro" style={{ textTransform: 'none', letterSpacing: 0, lineHeight: 1.45, color: 'var(--ink-3)', marginBottom: 18 }}>
          browser-to-browser over an encrypted data channel. <b>host</b> funds Claude calls with their key · <b>guest</b> never sees it.
        </p>

        {connected ? (
          <>
            <div style={{ padding: 16, background: 'var(--green-soft)', borderLeft: '2px solid var(--green)', marginBottom: 14 }}>
              <div className="tiny" style={{ color: 'var(--green)', marginBottom: 4 }}>connected</div>
              <div style={{ fontSize: '0.95rem', lineHeight: 1.4 }}>
                you are <b>{s.role === 'host' ? names.A : names.B}</b> (seat {s.role === 'host' ? 'A · host' : 'B · guest'}) in room <span className="mono">{s.roomCode}</span>.
              </div>
              <div className="micro" style={{ textTransform: 'none', letterSpacing: 0, color: 'var(--ink-3)', marginTop: 6 }}>
                partner: {s.role === 'host' ? (names.B || '—') : (names.A || '—')}
              </div>
            </div>
            <button className="btn" onClick={onLeave}>leave room</button>
            <button className="btn btn-sm" onClick={onClose} style={{ marginLeft: 8 }}>close</button>
          </>
        ) : s.state === 'waiting' && s.role === 'host' ? (
          <>
            <div style={{ padding: 18, background: 'var(--paper-2)', marginBottom: 14, textAlign: 'center' }}>
              <div className="tiny" style={{ marginBottom: 8 }}>share this code with {hostName ? 'your partner' : 'the joiner'}</div>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: '2.2rem', letterSpacing: '0.08em', fontWeight: 600 }}>
                {s.roomCode}
              </div>
              <button className="btn btn-sm mt-2" onClick={onCopy}>{copied ? '✓ copied' : 'copy code'}</button>
            </div>
            <div className="micro" style={{ textTransform: 'none', letterSpacing: 0, color: 'var(--ink-3)', marginBottom: 14, lineHeight: 1.4 }}>
              waiting for your partner to join… they open Clarguments on their end and enter this code.
            </div>
            <button className="btn" onClick={onLeave}>cancel</button>
            <button className="btn btn-sm" onClick={onClose} style={{ marginLeft: 8 }}>close</button>
          </>
        ) : s.state === 'error' ? (
          <>
            <div style={{ padding: '10px 12px', background: 'oklch(93% 0.05 25)', borderLeft: '2px solid var(--red)', marginBottom: 14, fontSize: '0.85rem' }}>{s.error}</div>
            <button className="btn" onClick={onLeave}>try again</button>
          </>
        ) : (
          <>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14, marginBottom: 14 }}>
              {/* host */}
              <div style={{ padding: 14, border: '1px dashed var(--rule)' }}>
                <div className="tiny" style={{ marginBottom: 6 }}>host a room</div>
                <div className="micro" style={{ textTransform: 'none', letterSpacing: 0, lineHeight: 1.4, color: 'var(--ink-3)', marginBottom: 10 }}>
                  you get a code to share. seat A · your Claude key funds both sides.
                </div>
                <input className="paper-input" placeholder="your name" value={hostName} onChange={e => setHostName(e.target.value)} style={{ marginBottom: 8, fontSize: '0.85rem' }} />
                <button className="btn btn-primary btn-sm" onClick={onHost} disabled={!CG.hasKey() || !hostName.trim()} title={CG.hasKey() ? '' : 'connect claude first'}>
                  host · start a room
                </button>
                {!CG.hasKey() && (<div className="micro mt-2" style={{ textTransform: 'none', letterSpacing: 0, color: 'var(--red)' }}>connect your Claude key first.</div>)}
                {lastRoom && CG.hasKey() && (
                  <div style={{ marginTop: 10, paddingTop: 10, borderTop: '1px dashed var(--rule)' }}>
                    <div className="micro mb-1" style={{ textTransform: 'none', letterSpacing: 0, color: 'var(--ink-3)' }}>
                      last session · room <span className="mono">{lastRoom.code}</span>
                    </div>
                    <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
                      <button className="btn btn-sm" onClick={onResume} disabled={!hostName.trim()}>
                        resume · re-host {lastRoom.code}
                      </button>
                      <button
                        className="btn btn-sm btn-ghost"
                        style={{ fontSize: '0.7rem', color: 'var(--ink-3)' }}
                        onClick={async () => { await CG.resume.hardReset(); force(t => t + 1); }}
                      >
                        start fresh
                      </button>
                    </div>
                  </div>
                )}
              </div>

              {/* join */}
              <div style={{ padding: 14, border: '1px dashed var(--rule)' }}>
                <div className="tiny" style={{ marginBottom: 6 }}>join a room</div>
                <div className="micro" style={{ textTransform: 'none', letterSpacing: 0, lineHeight: 1.4, color: 'var(--ink-3)', marginBottom: 10 }}>
                  your partner shared a code. seat B · no key needed.
                </div>
                <input className="paper-input" placeholder="your name" value={guestName} onChange={e => setGuestName(e.target.value)} style={{ marginBottom: 8, fontSize: '0.85rem' }} />
                <input className="paper-input" placeholder="room code" value={joinCode} onChange={e => setJoinCode(e.target.value)} style={{ fontFamily: 'var(--font-mono)', fontSize: '0.9rem', marginBottom: 8 }} />
                <button className="btn btn-primary btn-sm" onClick={onJoin} disabled={!joinCode.trim() || !guestName.trim() || s.state !== 'idle'}>
                  join →
                </button>
              </div>
            </div>
            <button className="btn btn-sm" onClick={onClose}>close</button>
          </>
        )}
      </div>
    </div>
  );
}

// Small banner that shows when the peer drops — used inside the app layout
function DisconnectBanner() {
  const [, force] = React.useState(0);
  React.useEffect(() => CG.peer.onStatus(() => force(t => t + 1)), []);
  const s = CG.peer.status();
  if (s.state !== 'reconnecting') return null;
  return (
    <div style={{
      padding: '8px 16px',
      background: 'oklch(94% 0.07 75)',
      borderBottom: '1px solid oklch(70% 0.15 75)',
      fontSize: '0.85rem',
      display: 'flex', alignItems: 'center', gap: 10,
    }}>
      <span className="blink-dot" style={{ width: 8, height: 8, borderRadius: '50%', background: 'oklch(65% 0.17 75)', animation: 'blink 1.2s infinite' }} />
      partner disconnected · room is frozen · waiting for reconnect…
    </div>
  );
}

// Credits chip — only shows for guest when connected
function CreditsChip() {
  const [, force] = React.useState(0);
  React.useEffect(() => {
    const id = setInterval(() => force(t => t + 1), 1000);
    const u = CG.session.onState(() => force(t => t + 1));
    return () => { clearInterval(id); u(); };
  }, []);
  if (!CG.session.isGuest()) return null;
  const c = CG.session.getCreditsInfo();
  return (
    <div className="mono" style={{
      padding: '4px 8px', fontSize: '0.68rem',
      border: '1px solid var(--rule)',
      background: c.rateOk ? 'var(--paper-2)' : 'oklch(94% 0.07 75)',
      color: c.rateOk ? 'var(--ink-3)' : 'oklch(55% 0.17 75)',
    }} title={`${c.recentInWindow}/${c.rateMax} in the last ${c.windowMs/1000}s · ${c.used}/${c.cap} this session`}>
      claude credits · {c.used}/{c.cap}
    </div>
  );
}

Object.assign(window, { RoomChip, RoomModal, DisconnectBanner, CreditsChip });
