/* ============================================================
   devarv.ai — Instant Messenger window for ATHARV.OS
   Talks to /api/chat (Vercel serverless function → Gemini).
   Zero-build: loaded as text/babel like every other window.
   NOTE: `D` (ATHARV_DATA) is already a shared global binding
   from contents.jsx — do not redeclare it here.
============================================================ */

// Agentic reasoning trace shown while awaiting the first token — reflects the
// real pipeline (understand → retrieve from the knowledge base → compose).
function ReasoningTrace() {
  const STEPS = [
    { icon: '🧠', label: 'understanding your question' },
    { icon: '🔍', label: 'searching my knowledge base' },
    { icon: '✍️', label: 'composing a reply' },
  ];
  const [step, setStep] = React.useState(0);
  React.useEffect(() => {
    const t = setInterval(() => setStep(s => Math.min(s + 1, STEPS.length - 1)), 900);
    return () => clearInterval(t);
  }, []);
  return (
    <div style={{ fontSize: 11, color: '#5a6b8a', fontFamily: 'inherit', margin: '4px 0' }}>
      <div style={{ fontWeight: 700, color: '#1f3a72', marginBottom: 2 }}>devarv is thinking…</div>
      {STEPS.slice(0, step + 1).map((s, i) => (
        <div key={i} style={{ opacity: i === step ? 1 : 0.55, transition: 'opacity .3s' }}>
          {i < step ? '✓' : s.icon} {s.label}{i === step ? <span className="rt-dots">…</span> : ''}
        </div>
      ))}
    </div>
  );
}

function ChatContent() {
  const email = (window.ATHARV_DATA && window.ATHARV_DATA.identity.email) || 'atharv5873@gmail.com';
  const [msgs, setMsgs] = React.useState([
    { role: 'model', text: "yo 👋 I'm devarv — well, the AI version of me. Ask me anything about my work, my projects, or life up in the hills 🏔" },
  ]);
  const [input, setInput] = React.useState('');
  const [typing, setTyping] = React.useState(false);
  const listRef = React.useRef(null);
  const inputRef = React.useRef(null);

  React.useEffect(() => {
    if (listRef.current) listRef.current.scrollTop = listRef.current.scrollHeight;
  }, [msgs, typing]);

  const offlineLine = {
    role: 'sys',
    text: `⚠ devarv.ai seems to be offline right now — email me instead: ${email}`,
  };

  // Agentic control tokens: devarv AI can emit [[open:mycomputer]],
  // [[open:project:royalbankpacific]] (open a window) or [[do:screensaver]]
  // (trigger an effect). We hide the token from the bubble and dispatch it to
  // the shell, allowlist-validated there so it can only do harmless UI actions.
  const LAUNCH_RE = /\[\[\s*(open|do):\s*([a-z0-9:_-]+?)\s*\]\]/gi;
  const stripLaunch = (s) => s.replace(LAUNCH_RE, '').replace(/[ \t]{2,}/g, ' ').trim();
  const dispatchLaunches = (s) => {
    const tokens = [];
    let mm;
    LAUNCH_RE.lastIndex = 0;
    while ((mm = LAUNCH_RE.exec(s)) !== null) tokens.push([mm[1].toLowerCase(), mm[2].toLowerCase()]);
    tokens.slice(0, 2).forEach(([verb, tok], i) => setTimeout(() => {
      const detail = verb === 'do' ? { do: tok }
        : tok.startsWith('project:') ? { project: tok.slice(8) } : { app: tok };
      try { window.dispatchEvent(new CustomEvent('atharv-os:launch', { detail })); } catch (e) {}
    }, 600 + i * 500));
  };

  const send = async (forced) => {
    const text = (forced != null ? forced : input).trim();
    if (!text || typing) return;
    setInput('');
    const nextMsgs = [...msgs, { role: 'user', text }];
    setMsgs(nextMsgs);
    setTyping(true);
    if (window.va) {
      window.va('event', { name: nextMsgs.filter(m => m.role === 'user').length === 1 ? 'chat_started' : 'chat_message' });
    }
    try {
      const res = await fetch('/api/chat', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          message: text,
          history: nextMsgs
            .filter(m => m.role === 'user' || m.role === 'model')
            .slice(-9, -1)                       // last turns before the new message
            .map(m => ({ role: m.role, text: m.text })),
        }),
      });
      const ctype = (res.headers.get('content-type') || '');
      if (!res.ok || ctype.includes('application/json')) {
        const data = await res.json().catch(() => ({}));
        setMsgs(m => [...m, data.error ? { role: 'sys', text: `⚠ ${data.error}` } : offlineLine]);
        return;
      }
      // Streaming reply: grow the last bubble as chunks arrive.
      setMsgs(m => [...m, { role: 'model', text: '' }]);
      setTyping(false);
      const reader = res.body.getReader();
      const dec = new TextDecoder();
      let got = false;
      let acc = '';
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        const chunk = dec.decode(value, { stream: true });
        if (!chunk) continue;
        got = true;
        acc += chunk;
        const display = stripLaunch(acc);   // hide control tokens as they arrive
        setMsgs(m => {
          const out = m.slice();
          out[out.length - 1] = { role: 'model', text: display };
          return out;
        });
      }
      if (!got) setMsgs(m => [...m.slice(0, -1), offlineLine]);
      else dispatchLaunches(acc);           // act on any [[open:...]] tokens
    } catch (e) {
      setMsgs(m => (m.length && m[m.length - 1].role === 'model' && m[m.length - 1].text === '')
        ? [...m.slice(0, -1), offlineLine]
        : [...m, offlineLine]);
    } finally {
      setTyping(false);
      if (inputRef.current) inputRef.current.focus();
    }
  };

  const CHIPS = [
    'What did you build at Mirakalous?',
    'Are you open to work?',
    "What's your stack?",
    'Tell me about the mountains 🏔',
  ];
  const showChips = msgs.length === 1 && !typing;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0 }}>
      {/* MSN-style header */}
      <div style={{
        background: 'linear-gradient(180deg, #7BA7E1 0%, #4A7BC8 100%)',
        color: '#fff', padding: '8px 10px',
        display: 'flex', alignItems: 'center', gap: 8,
        borderBottom: '1px solid #2d5a9e',
      }}>
        <span style={{
          width: 10, height: 10, borderRadius: '50%',
          background: '#3ADB3A', border: '1px solid #1a6b1a',
          boxShadow: '0 0 4px #3ADB3A', flexShrink: 0,
        }}/>
        <div style={{ lineHeight: 1.25 }}>
          <div style={{ fontWeight: 700, fontSize: 12 }}>devarv &lt;atharv5873@gmail.com&gt;</div>
          <div style={{ fontSize: 10, opacity: 0.85 }}>Online — powered by an actual LLM, built by the guy it imitates</div>
        </div>
      </div>

      {/* Message list */}
      <div ref={listRef} className="sunken" style={{
        flex: 1, minHeight: 0, overflowY: 'auto',
        background: '#fff', padding: '8px 10px',
        fontSize: 12, lineHeight: 1.5,
      }}>
        {msgs.map((m, i) => (
          m.role === 'sys' ? (
            <div key={i} style={{ color: '#804000', background: '#FFFFCC', border: '1px solid #c0a060', padding: '4px 8px', margin: '6px 0', fontSize: 11 }}>
              {m.text}{' '}
              {m.text.includes('offline') && <a href={`mailto:${email}`} style={{ color: '#0000EE' }}>send email</a>}
            </div>
          ) : (
            <div key={i} style={{ marginBottom: 8 }}>
              <div style={{ fontWeight: 700, fontSize: 11, color: m.role === 'user' ? '#B03060' : '#1f3a72' }}>
                {m.role === 'user' ? 'you say:' : 'devarv says:'}
              </div>
              <div style={{ whiteSpace: 'pre-wrap', paddingLeft: 8 }}>{m.text}</div>
            </div>
          )
        ))}
        {typing && <ReasoningTrace/>}
      </div>

      {/* Suggested questions (fresh conversation only) */}
      {showChips && (
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4, padding: '6px 6px 0' }}>
          {CHIPS.map((c, i) => (
            <button key={i} className="btn" style={{ fontSize: 10, padding: '3px 8px' }} onClick={() => send(c)}>
              {c}
            </button>
          ))}
        </div>
      )}

      {/* Input row */}
      <div style={{ display: 'flex', gap: 6, padding: 6, alignItems: 'stretch' }}>
        <input
          ref={inputRef}
          className="w95-input"
          style={{ flex: 1, minWidth: 0 }}
          placeholder="Ask me about my projects, stack, the mountains…"
          value={input}
          maxLength={600}
          disabled={typing}
          onChange={e => setInput(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter') send(); }}
          aria-label="Message to devarv AI"
        />
        <button className="btn" onClick={() => send()} disabled={typing || !input.trim()}>
          {typing ? '…' : 'Send'}
        </button>
      </div>
      <div style={{ padding: '0 8px 6px', fontSize: 9, color: '#606060' }}>
        AI-generated — may occasionally get things wrong. The real me replies at {email}.
      </div>
    </div>
  );
}

Object.assign(window, { ChatContent });
