// screen-chat.jsx — Haiku assistant that knows Alex's pipeline and can act on it.
// The Worker runs one Anthropic turn at a time; this screen drives the loop:
// user message → AI → (tool_use? show Confirm/Skip cards) → execute via onApply →
// send tool_result → AI → … until the AI replies with plain text.

function ChatScreen({ theme, customers, onBack, onApply, openCustomer }) {
  const custById = React.useMemo(() => Object.fromEntries(customers.map(c => [c.id, c])), [customers]);
  const [msgs, setMsgs] = React.useState([]);        // Anthropic-format message array
  const [input, setInput] = React.useState('');
  const [busy, setBusy] = React.useState(false);     // waiting on the model
  const [pending, setPending] = React.useState(null); // { blocks:[tool_use], decisions:{} }
  const [err, setErr] = React.useState('');
  const scrollRef = React.useRef(null);

  React.useEffect(() => {
    const el = scrollRef.current; if (el) el.scrollTop = el.scrollHeight;
  }, [msgs, busy, pending]);

  const snapshot = () => customers.map(c => ({
    id: c.id, name: c.name, car: c.car, location: c.location, status: c.status, stage: c.stage,
    source: c.source, finance: c.finance, journey: c.journey, notes: c.notes,
    nurturing: c.nurturing, carsWanted: c.carsWanted, readyDate: c.readyDate,
    callbackAt: c.callbackAt, appointmentAt: c.appointmentAt, tradeIn: c.tradeIn, phone: c.phone,
  }));

  const callAI = async (nextMsgs) => {
    setBusy(true); setErr('');
    try {
      const res = await AI.chat(nextMsgs, snapshot());
      const content = res.content || [];
      const after = [...nextMsgs, { role: 'assistant', content }];
      setMsgs(after);
      const toolUses = content.filter(b => b.type === 'tool_use');
      setBusy(false);                                  // not waiting on the model anymore
      if (toolUses.length) setPending({ blocks: toolUses, decisions: {} });
    } catch (e) {
      setErr(String(e && e.message || e)); setBusy(false);
    }
  };

  const send = () => {
    const text = input.trim();
    if (!text || busy) return;
    setInput('');
    // If a confirm card is still open, typing a new instruction = skip the proposed
    // action(s) and replace with this. The API requires every tool_use to be answered
    // by a tool_result in the very next message, so we emit skip-results first, then
    // the new text (in the same user message).
    if (pending) {
      const results = pending.blocks.map(b => ({
        type: 'tool_result', tool_use_id: b.id,
        content: 'Skipped — Alex sent a new instruction instead. Use the message below.',
      }));
      setPending(null);
      setMsgs(cur => {
        const next = [...cur, { role: 'user', content: [...results, { type: 'text', text }] }];
        callAI(next);
        return next;
      });
      return;
    }
    setMsgs(cur => {
      const next = [...cur, { role: 'user', content: text }];
      callAI(next);
      return next;
    });
  };

  const decide = (id, decision) => setPending(p => p && ({ ...p, decisions: { ...p.decisions, [id]: decision } }));

  // once every pending tool has a decision, execute confirmed ones and continue
  React.useEffect(() => {
    if (!pending) return;
    if (!pending.blocks.every(b => pending.decisions[b.id])) return;
    let cancelled = false;
    (async () => {
      const results = [];
      for (const b of pending.blocks) {
        if (pending.decisions[b.id] === 'confirm') {
          const r = await onApply(b.name, b.input || {});
          results.push({ type: 'tool_result', tool_use_id: b.id,
            content: r.ok ? ('Done. ' + (r.message || '')) : ('Failed: ' + (r.message || '')), is_error: !r.ok });
        } else {
          results.push({ type: 'tool_result', tool_use_id: b.id, content: 'Skipped by Alex — do not retry.' });
        }
      }
      if (cancelled) return;
      setPending(null);
      setMsgs(cur => {
        const next = [...cur, { role: 'user', content: results }];
        callAI(next);
        return next;
      });
    })();
    return () => { cancelled = true; };
  }, [pending]);

  // result text for an already-resolved tool_use (scan later tool_result blocks)
  const resultFor = (id) => {
    for (const m of msgs) {
      if (m.role === 'user' && Array.isArray(m.content)) {
        const tr = m.content.find(b => b.type === 'tool_result' && b.tool_use_id === id);
        if (tr) return { text: tr.content, error: tr.is_error };
      }
    }
    return null;
  };

  const pendingIds = pending ? pending.blocks.map(b => b.id) : [];
  const suggestions = ['Who should I chase today?', 'Any hot leads still open?', 'Draft a follow-up text for my newest lead'];

  return (
    <React.Fragment>
      <TopBar theme={theme} onBack={onBack} title="Alejandro"
        trailing={<AlejAvatar size={32} theme={theme} />} />
      <div ref={scrollRef} style={{ flex: 1, overflowY: 'auto', overflowX: 'hidden', padding: '4px 16px 12px' }}>
        {msgs.length === 0 && (
          <div style={{ padding: '12px 2px 16px' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
              <AlejAvatar size={52} theme={theme} />
              <div>
                <div style={{ color: theme.text, fontSize: 19, fontWeight: 700, letterSpacing: -0.3 }}>Alejandro</div>
                <div style={{ fontSize: 13, color: theme.textMute, letterSpacing: -0.1 }}>Your sales sidekick</div>
              </div>
            </div>
            <div style={{ fontSize: 13.5, color: theme.textMute, marginTop: 12, lineHeight: 1.5 }}>
              Ask who to chase and I'll tell you why and write the text to send. I can also update leads, set callbacks and mark things done — you confirm each change.
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 14 }}>
              {suggestions.map(s => (
                <button key={s} onClick={() => { setInput(s); }} style={{
                  border: `0.5px solid ${theme.border}`, background: theme.surface, color: theme.text,
                  borderRadius: 12, padding: '12px 14px', textAlign: 'left', cursor: 'pointer',
                  fontFamily: 'inherit', fontSize: 14, letterSpacing: -0.1,
                }}>{s}</button>
              ))}
            </div>
          </div>
        )}

        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          {msgs.map((m, mi) => {
            // user text (plain string)
            if (m.role === 'user' && typeof m.content === 'string') {
              return <Bubble key={mi} theme={theme} mine>{m.content}</Bubble>;
            }
            // user array message: render any typed text; tool_result blocks stay hidden
            // (their outcome shows under the matching tool card)
            if (m.role === 'user') {
              return (m.content || []).filter(b => b.type === 'text' && b.text && b.text.trim())
                .map((b, bi) => <Bubble key={mi + '-' + bi} theme={theme} mine>{b.text}</Bubble>);
            }
            // assistant: text + tool_use blocks
            return (m.content || []).map((b, bi) => {
              if (b.type === 'text' && b.text && b.text.trim()) {
                return <Bubble key={mi + '-' + bi} theme={theme} bot>{b.text}</Bubble>;
              }
              if (b.type === 'tool_use') {
                const isPending = pendingIds.includes(b.id);
                const decided = pending && pending.decisions[b.id];
                const res = resultFor(b.id);
                return (
                  <ToolCard key={mi + '-' + bi} theme={theme}
                    label={describeTool(b, custById)}
                    pending={isPending && !decided}
                    decision={decided}
                    result={res}
                    onConfirm={() => decide(b.id, 'confirm')}
                    onSkip={() => decide(b.id, 'skip')} />
                );
              }
              return null;
            });
          })}
          {busy && <div style={{ color: theme.textDim, fontSize: 13, padding: '4px 2px' }}>Thinking…</div>}
          {err && <div style={{ color: theme.red, fontSize: 13, padding: '4px 2px' }}>{err}</div>}
        </div>
        <div style={{ height: 8 }} />
      </div>

      {/* input bar */}
      <div style={{
        flexShrink: 0, padding: '8px 14px calc(env(safe-area-inset-bottom,0px) + 12px)',
        borderTop: `0.5px solid ${theme.border}`, background: theme.bg,
        display: 'flex', gap: 8, alignItems: 'flex-end',
      }}>
        <textarea value={input} onChange={e => setInput(e.target.value)} rows={1}
          placeholder="Ask or tell me to do something…"
          onKeyDown={e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }}
          style={{
            flex: 1, resize: 'none', maxHeight: 120, border: `0.5px solid ${theme.border}`,
            background: theme.surface, color: theme.text, borderRadius: 14, padding: '12px 14px',
            fontFamily: 'inherit', fontSize: 15, outline: 'none', lineHeight: 1.4, letterSpacing: -0.1,
          }} />
        <button onClick={send} disabled={!input.trim() || busy} style={{
          flexShrink: 0, width: 44, height: 44, borderRadius: 99, border: 'none', cursor: 'pointer',
          background: (input.trim() && !busy) ? (theme.accentSolid || theme.blue) : theme.chip,
          color: (input.trim() && !busy) ? '#fff' : theme.textDim,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <Icon name="arrow-up" size={20} stroke={2.4}/>
        </button>
      </div>
    </React.Fragment>
  );
}

function Bubble({ theme, mine, bot, children }) {
  return (
    <div style={{ display: 'flex', justifyContent: mine ? 'flex-end' : 'flex-start', gap: 8, alignItems: 'flex-end' }}>
      {bot && <AlejAvatar size={28} theme={theme} />}
      <div style={{
        maxWidth: bot ? 'calc(85% - 36px)' : '85%', padding: '10px 13px', borderRadius: 16,
        background: mine ? (theme.accentSolid || theme.blue) : theme.surface,
        color: mine ? '#fff' : theme.text,
        border: mine ? 'none' : `0.5px solid ${theme.border}`,
        fontSize: 14.5, lineHeight: 1.45, letterSpacing: -0.1, whiteSpace: 'pre-wrap',
        borderBottomRightRadius: mine ? 5 : 16, borderBottomLeftRadius: mine ? 16 : 5,
      }}>{children}</div>
    </div>
  );
}

// Alejandro's avatar — the photo Alex picked, with a graceful fallback.
function AlejAvatar({ size = 32, theme }) {
  const [ok, setOk] = React.useState(true);
  if (!ok) {
    return (
      <div style={{
        width: size, height: size, borderRadius: 99, flexShrink: 0,
        background: theme.accentSolid || theme.blue, color: '#fff',
        display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700, fontSize: size * 0.45,
      }}>A</div>
    );
  }
  return (
    <img src="./alejandro.jpg?v=2" alt="Alejandro" onError={() => setOk(false)} style={{
      width: size, height: size, borderRadius: 99, objectFit: 'cover', flexShrink: 0,
      border: `0.5px solid ${theme.border}`,
    }} />
  );
}

function ToolCard({ theme, label, pending, decision, result, onConfirm, onSkip }) {
  const skipped = decision === 'skip' || (result && /^Skipped/.test(result.text || ''));
  const failed = result && result.error;
  const tint = failed ? theme.red : skipped ? theme.textMute : theme.greenInk;
  return (
    <div style={{
      background: theme.surface, border: `0.5px solid ${theme.border}`, borderRadius: 14, padding: '12px 14px',
      borderLeft: `3px solid ${theme.accentSolid || theme.blue}`,
    }}>
      <div style={{ display: 'flex', gap: 8, alignItems: 'flex-start' }}>
        <Icon name="sparkle" size={15} style={{ color: theme.accentSolid || theme.blue, flexShrink: 0, marginTop: 2 }}/>
        <div style={{ flex: 1, fontSize: 14, color: theme.text, fontWeight: 600, letterSpacing: -0.1, lineHeight: 1.4 }}>
          {label}
        </div>
      </div>
      {pending ? (
        <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
          <button onClick={onConfirm} style={{
            flex: 1, border: 'none', borderRadius: 10, padding: '11px 0', minHeight: 42, cursor: 'pointer',
            background: theme.accentSolid || theme.blue, color: '#fff', fontFamily: 'inherit', fontSize: 14, fontWeight: 600,
          }}>Confirm</button>
          <button onClick={onSkip} style={{
            flex: 1, border: `0.5px solid ${theme.border}`, borderRadius: 10, padding: '11px 0', minHeight: 42, cursor: 'pointer',
            background: 'transparent', color: theme.textMute, fontFamily: 'inherit', fontSize: 14, fontWeight: 600,
          }}>Skip</button>
        </div>
      ) : (
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 8, fontSize: 12.5, color: tint, fontWeight: 600 }}>
          <Icon name={skipped ? 'x' : failed ? 'x' : 'check'} size={13} stroke={2.4}/>
          {skipped ? 'Skipped' : (result ? (result.text || 'Done') : (decision === 'confirm' ? 'Applying…' : ''))}
        </div>
      )}
    </div>
  );
}

function describeTool(b, custById) {
  const i = b.input || {};
  const nm = (id) => (custById[id] && custById[id].name) || 'customer';
  if (b.name === 'create_customer') return 'Add new lead: ' + (i.name || '?') + (i.car ? ' — ' + i.car : '');
  if (b.name === 'remove_customer') return 'Remove ' + nm(i.id);
  if (b.name === 'complete_schedule') return 'Mark ' + (i.kind || 'item') + ' done for ' + nm(i.id);
  if (b.name === 'update_customer') {
    const parts = [];
    Object.keys(i).forEach(k => {
      if (k === 'id') return;
      let v = i[k];
      if ((k === 'callbackAt' || k === 'appointmentAt') && v) v = v.replace('T', ' ');
      parts.push(k + ' → ' + (v === '' ? '(clear)' : v));
    });
    return 'Update ' + nm(i.id) + ': ' + (parts.join(', ') || 'no change');
  }
  return b.name;
}

window.ChatScreen = ChatScreen;
