// Five Nodes Hospital — Inbox (live chat + 7 demo medical scenarios)
const { useState: useStateC, useRef: useRefC, useEffect: useEffectC, useMemo: useMemoC } = React;

function sessionsKey(uid) { return 'fnhsp-sessions-' + (uid || 'anon'); }
function loadSessions(uid) { try { return JSON.parse(localStorage.getItem(sessionsKey(uid))) || []; } catch (e) { return []; } }
function saveSessions(uid, s) { try { localStorage.setItem(sessionsKey(uid), JSON.stringify(s)); } catch (e) {} }
function newSessionId() {
  const bytes = new Uint8Array(6);
  (crypto || window.crypto).getRandomValues(bytes);
  return 's-' + Array.from(bytes).map(b => b.toString(16).padStart(2,'0')).join('');
}
function fmtTime(d) { const x = d instanceof Date ? d : new Date(d); return x.getHours().toString().padStart(2,'0') + ':' + x.getMinutes().toString().padStart(2,'0'); }
function fmtRelative(iso) {
  if (!iso) return '';
  const m = Math.floor((Date.now() - new Date(iso).getTime()) / 60000);
  if (m < 1) return 'now'; if (m < 60) return m + 'm';
  const h = Math.floor(m / 60); if (h < 24) return h + 'h';
  return Math.floor(h / 24) + 'd';
}

function analysisRowToProps(row) {
  if (!row) return null;
  return {
    intent:      row.intent || '—',
    specialty:   row.preferred_specialty || '—',
    doctor:      row.preferred_doctor || '—',
    gender:      row.gender_preference || '—',
    reason:      row.reason_for_visit || '—',
    urgency:     row.urgency || '—',
    sentiment:   row.sentiment || 'Neutral',
    priority:    row.priority || 'Warm',
    leadScore:   row.lead_score || 3,
    summary:     row.summary || '',
    keyDetails:  Array.isArray(row.key_details) ? row.key_details : [],
    nextAction:  row.next_action || '',
    risks:       row.risks || null,
    tags:        Array.isArray(row.tags) ? row.tags : []
  };
}
function analysisFromMock(a) {
  if (!a) return null;
  return {
    intent: a.intent, specialty: a.preferred_specialty, doctor: a.preferred_doctor,
    gender: a.gender_preference || '—', reason: a.reason_for_visit, urgency: a.urgency,
    sentiment: a.sentiment, priority: a.priority, leadScore: a.lead_score,
    summary: a.summary, keyDetails: a.key_details || [],
    nextAction: a.next_action, risks: a.risks, tags: a.tags || []
  };
}

const SessionList = ({ sessions, mockChats, activeId, onPick, onNew }) => {
  const t = (k) => window.__t ? window.__t(k) : k;
  return (
  <div className="chat-side">
    <div className="chat-side-head">
      <h3><em>{t('inbox.title')}</em></h3>
      <div className="sub">{sessions.length} {t('inbox.live')} · {mockChats.length} {t('inbox.demo')}</div>
    </div>
    <button className="new-thread-btn" onClick={onNew}><Icon name="plus" size={12} /> {t('inbox.newConv')}</button>
    <div className="thread-list">
      {sessions.length > 0 && (<>
        <div className="nav-label">{t('inbox.yours')}</div>
        {sessions.map(s => (
          <div key={s.phone} className={`thread ${activeId === s.phone ? 'active' : ''}`} onClick={() => onPick(s.phone)}>
            <div className="t-top">
              <div className="t-title">{(s.name || t('inbox.newPatient')).split(' ')[0]}</div>
              <div className="t-time">{fmtRelative(s.lastActivity)}</div>
            </div>
            <div className="t-prev">{s.lastMessagePreview || t('inbox.waiting')}</div>
          </div>
        ))}
      </>)}
      <div className="nav-label">{t('inbox.demoScenarios')}</div>
      {mockChats.map(m => (
        <div key={m.id} className={`thread ${activeId === m.id ? 'active' : ''}`} onClick={() => onPick(m.id)}>
          <div className="t-top">
            <div className="t-title" style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              {m.name.split(' ')[0]}
              {m.language === 'ar' && <span style={{ fontSize: 8, fontWeight: 600, padding: '1px 5px', borderRadius: 3, background: 'var(--accent-soft)', color: 'var(--accent-deep)', letterSpacing: '0.04em' }}>AR</span>}
              <span style={{ fontSize: 8, fontWeight: 600, padding: '1px 5px', borderRadius: 3, background: 'rgba(180,83,9,0.12)', color: 'var(--warn)', letterSpacing: '0.04em' }}>{t('common.demo')}</span>
            </div>
            <div className="t-time">{fmtRelative(m.lastActivity)}</div>
          </div>
          <div className="t-prev" style={{ fontStyle: 'italic', fontSize: 11.5, color: 'var(--fg-4)' }}>{m.scenario}</div>
          <div className="t-prev" style={{ marginTop: 2 }}>{m.lastMessagePreview}</div>
        </div>
      ))}
    </div>
  </div>
  );
};

// ---- Voice message bubble (audio player + collapsible transcription) ----
const VoiceBubble = ({ audioUrl, audioPath, transcription, pending, error }) => {
  const [resolvedUrl, setResolvedUrl] = useStateC(audioUrl || null);
  const [showTx, setShowTx] = useStateC(false);
  useEffectC(() => {
    let cancelled = false;
    if (audioUrl) { setResolvedUrl(audioUrl); return; }
    if (!audioPath) { setResolvedUrl(null); return; }
    window.__api.getVoiceSignedUrl(audioPath).then(u => { if (!cancelled) setResolvedUrl(u); });
    return () => { cancelled = true; };
  }, [audioUrl, audioPath]);
  const txReady = !pending && transcription && !error;
  const txLabel = error ? (transcription || 'Voice failed')
    : pending ? 'Transcribing…'
    : (showTx ? 'Hide transcription' : 'View transcription');
  return (
    <div className="m-voice">
      <div className="voice-player">
        {resolvedUrl ? <audio controls preload="metadata" src={resolvedUrl} />
          : <div className="voice-loading"><span className="spinner sm" /></div>}
      </div>
      <button type="button" className={`voice-tx-toggle ${error ? 'is-error' : ''}`}
        onClick={() => txReady && setShowTx(v => !v)} disabled={!txReady}>
        {txLabel}
      </button>
      {showTx && txReady && <div className="voice-tx-text">{transcription}</div>}
    </div>
  );
};

const ChatPanel = ({ session, onBumpActivity, onSyncLead }) => {
  const t = (k) => window.__t ? window.__t(k) : k;
  const isMock = !!session.isMock;
  const [messages, setMessages] = useStateC(session._preloadedMessages || []);
  const [input, setInput] = useStateC('');
  const [isTyping, setIsTyping] = useStateC(false);
  const [loading, setLoading] = useStateC(!isMock && !session._preloadedMessages);
  const [recordState, setRecordState] = useStateC('idle');
  const [recordSeconds, setRecordSeconds] = useStateC(0);
  const bodyRef = useRefC(null), bottomRef = useRefC(null);
  const mediaRecorderRef = useRefC(null);
  const audioStreamRef = useRefC(null);
  const audioChunksRef = useRefC([]);
  const recordTimerRef = useRefC(null);
  const blobUrlsRef = useRefC([]);
  const typingTimeoutRef = useRefC(null);
  const MAX_RECORD_SECONDS = 120;

  useEffectC(() => {
    if (isMock) { setMessages(session._preloadedMessages || []); setLoading(false); return; }
    let cancelled = false;
    setLoading(true); setMessages([]);
    (async () => {
      try {
        const logs = await window.__api.loadChatHistory(session.phone, 50);
        if (cancelled) return;
        setMessages((logs || []).filter(l => l.message_content && l.message_content.trim()).map(l => {
          const isVoice = l.sender_type === 'customer' && l.message_type === 'voice';
          if (isVoice) {
            return {
              _id: l.id, role: 'user', kind: 'voice',
              message_id: l.message_id,
              audioPath: l.audio_path || null,
              transcription: l.message_content,
              pending: false,
              time: fmtTime(l.created_at)
            };
          }
          return {
            _id: l.id,
            role: l.sender_type === 'customer' ? 'user' : 'ai',
            text: l.message_content, time: fmtTime(l.created_at)
          };
        }));
      } catch (e) { console.warn('[history]', e); }
      finally { if (!cancelled) setLoading(false); }
    })();
    return () => { cancelled = true; };
  }, [session.phone, isMock]);

  // Subscribe to incoming rows for this session via Supabase Realtime
  useEffectC(() => {
    if (isMock) return;
    const unsubscribe = window.__api.subscribeToChat(session.phone, (row) => {
      if (row.sender_type === 'customer' && row.message_type === 'voice') {
        setMessages(m => {
          const idx = m.findIndex(x => x.kind === 'voice' && x.message_id === row.message_id);
          if (idx >= 0) {
            const updated = [...m];
            updated[idx] = {
              ...updated[idx],
              _id: row.id,
              transcription: row.message_content,
              audioPath: row.audio_path || updated[idx].audioPath,
              pending: false
            };
            return updated;
          }
          if (m.some(x => x._id === row.id)) return m;
          return [...m, {
            _id: row.id, role: 'user', kind: 'voice',
            message_id: row.message_id,
            audioPath: row.audio_path || null,
            transcription: row.message_content,
            pending: false,
            time: fmtTime(row.created_at)
          }];
        });
        return;
      }
      if (row.sender_type !== 'ai_agent') return;
      setMessages(m => {
        if (m.some(x => x._id === row.id)) return m;
        return [...m, { _id: row.id, role: 'ai', text: row.message_content, time: fmtTime(row.created_at) }];
      });
      if (typingTimeoutRef.current) { clearTimeout(typingTimeoutRef.current); typingTimeoutRef.current = null; }
      setIsTyping(false);
      onBumpActivity(session.phone, row.message_content);
    });
    return () => {
      unsubscribe();
      if (typingTimeoutRef.current) { clearTimeout(typingTimeoutRef.current); typingTimeoutRef.current = null; }
    };
  }, [session.phone, isMock]);

  useEffectC(() => {
    requestAnimationFrame(() => {
      if (bottomRef.current) bottomRef.current.scrollIntoView({ behavior: 'smooth', block: 'end' });
      else if (bodyRef.current) bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
    });
  }, [messages.length, isTyping]);

  // ---- Voice recording ----
  const fmtRecordTime = (s) => {
    const mm = Math.floor(s / 60).toString().padStart(2, '0');
    const ss = (s % 60).toString().padStart(2, '0');
    return mm + ':' + ss;
  };
  const cleanupRecorder = () => {
    if (recordTimerRef.current) { clearInterval(recordTimerRef.current); recordTimerRef.current = null; }
    if (audioStreamRef.current) {
      audioStreamRef.current.getTracks().forEach(tr => tr.stop());
      audioStreamRef.current = null;
    }
    mediaRecorderRef.current = null;
    audioChunksRef.current = [];
  };
  useEffectC(() => {
    return () => {
      cleanupRecorder();
      blobUrlsRef.current.forEach(u => { try { URL.revokeObjectURL(u); } catch (e) {} });
      blobUrlsRef.current = [];
    };
  }, []);

  const sendVoice = async (blob, mimetype) => {
    const messageId = 'WEB-VOICE-' + Date.now() + '-' + Math.random().toString(36).slice(2, 8);
    const localUrl = URL.createObjectURL(blob);
    blobUrlsRef.current.push(localUrl);
    const now = new Date();
    setMessages(m => [...m, {
      role: 'user', kind: 'voice', message_id: messageId,
      audioUrl: localUrl, audioPath: null,
      transcription: null, pending: true,
      time: fmtTime(now)
    }]);
    setIsTyping(true);
    onBumpActivity(session.phone, '🎤 Voice message');
    if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current);
    typingTimeoutRef.current = setTimeout(() => {
      setMessages(m => [...m, { role: 'ai', text: "I'm taking longer than usual. Please try again in a moment.", time: fmtTime(new Date()) }]);
      setMessages(m => m.map(x => x.message_id === messageId && x.pending
        ? { ...x, pending: false, transcription: 'Transcription unavailable', error: true } : x));
      setIsTyping(false);
      typingTimeoutRef.current = null;
    }, 120000);
    try {
      const { path, signedUrl } = await window.__api.uploadVoiceNote(blob, mimetype, messageId);
      setMessages(m => m.map(x => x.message_id === messageId ? { ...x, audioPath: path } : x));
      await window.__api.postVoiceToAgent({
        phone: session.phone, name: session.name || 'Unknown',
        message_id: messageId, language: session.language || 'en',
        audio_url: signedUrl, audio_mimetype: mimetype, audio_path: path
      });
    } catch (e) {
      console.error('voice send failed', e);
      if (typingTimeoutRef.current) { clearTimeout(typingTimeoutRef.current); typingTimeoutRef.current = null; }
      setIsTyping(false);
      setMessages(m => m.map(x => x.message_id === messageId
        ? { ...x, pending: false, transcription: 'Voice failed to upload', error: true } : x));
    }
  };

  const startRecording = async () => {
    if (isMock || isTyping || recordState !== 'idle') return;
    if (!navigator.mediaDevices?.getUserMedia || typeof window.MediaRecorder === 'undefined') {
      setMessages(m => [...m, { role: 'ai', text: 'Voice recording is not supported in this browser.', time: fmtTime(new Date()) }]);
      return;
    }
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      audioStreamRef.current = stream;
      const candidates = ['audio/webm;codecs=opus', 'audio/webm', 'audio/mp4', 'audio/ogg;codecs=opus'];
      let mimeType = '';
      for (const m of candidates) {
        if (window.MediaRecorder.isTypeSupported && window.MediaRecorder.isTypeSupported(m)) { mimeType = m; break; }
      }
      const rec = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream);
      audioChunksRef.current = [];
      rec.ondataavailable = (e) => { if (e.data && e.data.size > 0) audioChunksRef.current.push(e.data); };
      rec.onstop = () => {
        const wasCancelled = rec._cancelled;
        const chunks = audioChunksRef.current.slice();
        const recMime = rec.mimeType || mimeType || 'audio/webm';
        cleanupRecorder();
        if (wasCancelled || chunks.length === 0) { setRecordState('idle'); setRecordSeconds(0); return; }
        setRecordState('idle'); setRecordSeconds(0);
        const blob = new Blob(chunks, { type: recMime });
        sendVoice(blob, recMime);
      };
      rec.start();
      mediaRecorderRef.current = rec;
      setRecordState('recording'); setRecordSeconds(0);
      recordTimerRef.current = setInterval(() => {
        setRecordSeconds(s => {
          const next = s + 1;
          if (next >= MAX_RECORD_SECONDS) stopRecording();
          return next;
        });
      }, 1000);
    } catch (e) {
      console.error('mic permission failed', e);
      setMessages(m => [...m, { role: 'ai', text: 'Microphone permission denied or unavailable.', time: fmtTime(new Date()) }]);
      cleanupRecorder();
      setRecordState('idle');
    }
  };
  const stopRecording = () => {
    const rec = mediaRecorderRef.current;
    if (rec && rec.state !== 'inactive') rec.stop();
  };
  const cancelRecording = () => {
    const rec = mediaRecorderRef.current;
    if (rec) { rec._cancelled = true; if (rec.state !== 'inactive') rec.stop(); }
    else { cleanupRecorder(); setRecordState('idle'); setRecordSeconds(0); }
  };

  const send = async () => {
    const text = input.trim();
    if (!text || isTyping || isMock) return;
    const now = new Date();
    const messageId = 'WEB-' + Date.now() + '-' + Math.random().toString(36).slice(2, 8);
    setMessages(m => [...m, { role: 'user', text, time: fmtTime(now) }]);
    setInput(''); setIsTyping(true); onBumpActivity(session.phone, text);
    if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current);
    typingTimeoutRef.current = setTimeout(() => {
      setMessages(m => [...m, { role: 'ai', text: "I'm taking longer than usual. Please try again in a moment.", time: fmtTime(new Date()) }]);
      setIsTyping(false);
      typingTimeoutRef.current = null;
    }, 120000);
    try {
      await window.__api.postToAgent({ phone: session.phone, name: session.name || 'Unknown', user_message: text, message_id: messageId, language: session.language || 'en' });
    } catch (e) {
      if (typingTimeoutRef.current) { clearTimeout(typingTimeoutRef.current); typingTimeoutRef.current = null; }
      setMessages(m => [...m, { role: 'ai', text: 'Network error reaching the assistant. Please try again.', time: fmtTime(new Date()) }]);
      setIsTyping(false); return;
    }

    // Fallback to Realtime: poll the DB for the agent's reply in case the
    // Realtime INSERT event never reaches the browser. Deduped by row id.
    (async () => {
      const sinceIso = new Date(now.getTime() - 2000).toISOString();
      const row = await window.__api.pollForReply(session.phone, sinceIso, 115000, 2000);
      if (!row) return;
      setMessages(m => (row.id && m.some(x => x._id === row.id))
        ? m
        : [...m, { _id: row.id, role: 'ai', text: row.message_content, time: fmtTime(row.created_at) }]);
      if (typingTimeoutRef.current) { clearTimeout(typingTimeoutRef.current); typingTimeoutRef.current = null; }
      setIsTyping(false);
    })();

    // Fire the "you're in the database" tutorial once the AI books an
    // hsp_appointments row for this patient (proves real-time fetch).
    window.__leadTutorial?.pollAndFire(session.phone);
    setTimeout(async () => {
      try {
        const rows = await window.__api.sbGet('hsp_patients', {
          'select': 'name,contact_phone,email,language,status',
          'phone':  'eq.' + session.phone, 'limit': '1'
        });
        const lead = rows?.[0];
        if (lead && onSyncLead) {
          onSyncLead(session.phone, {
            name:     lead.name && lead.name !== 'New Patient' ? lead.name : session.name,
            language: lead.language || session.language,
            status:   lead.status || session.status
          });
        }
      } catch (e) {}
    }, 8000);
  };
  const onKey = (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } };

  return (
    <div className="chat-main">
      <div className="chat-head">
        <div className="title-row">
          <div className="chat-avatar">{(session.name || '?').slice(0,1).toUpperCase()}</div>
          <div>
            <h3 style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              {(session.name || t('inbox.newPatient')).split(' ')[0]}
              {isMock && <span style={{ fontSize: 9, fontWeight: 600, padding: '2px 6px', borderRadius: 3, background: 'rgba(180,83,9,0.12)', color: 'var(--warn)', letterSpacing: '0.04em' }}>{t('common.demo')}</span>}
            </h3>
            <div className="status">{isMock ? session.scenario : ((session.language || 'en') === 'ar' ? t('inbox.lang.ar') : t('inbox.lang.en')) + ' · ' + t('inbox.channel')}</div>
          </div>
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          {isMock ? <span className="tag warn">{t('inbox.demoReadonly')}</span> : <span className="tag accent">{isTyping ? t('inbox.typing') : t('inbox.live.badge')}</span>}
        </div>
      </div>
      <div className="chat-body" ref={bodyRef} dir={session.language === 'ar' ? 'rtl' : 'ltr'}>
        {loading && <div className="loading-block"><div className="spinner" /></div>}
        {!loading && messages.length === 0 && !isMock && (
          <div style={{ color: 'var(--fg-4)', textAlign: 'center', padding: 40, fontSize: 13 }}>{t('inbox.sayHi')}</div>
        )}
        {messages.map((m, i) => (
          <div key={m._id || m.message_id || i} className={`msg ${m.role === 'user' ? 'out' : 'in'}`}>
            <div className="m-avatar">{m.role === 'user' ? (session.name || 'P').slice(0,1).toUpperCase() : 'AI'}</div>
            <div className="m-bubble">
              <div className="m-meta">{m.role === 'user' ? (session.name || t('inbox.patient')).split(' ')[0] : t('inbox.assistant')} · {m.time}</div>
              {m.kind === 'voice'
                ? <VoiceBubble audioUrl={m.audioUrl} audioPath={m.audioPath} transcription={m.transcription} pending={m.pending} error={m.error} />
                : <div className="m-text" style={{ whiteSpace: 'pre-wrap' }}>{m.text}</div>}
            </div>
          </div>
        ))}
        {isTyping && (
          <div className="msg in">
            <div className="m-avatar">AI</div>
            <div className="m-bubble">
              <div className="m-meta">{t('inbox.assistant')} · {t('inbox.thinking')}</div>
              <div className="m-text"><span className="typing"><span /><span /><span /></span></div>
            </div>
          </div>
        )}
        <div ref={bottomRef} style={{ height: 1 }} />
      </div>
      <div className="chat-input">
        <div className={`wrap ${recordState === 'recording' ? 'is-recording' : ''}`}>
          {recordState === 'recording' ? (
            <>
              <button className="tool rec-cancel" title="Cancel recording" onClick={cancelRecording}><Icon name="xCircle" size={14} /></button>
              <div className="rec-meter">
                <span className="rec-dot" />
                <span className="rec-time mono">{fmtRecordTime(recordSeconds)}</span>
                <span className="rec-hint">Recording… click send to finish</span>
              </div>
              <button className="send" title="Stop & send" onClick={stopRecording}><Icon name="send" size={13} /></button>
            </>
          ) : (
            <>
              <button className="tool" title="Voice message" onClick={startRecording} disabled={isMock || isTyping || recordState !== 'idle'}>
                <Icon name="mic" size={14} />
              </button>
              <textarea rows={1} value={input} onChange={e => setInput(e.target.value)} onKeyDown={onKey}
                placeholder={isMock ? t('inbox.demoReadonlyMsg') : (isTyping ? t('inbox.waitingAssistant') : t('inbox.placeholder') + ' ' + (session.name || t('inbox.patient')).split(' ')[0] + '…')}
                disabled={isMock || isTyping} />
              <button className="send" onClick={send} disabled={!input.trim() || isTyping || isMock}><Icon name="send" size={13} /></button>
            </>
          )}
        </div>
      </div>
    </div>
  );
};

const AnalysisPanel = ({ session }) => {
  const t = (k) => window.__t ? window.__t(k) : k;
  const isMock = !!session?.isMock;
  const [liveAnalysis, setLiveAnalysis] = useStateC(null);
  const [liveLoading, setLiveLoading] = useStateC(false);

  useEffectC(() => {
    if (!session || isMock || !session.phone) { setLiveAnalysis(null); return; }
    let cancelled = false;
    const fetchOnce = async () => {
      try {
        const rows = await window.__api.sbGet('hsp_conversation_analysis', {
          'select': '*', 'phone_number': 'eq.' + session.phone, 'order': 'analyzed_at.desc', 'limit': '1'
        });
        if (cancelled) return;
        setLiveAnalysis(rows?.[0] ? analysisRowToProps(rows[0]) : null);
      } catch (e) { if (!cancelled) console.warn('[analysis]', e.message); }
      finally { if (!cancelled) setLiveLoading(false); }
    };
    setLiveLoading(true); fetchOnce();
    const id = setInterval(fetchOnce, 30000);
    return () => { cancelled = true; clearInterval(id); };
  }, [session?.phone, isMock]);

  if (!session) return <div className="chat-analysis"><div style={{ padding: 22, textAlign: 'center', color: 'var(--fg-4)', fontSize: 12 }}>{t('analysis.selectConvo')}</div></div>;

  const a = isMock ? analysisFromMock(session.analysis) : liveAnalysis;
  if (!a) return (
    <div className="chat-analysis">
      <div style={{ padding: 22 }}>
        <div className="mono" style={{ fontSize: 10, color: 'var(--fg-3)', textTransform: 'uppercase', letterSpacing: '0.14em', marginBottom: 8 }}>{t('analysis.pending')}</div>
        <h3 style={{ margin: '0 0 6px', fontWeight: 500, fontSize: 16 }}>{(session.name || t('inbox.newPatient')).split(' ')[0]}</h3>
        {liveLoading ? (
          <div style={{ marginTop: 4 }}><div className="spinner sm" /></div>
        ) : (
          <p style={{ fontSize: 12, color: 'var(--fg-3)', lineHeight: 1.5, margin: 0 }}>{t('analysis.pending.body')}</p>
        )}
      </div>
    </div>
  );

  const priorityColor = a.priority === 'Hot' ? 'var(--neg)' : a.priority === 'Warm' ? 'var(--warn)' : a.priority === 'Cold' ? 'var(--accent-deep)' : 'var(--fg-3)';
  const sentimentColor = /negative|anxious/i.test(a.sentiment) ? 'var(--neg)'
                       : /positive|decisive|analytical|pragmatic/i.test(a.sentiment) ? 'var(--pos)'
                       : 'var(--fg-2)';

  return (
    <div className="chat-analysis">
      <div style={{ padding: '20px 22px 0' }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 4 }}>
          <div className="mono" style={{ fontSize: 10, color: 'var(--fg-3)', textTransform: 'uppercase', letterSpacing: '0.14em' }}>{t('analysis.title')}</div>
          {isMock && <span style={{ fontSize: 9, fontWeight: 600, padding: '2px 8px', borderRadius: 999, background: 'rgba(180,83,9,0.12)', color: 'var(--warn)', letterSpacing: '0.06em' }}>{t('common.demo')}</span>}
        </div>
        <h3 style={{ margin: '4px 0 14px', fontWeight: 500, fontSize: 18, lineHeight: 1.2 }}>{(session.name || t('inbox.patient')).split(' ')[0]}</h3>
        <div style={{ display: 'flex', gap: 8, marginBottom: 14, flexWrap: 'wrap' }}>
          <span style={{ fontSize: 10, fontWeight: 700, padding: '3px 10px', borderRadius: 999, background: priorityColor, color: 'white', textTransform: 'uppercase', letterSpacing: '0.06em' }}>{a.priority}</span>
          <span style={{ fontSize: 10, fontWeight: 600, padding: '3px 10px', borderRadius: 999, background: 'var(--bg-soft)', color: 'var(--fg-2)' }}>{t('analysis.score')} {a.leadScore}/5</span>
          <span style={{ fontSize: 10, fontWeight: 500, padding: '3px 10px', borderRadius: 999, background: 'var(--bg-soft)', color: sentimentColor }}>{a.sentiment}</span>
          {a.urgency && a.urgency !== '—' && <span style={{ fontSize: 10, fontWeight: 600, padding: '3px 10px', borderRadius: 999, background: 'var(--accent-soft)', color: 'var(--accent-deep)' }}>{a.urgency}</span>}
        </div>
      </div>
      <div style={{ padding: '0 22px', overflowY: 'auto', flex: 1, paddingBottom: 22 }}>
        <div style={{ marginBottom: 18 }}>
          <div className="mono" style={{ fontSize: 9, color: 'var(--fg-4)', textTransform: 'uppercase', letterSpacing: '0.14em', marginBottom: 6 }}>{t('analysis.summary')}</div>
          <p style={{ margin: 0, fontSize: 12.5, lineHeight: 1.55 }}>{a.summary}</p>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 18 }}>
          {[
            [t('analysis.intent'),     a.intent],
            [t('analysis.specialty'),  a.specialty],
            [t('analysis.doctor'),     a.doctor],
            [t('analysis.genderPref'), a.gender],
            [t('analysis.reason'),     a.reason],
            [t('analysis.urgency'),    a.urgency]
          ].map(([k, v], i) => (
            <div key={i} style={{ background: 'var(--bg-soft)', padding: '10px 12px', borderRadius: 8 }}>
              <div className="mono" style={{ fontSize: 9, color: 'var(--fg-4)', textTransform: 'uppercase', letterSpacing: '0.14em', marginBottom: 4 }}>{k}</div>
              <div style={{ fontSize: 12.5, color: 'var(--fg)' }}>{v || '—'}</div>
            </div>
          ))}
        </div>
        {a.keyDetails && a.keyDetails.length > 0 && (
          <div style={{ marginBottom: 18 }}>
            <div className="mono" style={{ fontSize: 9, color: 'var(--fg-4)', textTransform: 'uppercase', letterSpacing: '0.14em', marginBottom: 8 }}>{t('analysis.keyDetails')}</div>
            <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 6 }}>
              {a.keyDetails.map((d, i) => (
                <li key={i} style={{ display: 'flex', gap: 8, fontSize: 12.5, lineHeight: 1.5 }}>
                  <span style={{ color: 'var(--fg-3)', flexShrink: 0, marginTop: 6 }}>
                    <svg width="4" height="4" viewBox="0 0 4 4"><circle cx="2" cy="2" r="2" fill="currentColor"/></svg>
                  </span>
                  {d}
                </li>
              ))}
            </ul>
          </div>
        )}
        <div style={{ background: 'rgba(4,120,87,0.08)', border: '1px solid rgba(4,120,87,0.2)', padding: '12px 14px', borderRadius: 8, marginBottom: 14 }}>
          <div className="mono" style={{ fontSize: 9, color: 'var(--pos)', textTransform: 'uppercase', letterSpacing: '0.14em', marginBottom: 6 }}>{t('analysis.nextAction')}</div>
          <p style={{ margin: 0, fontSize: 12.5, lineHeight: 1.55 }}>{a.nextAction}</p>
        </div>
        {a.risks && (
          <div style={{ background: 'rgba(185,28,28,0.06)', border: '1px solid rgba(185,28,28,0.18)', padding: '12px 14px', borderRadius: 8, marginBottom: 14 }}>
            <div className="mono" style={{ fontSize: 9, color: 'var(--neg)', textTransform: 'uppercase', letterSpacing: '0.14em', marginBottom: 6 }}>{t('analysis.risks')}</div>
            <p style={{ margin: 0, fontSize: 12.5, lineHeight: 1.55 }}>{a.risks}</p>
          </div>
        )}
        {a.tags && a.tags.length > 0 && (
          <div>
            <div className="mono" style={{ fontSize: 9, color: 'var(--fg-4)', textTransform: 'uppercase', letterSpacing: '0.14em', marginBottom: 6 }}>{t('analysis.tags')}</div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 5 }}>
              {a.tags.map((tag, i) => <span key={i} className="mono" style={{ fontSize: 10, padding: '3px 8px', borderRadius: 999, background: 'var(--bg-soft)', color: 'var(--fg-3)' }}>{tag}</span>)}
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

const Inbox = () => {
  const mockChats = window.__mockChats || [];
  const [userId, setUserId] = useStateC(null);
  const [sessions, setSessions] = useStateC([]);
  const [activeId, setActiveId] = useStateC(null);

  useEffectC(() => {
    let cancelled = false;
    window.__api.getUser().then(u => {
      if (cancelled || !u) return;
      setUserId(u.id);
      const s = loadSessions(u.id);
      setSessions(s);
      setActiveId(s.length > 0 ? s[0].phone : (mockChats[0]?.id || null));
    });
    return () => { cancelled = true; };
  }, []);
  useEffectC(() => { if (userId) saveSessions(userId, sessions); }, [sessions, userId]);

  const handleNew = async () => {
    if (!userId) return;
    const phone = newSessionId();
    const newSession = { phone, name: '', language: 'en', lastActivity: new Date().toISOString(), lastMessagePreview: '' };
    try {
      await window.__api.sbInsert('hsp_patients', {
        phone, name: 'New Patient', language: 'en', status: 'new', owner_id: userId, source: 'web'
      });
    } catch (e) { console.warn('[patient insert]', e); }
    setSessions(prev => [newSession, ...prev]);
    setActiveId(phone);
  };
  const bumpActivity = (phone, preview) => {
    setSessions(prev => prev.map(s => s.phone === phone ? { ...s, lastActivity: new Date().toISOString(), lastMessagePreview: (preview || '').slice(0, 80) } : s));
  };
  const syncLead = (phone, patch) => {
    setSessions(prev => prev.map(s => s.phone === phone ? { ...s, ...patch } : s));
  };

  const activeSession = useMemoC(() => {
    if (!activeId) return null;
    const live = sessions.find(s => s.phone === activeId);
    if (live) return { ...live, isMock: false };
    const mock = mockChats.find(m => m.id === activeId);
    if (mock) return {
      phone: mock.id, name: mock.name, language: mock.language || 'en',
      isMock: true, scenario: mock.scenario, analysis: mock.analysis,
      _preloadedMessages: mock.messages
    };
    return null;
  }, [activeId, sessions, mockChats]);

  return (
    <div className="chat-shell view">
      <SessionList sessions={sessions} mockChats={mockChats} activeId={activeId} onPick={setActiveId} onNew={handleNew} />
      {activeSession
        ? <ChatPanel key={activeSession.phone} session={activeSession} onBumpActivity={bumpActivity} onSyncLead={syncLead} />
        : <div className="chat-main" style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <div style={{ textAlign: 'center', color: 'var(--fg-3)' }}>
              <div className="mono" style={{ fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.14em', marginBottom: 10 }}>No conversation selected</div>
              <h2 style={{ margin: '0 0 12px', fontWeight: 500 }}>Pick a demo or start a live chat</h2>
              <button className="btn primary" onClick={handleNew}><Icon name="plus" size={13} /> New conversation</button>
            </div>
          </div>}
      <AnalysisPanel session={activeSession} />
    </div>
  );
};

window.Inbox = Inbox;
