// screens-roleplay.jsx — Role-play scenarios.
// Pre-baked scenarios + a custom option. AI stays in character; learner
// practices conversational Chinese in a focused context.

function RolePlayScreen({ theme, mascotOn, onTab, nav }) {
  const [scenario, setScenario] = React.useState(null);
  // Per-scenario state. When scenario is null, the picker is shown.

  if (!scenario) {
    return <RolePlayPicker theme={theme} mascotOn={mascotOn} onPick={setScenario} onTab={onTab} nav={nav}/>;
  }
  return (
    <RolePlayChat theme={theme} mascotOn={mascotOn} scenario={scenario}
                  onExit={() => setScenario(null)} onTab={onTab}/>
  );
}

function RolePlayPicker({ theme, mascotOn, onPick, onTab, nav }) {
  const hasKey = orHasKey();

  return (
    <Screen theme={theme}>
      <div style={{ padding: '54px 16px 12px' }}>
        <button onClick={() => onTab('home')} style={{
          all: 'unset', cursor: 'pointer',
          fontFamily: theme.fontBody, fontSize: 12, color: theme.fgMute,
          letterSpacing: '0.1em', textTransform: 'uppercase', marginBottom: 8,
          display: 'inline-block',
        }}>← HOME</button>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
          {mascotOn && <Mascot theme={theme} mood="excited" size={64}/>}
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: theme.fontBody, fontSize: 11, letterSpacing: '0.15em', color: theme.fgMute, textTransform: 'uppercase' }}>
              REAL CONVERSATIONS
            </div>
            <H theme={theme} size={28}>ROLE-PLAY</H>
            <div style={{
              width: 80, height: 6,
              background: `repeating-linear-gradient(90deg, ${theme.primary} 0 8px, transparent 8px 12px)`,
              marginTop: 4,
            }} />
          </div>
        </div>
        <div style={{ fontFamily: theme.fontBody, fontSize: 12, color: theme.fgMute, lineHeight: 1.5, marginTop: 12 }}>
          Pick a scene. I stay in character — you practice replying in Chinese (pinyin OK if no IME).
        </div>
      </div>

      <div style={{ flex: 1, overflowY: 'auto', padding: '8px 16px 16px', display: 'flex', flexDirection: 'column', gap: 10 }}>
        {!hasKey && (
          <div style={{
            background: theme.yellow, color: theme.fg,
            border: `2px solid ${theme.fg}`, borderRadius: theme.radius,
            padding: 12, fontFamily: theme.fontBody, fontSize: 12, lineHeight: 1.4,
            boxShadow: `0 3px 0 0 ${theme.fg}`,
          }}>
            <div style={{ fontFamily: theme.fontHead, fontSize: 13, fontWeight: 700, marginBottom: 4 }}>NEEDS AN API KEY</div>
            Role-play uses your OpenRouter key. Add one in Settings to start.
          </div>
        )}
        {SCENARIOS.map((s) => (
          <button key={s.id} onClick={() => hasKey && onPick(s)} disabled={!hasKey} style={{
            all: 'unset', cursor: hasKey ? 'pointer' : 'not-allowed',
            background: theme.surface, color: theme.fg,
            border: `2px solid ${theme.fg}`, borderRadius: theme.radius,
            padding: 14,
            boxShadow: `0 3px 0 0 ${({primary:theme.primary, cyan:theme.cyan, yellow:theme.yellow, red:theme.red, green:theme.green}[s.color] || theme.primary)}`,
            display: 'flex', alignItems: 'center', gap: 14,
            opacity: hasKey ? 1 : 0.55,
          }}>
            <div style={{
              width: 54, height: 54, fontSize: 30, lineHeight: 1,
              background: ({primary:theme.primary, cyan:theme.cyan, yellow:theme.yellow, red:theme.red, green:theme.green}[s.color] || theme.primary),
              border: `2px solid ${theme.fg}`, borderRadius: theme.radius * 0.6,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              flexShrink: 0,
            }}>{s.emoji}</div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontFamily: theme.fontDisplay, fontSize: 18, lineHeight: 1 }}>{s.title}</div>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 6, marginTop: 4 }}>
                <CN theme={theme} size={14} color={theme.primary}>{s.cn}</CN>
                {s.custom && (
                  <span style={{
                    fontFamily: theme.fontBody, fontSize: 9, fontWeight: 700,
                    color: theme.bg, background: theme.cyan,
                    border: `1.5px solid ${theme.fg}`, padding: '1px 5px',
                    borderRadius: 999, letterSpacing: '0.08em', textTransform: 'uppercase',
                  }}>AI</span>
                )}
              </div>
            </div>
            <div style={{
              width: 32, height: 32, background: theme.fg, color: theme.surface,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              borderRadius: 999, flexShrink: 0, fontFamily: theme.fontDisplay,
            }}>▶</div>
          </button>
        ))}
      </div>

      <TabBar theme={theme} tab="home" onTab={onTab}/>
    </Screen>
  );
}

function RolePlayChat({ theme, mascotOn, scenario, onExit, onTab }) {
  const [customScene, setCustomScene] = React.useState('');
  const [started, setStarted] = React.useState(!scenario.custom);
  const [messages, setMessages] = React.useState([]);
  const [input, setInput] = React.useState('');
  const [sending, setSending] = React.useState(false);
  const [streaming, setStreaming] = React.useState('');
  const [error, setError] = React.useState(null);
  const [ending, setEnding] = React.useState(false);
  const [recap, setRecap] = React.useState(null);
  const scrollRef = React.useRef(null);
  const abortRef = React.useRef(null);

  // Resolve persona + opener. For custom, build from user input on Start.
  const [persona, setPersona] = React.useState(scenario.persona);
  const [opener, setOpener] = React.useState(scenario.opener);

  React.useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages, streaming, recap]);

  // Auto-fire AI opener on first mount (or after Start for custom).
  React.useEffect(() => {
    if (!started || messages.length > 0 || sending || recap) return;
    sendOpener();
    // eslint-disable-next-line
  }, [started]);

  const sendOpener = async () => {
    setSending(true); setError(null); setStreaming('');
    const controller = new AbortController(); abortRef.current = controller;
    try {
      const sys = `${ROLEPLAY_SYSTEM}\n\nSCENARIO: ${persona}\n\nOPEN with a single in-character greeting (1 Chinese line, with pinyin and english).`;
      const full = await orChatStream({
        messages: [
          { role: 'system', content: sys },
          { role: 'user', content: `(Open the scene now.) Setting: ${opener || 'A short everyday situation.'}` },
        ],
        temperature: 0.7, max_tokens: 250,
        signal: controller.signal,
        onToken: (_d, full) => setStreaming(full),
      });
      setMessages([{ role: 'assistant', content: full }]);
      setStreaming('');
    } catch (e) {
      if (e.name !== 'AbortError') setError(e.message);
      setStreaming('');
    } finally {
      setSending(false);
      abortRef.current = null;
    }
  };

  const send = async () => {
    const text = input.trim();
    if (!text || sending || recap) return;
    const next = [...messages, { role: 'user', content: text }];
    setMessages(next);
    setInput('');
    setSending(true);
    setStreaming('');
    setError(null);
    const controller = new AbortController(); abortRef.current = controller;
    try {
      const sys = `${ROLEPLAY_SYSTEM}\n\nSCENARIO: ${persona}`;
      const orMessages = [
        { role: 'system', content: sys },
        ...next.map((m) => ({ role: m.role, content: m.content })),
      ];
      const full = await orChatStream({
        messages: orMessages,
        temperature: 0.65, max_tokens: 300,
        signal: controller.signal,
        onToken: (_d, full) => setStreaming(full),
      });
      setMessages([...next, { role: 'assistant', content: full }]);
      setStreaming('');
    } catch (e) {
      if (e.name !== 'AbortError') setError(e.message);
      setStreaming('');
    } finally {
      setSending(false);
      abortRef.current = null;
    }
  };

  const stop = () => abortRef.current?.abort();

  const giveHint = async () => {
    if (sending || recap) return;
    setSending(true); setError(null);
    try {
      const transcript = messages.map((m) => `${m.role === 'user' ? 'Learner' : 'NPC'}: ${m.content}`).join('\n');
      const { content } = await orChat({
        messages: [
          { role: 'system', content: HINT_SYSTEM },
          { role: 'user', content: `Scenario: ${persona}\n\nTranscript so far:\n${transcript}\n\nSuggest the learner's NEXT reply.` },
        ],
        temperature: 0.5, max_tokens: 120,
      });
      // Show hint inline by prefilling the input.
      setInput(extractFirstChinese(content) || content);
    } catch (e) {
      setError(e.message);
    } finally {
      setSending(false);
    }
  };

  const endScene = async () => {
    if (sending) stop();
    setEnding(true);
    setError(null);
    try {
      const transcript = messages.map((m) => `${m.role === 'user' ? 'Learner' : 'NPC'}: ${m.content}`).join('\n');
      const { content } = await orChat({
        messages: [
          { role: 'system', content: RECAP_SYSTEM },
          { role: 'user', content: `Scenario: ${persona}\n\nTranscript:\n${transcript}` },
        ],
        temperature: 0.3, max_tokens: 250,
      });
      setRecap(content);
    } catch (e) {
      setError(e.message);
    } finally {
      setEnding(false);
    }
  };

  // ── Custom scenario start screen ───────────────────────────
  if (scenario.custom && !started) {
    return (
      <Screen theme={theme} scroll={false} style={{ padding: '54px 16px 16px' }}>
        <button onClick={onExit} style={{
          all: 'unset', cursor: 'pointer',
          fontFamily: theme.fontBody, fontSize: 12, color: theme.fgMute,
          letterSpacing: '0.1em', textTransform: 'uppercase', marginBottom: 8,
          display: 'inline-block',
        }}>← BACK</button>
        <H theme={theme} size={28}>CUSTOM SCENARIO</H>
        <div style={{ fontFamily: theme.fontBody, fontSize: 12, color: theme.fgMute, lineHeight: 1.5, marginTop: 8, marginBottom: 14 }}>
          Describe a situation in English. I’ll set the scene and play a character in it.
        </div>
        <textarea
          rows={4}
          value={customScene}
          onChange={(e) => setCustomScene(e.target.value)}
          placeholder="e.g. I'm checking into a hotel in Taipei…"
          style={{
            width: '100%', resize: 'none',
            fontFamily: theme.fontBody, fontSize: 14,
            padding: 12,
            background: theme.surface, color: theme.fg,
            border: `2.5px solid ${theme.fg}`, borderRadius: theme.radius,
            outline: 'none', boxShadow: `0 3px 0 0 ${theme.fg}`,
            boxSizing: 'border-box',
          }}
        />
        <div style={{ marginTop: 12, display: 'flex', gap: 10 }}>
          <RetroBtn theme={theme} variant="ghost" onClick={onExit} style={{ flex: 1 }}>CANCEL</RetroBtn>
          <RetroBtn theme={theme} variant="primary" onClick={() => {
            const scene = customScene.trim();
            if (!scene) return;
            setPersona(`You are playing a character in this user-described scene: "${scene}". Pick a plausible role (server, friend, stranger, official, etc.) and stay in character. Start the conversation.`);
            setOpener(`Custom scene: ${scene}`);
            setStarted(true);
          }} style={{ flex: 1.5 }}>START →</RetroBtn>
        </div>
      </Screen>
    );
  }

  // ── Active chat ────────────────────────────────────────────
  return (
    <Screen theme={theme} scroll={false}>
      <div style={{ padding: '54px 16px 10px', borderBottom: `2px solid ${theme.fg}`, background: theme.surface }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <button onClick={onExit} style={{
            width: 32, height: 32, background: theme.bg, color: theme.fg,
            border: `2px solid ${theme.fg}`, borderRadius: theme.radius,
            fontSize: 18, lineHeight: 0, cursor: 'pointer',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontFamily: theme.fontDisplay,
          }}>×</button>
          <div style={{ fontSize: 26, lineHeight: 1 }}>{scenario.emoji}</div>
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: theme.fontBody, fontSize: 9, letterSpacing: '0.15em', color: theme.fgMute, textTransform: 'uppercase' }}>
              SCENE
            </div>
            <div style={{ fontFamily: theme.fontDisplay, fontSize: 16, lineHeight: 1 }}>{scenario.title}</div>
          </div>
          {!recap && (
            <RetroBtn theme={theme} variant="ghost" size="sm" onClick={endScene} disabled={ending}>
              {ending ? <Spinner theme={theme}/> : '✓ END'}
            </RetroBtn>
          )}
        </div>
      </div>

      <div ref={scrollRef} style={{ flex: 1, overflowY: 'auto', padding: '12px 14px 8px', display: 'flex', flexDirection: 'column', gap: 10 }}>
        {/* Setting card */}
        {opener && (
          <div style={{
            alignSelf: 'center', maxWidth: '90%', textAlign: 'center',
            background: theme.surfaceAlt, color: theme.fgMute,
            border: `2px dashed ${theme.fgDim}`, borderRadius: theme.radius,
            padding: '8px 12px',
            fontFamily: theme.fontBody, fontSize: 11, lineHeight: 1.4,
            fontStyle: 'italic',
          }}>{opener}</div>
        )}

        {messages.map((m, i) => <RPBubble key={i} theme={theme} role={m.role} content={m.content}/>)}
        {streaming && <RPBubble theme={theme} role="assistant" content={streaming} streaming/>}
        {error && (
          <div style={{
            background: theme.red, color: '#fff', padding: 10, borderRadius: theme.radius,
            border: `2px solid ${theme.fg}`, fontFamily: theme.fontBody, fontSize: 12,
          }}>⚠ {error}</div>
        )}
        {recap && (
          <Card theme={theme} padded={false} accent={theme.primary} style={{ padding: 14, marginTop: 6 }}>
            <div style={{ fontFamily: theme.fontDisplay, fontSize: 14, color: theme.primary, marginBottom: 6 }}>
              SCENE CLEAR ★
            </div>
            <div style={{ fontFamily: theme.fontBody, fontSize: 13, color: theme.fg, whiteSpace: 'pre-wrap', lineHeight: 1.5 }}>
              {recap}
            </div>
            <div style={{ marginTop: 12, display: 'flex', gap: 8 }}>
              <RetroBtn theme={theme} variant="ghost" size="md" onClick={onExit} style={{ flex: 1 }}>NEW SCENE</RetroBtn>
              <RetroBtn theme={theme} variant="primary" size="md" onClick={() => onTab('home')} style={{ flex: 1 }}>HOME →</RetroBtn>
            </div>
          </Card>
        )}
      </div>

      {!recap && (
        <div style={{ padding: '8px 12px', borderTop: `2px solid ${theme.fg}`, background: theme.surface }}>
          <div style={{ display: 'flex', gap: 6, marginBottom: 8 }}>
            <button onClick={giveHint} disabled={sending} style={{
              all: 'unset', cursor: sending ? 'not-allowed' : 'pointer',
              fontFamily: theme.fontHead, fontSize: 11, fontWeight: 700,
              background: theme.yellow, color: theme.fg,
              border: `2px solid ${theme.fg}`, borderRadius: 999,
              padding: '4px 10px', letterSpacing: '0.08em',
              textTransform: 'uppercase',
              opacity: sending ? 0.5 : 1,
            }}>↻ HINT</button>
          </div>
          <div style={{ display: 'flex', gap: 8, alignItems: 'flex-end' }}>
            <textarea
              rows={1}
              value={input}
              onChange={(e) => setInput(e.target.value)}
              onKeyDown={(e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }}
              placeholder="Reply in Chinese (pinyin OK)…"
              disabled={sending}
              style={{
                flex: 1, resize: 'none',
                fontFamily: theme.fontCN, fontSize: 16,
                padding: '12px 14px',
                background: theme.bg, color: theme.fg,
                border: `2px solid ${theme.fg}`, borderRadius: theme.radius,
                outline: 'none', minHeight: 44, maxHeight: 120,
              }}
            />
            {sending ? (
              <RetroBtn theme={theme} variant="danger" size="lg" onClick={stop}>STOP</RetroBtn>
            ) : (
              <RetroBtn theme={theme} variant="primary" size="lg" onClick={send} disabled={!input.trim()}>SEND</RetroBtn>
            )}
          </div>
        </div>
      )}
    </Screen>
  );
}

// Role-play bubble. Same shape as Tutor's Bubble but lays out the AI line
// with the english translation hidden inside ((parens)) — tap to reveal.
function RPBubble({ theme, role, content, streaming }) {
  const isUser = role === 'user';
  const [showEN, setShowEN] = React.useState(false);
  return (
    <div style={{
      alignSelf: isUser ? 'flex-end' : 'flex-start',
      maxWidth: '85%',
      background: isUser ? theme.primary : theme.surface,
      color: isUser && theme.mode === 'dark' ? '#fff' : theme.fg,
      border: `2px solid ${theme.fg}`,
      borderRadius: theme.radius,
      padding: '10px 12px',
      boxShadow: isUser ? `0 3px 0 0 ${theme.yellow}` : `0 3px 0 0 ${theme.cyan}`,
      fontFamily: theme.fontBody, fontSize: 13, lineHeight: 1.55,
      whiteSpace: 'pre-wrap', wordBreak: 'break-word',
    }}>
      {isUser ? content : renderRPContent(theme, content, showEN, () => setShowEN(true))}
      {streaming && <span style={{
        display: 'inline-block', width: 8, height: 14, marginLeft: 2,
        background: theme.fg, verticalAlign: '-2px',
        animation: 'speakPulse 0.9s infinite',
      }}/>}
    </div>
  );
}

// AI replies should be 3 lines: CN, pinyin, ((english)). We pull each apart
// and let the user tap to reveal the English.
function renderRPContent(theme, content, showEN, onRevealEN) {
  const lines = content.split('\n').map((l) => l.trim()).filter(Boolean);
  return lines.map((line, i) => {
    const hasCJK = /[一-鿿]/.test(line);
    const isEN = /^\(\(.*\)\)$/.test(line) || /^\(.+\)$/.test(line);

    if (hasCJK) {
      return (
        <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 8, margin: '2px 0' }}>
          <button onClick={() => { primeSpeech(); speakZh(line); }} style={{
            all: 'unset', cursor: 'pointer', width: 26, height: 26, flexShrink: 0,
            border: `1.5px solid ${theme.fg}`, borderRadius: '50%',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            background: theme.yellow,
          }}>
            <Speaker theme={theme} size={14} color={theme.fg}/>
          </button>
          <span style={{ fontFamily: theme.fontCN, fontSize: 18, fontWeight: 700 }}>{line}</span>
        </div>
      );
    }
    if (isEN) {
      const clean = line.replace(/^\(\(/, '').replace(/\)\)$/, '').replace(/^\(/, '').replace(/\)$/, '').trim();
      if (showEN) {
        return <div key={i} style={{ fontStyle: 'italic', color: theme.fgMute, margin: '2px 0' }}>{clean}</div>;
      }
      return (
        <button key={i} onClick={onRevealEN} style={{
          all: 'unset', cursor: 'pointer',
          fontFamily: theme.fontBody, fontSize: 11, color: theme.fgDim,
          textTransform: 'uppercase', letterSpacing: '0.1em',
          borderBottom: `1px dashed ${theme.fgDim}`, marginTop: 4,
        }}>tap for english</button>
      );
    }
    // Pinyin or other
    if (/[āáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜü]/.test(line) ||
        (/^[a-zA-Z0-9\s.,'?!:\-—]+$/.test(line) && /[a-z]/i.test(line))) {
      return (
        <div key={i} style={{ fontFamily: theme.fontPinyin, fontSize: 13, color: theme.primary, margin: '2px 0' }}>{line}</div>
      );
    }
    return <div key={i} style={{ margin: '2px 0' }}>{line}</div>;
  });
}

// Extract first Chinese line from a hint reply so we can pre-fill the input.
function extractFirstChinese(text) {
  const lines = text.split('\n').map((l) => l.trim()).filter(Boolean);
  for (const l of lines) {
    if (/[一-鿿]/.test(l)) return l;
  }
  return null;
}

Object.assign(window, { RolePlayScreen, RPBubble });
