// AIChatPanel — generic chat surface used by both NoteAIPanel (note-screen.jsx)
// and GuideAIPanel (guide-screens.jsx). Extracted from app.jsx in Wave 8 so
// neither feature-group file has to reach back into app.jsx for it.
//
// Export (via Object.assign(window, { ... }) at bottom):
//   AIChatPanel
//
// `context` shape:
//   { kind: 'note' | 'guide' | 'general',
//     id?: string,
//     title?: string,
//     color?: string,           // dot color in the chip header
//     systemPrompt: string,
//     placeholder?: string,
//     presets?: string[],
//     emptyHint?: string }
//
// Messages persist via chats.js (one row per user × context).
// Generation goes through window.generate (counts toward usage cap).
//
// External deps consumed:
//   window.useChat (chats.js), window.generate (api.js)
//   from helpers.jsx: AiGlyph

(function () {

function AIChatPanel({ context, onClose }) {
  const STORAGE_KEY = 'sb.aipanel.layout';
  const _saved = (() => {
    try { return JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}'); } catch { return {}; }
  })();
  const [mode, setMode]       = React.useState(_saved.mode || 'docked'); // 'docked' | 'floating'
  const [pos,  setPos]        = React.useState(_saved.pos  || { x: 120, y: 96 });
  const [size, setSize]       = React.useState(_saved.size || { w: 380, h: 540 });
  const [dockedWidth, setDockedWidth] = React.useState(_saved.dockedWidth || 380);
  const [messages, setMessages, _ready] = window.useChat({ kind: context.kind, id: context.id || null });
  const [input, setInput]     = React.useState('');
  const [busy, setBusy]       = React.useState(false);
  const [err, setErr]         = React.useState(null);
  const bodyRef = React.useRef(null);

  // Persist layout choice per session.
  React.useEffect(() => {
    try { localStorage.setItem(STORAGE_KEY, JSON.stringify({ mode, pos, size, dockedWidth })); } catch {}
  }, [mode, pos, size, dockedWidth]);

  // Auto-scroll on new message.
  React.useEffect(() => {
    if (bodyRef.current) bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
  }, [messages.length, busy]);

  const submit = async (e) => {
    e?.preventDefault?.();
    const q = input.trim();
    if (!q || busy) return;
    // Compute the next-state history BEFORE the state update so a fast double-
    // submit can't ship a stale slice. The user message gets appended as part
    // of the same value passed to OpenAI.
    const nextMessages = [...messages, { role: 'user', content: q }];
    setMessages(nextMessages);
    setInput('');
    setBusy(true); setErr(null);
    try {
      // Cap history sent to OpenAI at 20 — full history still rendered in UI.
      // history already includes the just-appended user msg, so no separate
      // trailing user entry.
      const history = nextMessages.slice(-20).map((m) => ({ role: m.role, content: m.content }));
      const payload = {
        model: 'gpt-4o-mini',
        messages: [
          { role: 'system', content: context.systemPrompt },
          ...history,
        ],
      };
      const res = await window.generate(payload, 'extract');
      const reply = res?.choices?.[0]?.message?.content || '(no response)';
      setMessages((m) => [...m, { role: 'assistant', content: reply }]);
    } catch (e2) {
      setErr(e2.message);
    } finally { setBusy(false); }
  };

  const clearAll = async () => {
    if (!messages.length) return;
    if (!confirm('Clear this chat history?')) return;
    setMessages([]);
  };

  // Drag (floating mode only) — track mousemove on window so the cursor can
  // leave the header without breaking the drag.
  const startDrag = (e) => {
    if (mode !== 'floating') return;
    e.preventDefault();
    const startX = e.clientX, startY = e.clientY;
    const startPos = { ...pos };
    const move = (ev) => {
      const x = Math.max(0, Math.min(window.innerWidth  - size.w, startPos.x + (ev.clientX - startX)));
      const y = Math.max(0, Math.min(window.innerHeight - 60,     startPos.y + (ev.clientY - startY)));
      setPos({ x, y });
    };
    const up = () => {
      window.removeEventListener('mousemove', move);
      window.removeEventListener('mouseup', up);
    };
    window.addEventListener('mousemove', move);
    window.addEventListener('mouseup', up);
  };

  // Resize from the bottom-right corner (floating mode only).
  const startResize = (e) => {
    if (mode !== 'floating') return;
    e.preventDefault(); e.stopPropagation();
    const startX = e.clientX, startY = e.clientY;
    const startSize = { ...size };
    const move = (ev) => {
      setSize({
        w: Math.max(280, Math.min(720, startSize.w + (ev.clientX - startX))),
        h: Math.max(320, Math.min(900, startSize.h + (ev.clientY - startY))),
      });
    };
    const up = () => {
      window.removeEventListener('mousemove', move);
      window.removeEventListener('mouseup', up);
    };
    window.addEventListener('mousemove', move);
    window.addEventListener('mouseup', up);
  };

  // Resize the docked panel by dragging its LEFT edge. Panel is right-pinned,
  // so dragging left makes it wider. Width is clamped + persisted to
  // localStorage with the rest of the layout.
  const startDockResize = (e) => {
    if (mode !== 'docked') return;
    e.preventDefault(); e.stopPropagation();
    const startX = e.clientX;
    const startWidth = dockedWidth;
    const move = (ev) => {
      const max = Math.min(900, window.innerWidth - 80);
      setDockedWidth(Math.max(280, Math.min(max, startWidth - (ev.clientX - startX))));
    };
    const up = () => {
      window.removeEventListener('mousemove', move);
      window.removeEventListener('mouseup', up);
      document.body.style.cursor = '';
      document.body.style.userSelect = '';
    };
    document.body.style.cursor = 'ew-resize';
    document.body.style.userSelect = 'none';
    window.addEventListener('mousemove', move);
    window.addEventListener('mouseup', up);
  };

  const shellStyle = mode === 'docked' ? {
    position: 'fixed', right: 0, top: 0, bottom: 0, width: dockedWidth,
    borderLeft: '1px solid var(--hairline-bold)',
    background: 'var(--page)',
    boxShadow: '-8px 0 24px -8px rgba(0, 0, 0, 0.06)',
  } : {
    position: 'fixed', left: pos.x, top: pos.y,
    width: size.w, height: size.h,
    border: '1px solid var(--hairline-bold)',
    borderRadius: 'var(--r-md)',
    background: 'var(--page)',
    boxShadow: '0 16px 48px -8px rgba(0, 0, 0, 0.22), 0 4px 12px rgba(0, 0, 0, 0.08)',
  };

  const presets = context.presets || [
    'Summarize in 3 bullets',
    'Explain like I\'m new to the topic',
    'Quiz me — 5 questions',
    'What\'s missing here?',
  ];

  return (
    <div className="ai-panel" style={{ ...shellStyle, zIndex: 200, display: 'flex', flexDirection: 'column' }}>
      {mode === 'docked' && (
        <div
          className="ai-panel-resize-w"
          onMouseDown={startDockResize}
          title="Drag to resize"
        />
      )}
      <div
        className="ai-panel-head"
        onMouseDown={startDrag}
        style={{
          display: 'flex', alignItems: 'center', gap: 6,
          padding: '8px 10px',
          borderBottom: '1px solid var(--hairline)',
          cursor: mode === 'floating' ? 'grab' : 'default',
          userSelect: 'none',
          background: 'var(--page-tint)',
          borderRadius: mode === 'floating' ? 'var(--r-md) var(--r-md) 0 0' : 0,
        }}>
        {/* Title chip — color-tagged when context provides one (subject color
            for guides). Falls back to plain ✦ AI · mode label. */}
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, flex: 1, minWidth: 0 }}>
          {context.color && (
            <span style={{ width: 8, height: 8, borderRadius: 999, background: context.color, flexShrink: 0 }} />
          )}
          <span style={{ display: 'inline-flex', alignItems: 'center', fontFamily: 'var(--mono)', fontSize: 10.5, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--ink-soft)' }}>
            <AiGlyph size={12} style={{ marginRight: 4 }} />AI
          </span>
          {context.title && (
            <span style={{ fontSize: 12, color: 'var(--ink-strong)', fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', minWidth: 0 }}>
              · {context.title}
            </span>
          )}
        </span>
        <button className="icon-btn" title="Clear chat" onClick={clearAll} disabled={!messages.length}>⌫</button>
        <button className="icon-btn" title={mode === 'docked' ? 'Pop out' : 'Dock right'}
          onClick={() => setMode((m) => m === 'docked' ? 'floating' : 'docked')}>
          {mode === 'docked' ? '⇱' : '⇲'}
        </button>
        <button className="icon-btn" title="Close" onClick={onClose}>×</button>
      </div>

      <div ref={bodyRef} style={{ flex: 1, overflowY: 'auto', padding: '14px 14px 8px' }}>
        {messages.length === 0 ? (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
            <div style={{ fontSize: 13, color: 'var(--ink-soft)', lineHeight: 1.55 }}>
              {context.emptyHint ||
                (context.kind === 'guide' ? `Ask anything about ${context.title || 'this guide'}. The AI is grounded in the guide's content.` :
                 context.kind === 'note'  ? 'Ask the AI about this note. It can summarize, rephrase, expand, quiz you, or suggest what\'s missing.' :
                 'Ask the AI anything.')}
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
              {presets.map((p) => (
                <button key={p} type="button"
                  onClick={() => setInput(p)}
                  className="filter-chip"
                  style={{ textAlign: 'left', justifyContent: 'flex-start', fontFamily: 'var(--sans)', textTransform: 'none', letterSpacing: 0, fontSize: 12.5, padding: '6px 10px' }}>
                  {p}
                </button>
              ))}
            </div>
          </div>
        ) : (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            {messages.map((m, i) => (
              <div key={i}>
                <div style={{ fontFamily: 'var(--mono)', fontSize: 10, fontWeight: 600, color: m.role === 'user' ? 'var(--ink-soft)' : 'var(--accent)', textTransform: 'uppercase', letterSpacing: '0.1em', marginBottom: 4 }}>
                  {m.role === 'user' ? 'You' : 'AI'}
                </div>
                <div style={{ fontSize: 13.5, color: 'var(--ink-strong)', whiteSpace: 'pre-wrap', lineHeight: 1.55 }}>{m.content}</div>
              </div>
            ))}
            {busy && (
              <div style={{ fontSize: 12, color: 'var(--ink-mute)' }}>
                <span className="pulse">Thinking…</span>
              </div>
            )}
          </div>
        )}
        {err && (
          <div style={{ marginTop: 10, padding: '8px 10px', background: 'var(--brick-tint)', border: '1px solid var(--brick)', borderRadius: 6, fontSize: 12, color: 'var(--brick)' }}>{err}</div>
        )}
      </div>

      <form onSubmit={submit}
        style={{ borderTop: '1px solid var(--hairline)', padding: 10, display: 'flex', gap: 6, alignItems: 'flex-end' }}>
        <textarea
          className="input"
          rows={2}
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyDown={(e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); submit(e); } }}
          placeholder={context.placeholder || 'Ask anything…  (Enter sends, Shift+Enter newline)'}
          style={{ flex: 1, minHeight: 44, fontSize: 13, fontFamily: 'var(--sans)', padding: '8px 10px', resize: 'none' }}
        />
        <button type="submit" className="btn accent sm" disabled={busy || !input.trim()} style={{ height: 44, padding: '0 14px' }}>
          {busy ? '…' : '↑'}
        </button>
      </form>

      {mode === 'floating' && (
        <div onMouseDown={startResize}
          title="Drag to resize"
          style={{
            position: 'absolute', right: 0, bottom: 0,
            width: 14, height: 14, cursor: 'nwse-resize',
            background: 'linear-gradient(135deg, transparent 50%, var(--ink-faint) 50%)',
            borderRadius: '0 0 var(--r-md) 0',
          }}
        />
      )}
    </div>
  );
}

// ─── Exports ───────────────────────────────────────────────────────────────

Object.assign(window, { AIChatPanel });

})();
