'use client';
import { useState, useEffect, useRef, useCallback } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { Send, ArrowLeft, Volume2, BookOpen, CheckCircle, Circle, ChevronRight, Lock, Mic } from 'lucide-react';
import ReactMarkdown from 'react-markdown';
import toast from 'react-hot-toast';
import ProgressBar from './ProgressBar';
import LoadingSpinner from './LoadingSpinner';
import GeminiVoiceButton, { type VoiceState } from './voice/GeminiVoiceButton';
import VoiceBottomSheet from './voice/VoiceBottomSheet';
import { SkeletonMessage } from './mobile/SkeletonCard';
import { VoiceAgent, checkVoiceSupport } from '@/utils/voiceAgent';
import { interview as interviewApi, book as bookApi, type Client, type User, type Message, type Chapter, type InterviewState } from '@/utils/api';
import { getSportEmoji } from '@/utils/analytics';
import { useRouter } from 'next/navigation';

const PART_COLORS: Record<number, string> = { 1: '#6366f1', 2: '#a855f7', 3: '#f59e0b', 4: '#10b981' };
const PART_NAMES:  Record<number, string> = { 1: 'ROOTS', 2: 'THE JOURNEY', 3: 'GLORY', 4: 'LEGACY' };

interface Props {
  client: Client;
  user: User | null;
  onBack: () => void;
  onClientUpdate: (c: Client) => void;
}

type UIPhase = 'loading' | 'chapter_select' | 'interviewing' | 'chapter_complete' | 'all_done';

// ── useMediaQuery hook ─────────────────────────────────────────────────────────
function useIsMobile() {
  const [isMobile, setIsMobile] = useState(false);
  useEffect(() => {
    const check = () => setIsMobile(window.innerWidth < 768);
    check();
    window.addEventListener('resize', check);
    return () => window.removeEventListener('resize', check);
  }, []);
  return isMobile;
}

export default function InterviewInterface({ client, onBack }: Props) {
  const router   = useRouter();
  const isMobile = useIsMobile();

  const [phase, setPhase]               = useState<UIPhase>('loading');
  const [chapters, setChapters]         = useState<Chapter[]>([]);
  const [state, setState]               = useState<InterviewState | null>(null);
  const [activeChapter, setActiveChapter] = useState<Chapter | null>(null);
  const [messages, setMessages]         = useState<Message[]>([]);
  const [input, setInput]               = useState('');
  const [sending, setSending]           = useState(false);
  const [typing, setTyping]             = useState(false);
  const [chapterResponses, setChapterResponses] = useState(0);
  const [canComplete, setCanComplete]   = useState(false);
  const [generatingBook, setGeneratingBook] = useState(false);
  const [autoSaved, setAutoSaved]       = useState(false);

  // Voice state
  const [voiceState, setVoiceState]     = useState<VoiceState>('idle');
  const [voiceSheetOpen, setVoiceSheetOpen] = useState(false);
  const [transcript, setTranscript]     = useState('');
  const [interimTranscript, setInterimTranscript] = useState('');
  const [audioLevel, setAudioLevel]     = useState(0);

  const messagesEndRef = useRef<HTMLDivElement>(null);
  const textareaRef    = useRef<HTMLTextAreaElement>(null);
  const voiceAgentRef  = useRef<VoiceAgent | null>(null);
  const sendingRef     = useRef(false);
  const autoSaveTimer  = useRef<ReturnType<typeof setTimeout> | null>(null);
  const audioCtxRef    = useRef<AudioContext | null>(null);
  const analyserRef    = useRef<AnalyserNode | null>(null);
  const audioLevelTimer = useRef<ReturnType<typeof setInterval> | null>(null);
  const voiceSupport   = checkVoiceSupport();
  // Refs to avoid stale closures in voice callbacks
  const sendMessageRef = useRef<(text: string, isVoice?: boolean) => void>(() => {});
  const voiceSheetOpenRef = useRef(false);
  const setVoiceSheetOpenRef = useRef<(cb: (v: boolean) => boolean) => void>((cb) => {
    voiceSheetOpenRef.current = cb(voiceSheetOpenRef.current);
    setVoiceSheetOpen(voiceSheetOpenRef.current);
  });

  // ── Load state ─────────────────────────────────────────────────────────────
  useEffect(() => { loadState(); }, []); // eslint-disable-line

  const loadState = async () => {
    try {
      const res = await interviewApi.getState(client.id);
      setChapters(res.chapters);
      setState(res.state);
      setMessages(Array.isArray(client.messages) ? client.messages : []);
      setPhase(res.state.completedChapters === 12 ? 'all_done' : 'chapter_select');
    } catch { setPhase('chapter_select'); setChapters([]); }
  };

  // ── Auto-scroll ─────────────────────────────────────────────────────────────
  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [messages, typing]);

  // ── Voice agent init ────────────────────────────────────────────────────────
  useEffect(() => {
    if (!voiceSupport.recognition) return;
    const agent = new VoiceAgent({
      rate: 0.88, pitch: 1.0,
      onListeningChange: (listening) => {
        setVoiceState(prev => {
          // Don't override thinking/speaking states
          if (prev === 'thinking' || prev === 'speaking') return prev;
          return listening ? 'listening' : 'idle';
        });
        if (listening) startAudioLevel();
        else stopAudioLevel();
      },
      onSpeakingChange: (speaking) => {
        if (speaking) {
          setVoiceState('speaking');
        } else {
          setVoiceState('idle');
          // After speaking done, auto-listen again if sheet is open
          if (voiceSheetOpenRef.current) {
            setTimeout(() => {
              setVoiceState('listening');
              agent.startListening();
            }, 600);
          }
        }
      },
      onTranscript: (t) => setInterimTranscript(t),
      onFinalTranscript: (t) => {
        setTranscript(t);
        setInterimTranscript('');
        setVoiceState('thinking');
        agent.stopListening();
        stopAudioLevel();
        sendMessageRef.current(t, true); // isVoice = true
      },
      onError: (err) => {
        console.warn('Voice error:', err);
        setVoiceState('idle');
      },
    });
    voiceAgentRef.current = agent;
    return () => { agent.stop(); stopAudioLevel(); };
  }, []); // eslint-disable-line

  // ── Audio level meter ───────────────────────────────────────────────────────
  const startAudioLevel = async () => {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      audioCtxRef.current = new AudioContext();
      analyserRef.current = audioCtxRef.current.createAnalyser();
      analyserRef.current.fftSize = 256;
      const src = audioCtxRef.current.createMediaStreamSource(stream);
      src.connect(analyserRef.current);
      const data = new Uint8Array(analyserRef.current.frequencyBinCount);
      audioLevelTimer.current = setInterval(() => {
        analyserRef.current?.getByteFrequencyData(data);
        const avg = data.reduce((a, b) => a + b, 0) / data.length;
        setAudioLevel(Math.min(100, avg * 2));
      }, 50);
    } catch { /* mic permission denied */ }
  };

  const stopAudioLevel = () => {
    if (audioLevelTimer.current) { clearInterval(audioLevelTimer.current); audioLevelTimer.current = null; }
    if (audioCtxRef.current) { audioCtxRef.current.close(); audioCtxRef.current = null; }
    setAudioLevel(0);
  };

  // ── Start chapter ───────────────────────────────────────────────────────────
  const startChapter = async (chapter: Chapter) => {
    setActiveChapter(chapter);
    setSending(true);
    setTyping(true);
    setPhase('interviewing');
    try {
      const res = await interviewApi.startChapter({ clientId: client.id, chapterNum: chapter.num });
      setState(res.state);
      setMessages(prev => [...prev, { role: 'assistant', content: res.response, chapterNum: chapter.num, timestamp: new Date().toISOString() }]);
      setChapterResponses(0);
      setCanComplete(false);
      // Auto-speak on mobile when voice sheet is open
      if (voiceSheetOpenRef.current && voiceAgentRef.current) {
        setVoiceState('speaking');
        voiceAgentRef.current.speak(res.response);
      }
    } catch (err: any) {
      toast.error(err.message || 'Failed to start chapter');
      setPhase('chapter_select');
    } finally { setSending(false); setTyping(false); }
  };

  // ── Send message ────────────────────────────────────────────────────────────
  const sendMessage = useCallback(async (text: string, isVoice = false) => {
    if (sendingRef.current || !text.trim() || !activeChapter) return;
    sendingRef.current = true;
    setSending(true);
    setTyping(true);
    setVoiceState('thinking');

    setMessages(prev => [...prev, { role: 'user', content: text, chapterNum: activeChapter.num, timestamp: new Date().toISOString() }]);
    setInput('');
    setTranscript('');

    try {
      const res = await interviewApi.sendMessage({ clientId: client.id, message: text, chapterNum: activeChapter.num, isVoice });
      setTyping(false);
      setMessages(prev => [...prev, { role: 'assistant', content: res.response, chapterNum: activeChapter.num, timestamp: new Date().toISOString() }]);
      setChapterResponses(res.chapterUserResponses);
      setCanComplete(res.canComplete);
      setState(res.state);

      // Haptic on response
      if ('vibrate' in navigator) navigator.vibrate([30, 50, 30]);

      // ✅ Always speak AI response if voice sheet is open
      if (voiceSheetOpenRef.current && voiceAgentRef.current) {
        setVoiceState('speaking');
        voiceAgentRef.current.speak(res.response);
        // onSpeakingChange(false) will auto-trigger listening again
      } else {
        setVoiceState('idle');
      }

      if (autoSaveTimer.current) clearTimeout(autoSaveTimer.current);
      setAutoSaved(false);
      autoSaveTimer.current = setTimeout(() => { setAutoSaved(true); setTimeout(() => setAutoSaved(false), 3000); }, 1500);
    } catch (err: any) {
      setTyping(false);
      setVoiceState('idle');
      toast.error(err.message || 'Failed to send');
      setMessages(prev => prev.slice(0, -1));
    } finally { setSending(false); sendingRef.current = false; }
  }, [activeChapter, client.id]); // removed voiceSheetOpen from deps — using ref instead

  // Keep sendMessageRef in sync
  useEffect(() => { sendMessageRef.current = sendMessage; }, [sendMessage]);

  // ── Complete chapter ────────────────────────────────────────────────────────
  const completeChapter = async () => {
    if (!activeChapter) return;
    setSending(true);
    try {
      const res = await interviewApi.completeChapter({ clientId: client.id, chapterNum: activeChapter.num });
      setState(res.state);
      setMessages(prev => [...prev, { role: 'assistant', content: res.closingMessage, chapterNum: activeChapter.num, type: 'chapter_closing', timestamp: new Date().toISOString() }]);
      if ('vibrate' in navigator) navigator.vibrate([50, 100, 50, 100, 50]);
      setPhase(res.isAllDone ? 'all_done' : 'chapter_complete');
    } catch (err: any) { toast.error(err.message || 'Failed to complete chapter'); }
    finally { setSending(false); }
  };

  // ── Voice button tap ────────────────────────────────────────────────────────
  const handleVoiceTap = useCallback(() => {
    if (!voiceAgentRef.current) {
      toast.error('Voice not supported in this browser');
      return;
    }
    if (voiceState === 'listening') {
      voiceAgentRef.current.stopListening();
      setVoiceState('idle');
    } else if (voiceState === 'idle') {
      voiceSheetOpenRef.current = true;
      setVoiceSheetOpen(true);
      setVoiceState('listening');
      voiceAgentRef.current.startListening();
    }
  }, [voiceState]);

  const handleVoiceSheetClose = () => {
    voiceAgentRef.current?.stop();
    voiceSheetOpenRef.current = false;
    setVoiceSheetOpen(false);
    setVoiceState('idle');
    setTranscript('');
    setInterimTranscript('');
    stopAudioLevel();
  };

  const handleGenerateBook = async () => {
    setGeneratingBook(true);
    try {
      await bookApi.generate(client.id);
      toast.success('Book generated!');
      router.push(`/book/${client.id}`);
    } catch (err: any) { toast.error(err.message || 'Failed to generate book'); }
    finally { setGeneratingBook(false); }
  };

  const speakMessage = (text: string) => {
    if ('speechSynthesis' in window) {
      window.speechSynthesis.cancel();
      const utt = new SpeechSynthesisUtterance(text.replace(/[#*_`]/g, ''));
      utt.rate = 0.92; utt.pitch = 1.05;
      window.speechSynthesis.speak(utt);
    }
  };

  const currentChapterMsgs = messages.filter(m => m.chapterNum === activeChapter?.num && m.role !== 'system' && m.content);
  const completedCount = state?.completedChapters ?? 0;
  const overallProgress = state?.progress ?? 0;
  const partColor = PART_COLORS[activeChapter?.part || 1];

  // Live preview state
  const [livePreview, setLivePreview] = useState<string | null>(null);
  const [loadingPreview, setLoadingPreview] = useState(false);
  const previewTimer = useRef<ReturnType<typeof setTimeout> | null>(null);

  // Fetch live preview after every 3 user responses
  useEffect(() => {
    if (!activeChapter || chapterResponses < 3 || chapterResponses % 3 !== 0) return;
    if (previewTimer.current) clearTimeout(previewTimer.current);
    previewTimer.current = setTimeout(async () => {
      setLoadingPreview(true);
      try {
        const res = await bookApi.preview(client.id, activeChapter.num);
        if (res.preview) setLivePreview(res.preview);
      } catch { /* silent */ }
      finally { setLoadingPreview(false); }
    }, 1000);
  }, [chapterResponses, activeChapter, client.id]);

  return (
    <div className="h-screen flex flex-col" style={{ background: 'var(--bg-secondary)' }}>

      {/* Header */}
      <header className="flex-shrink-0 border-b px-4 py-3 flex items-center gap-3 safe-top"
        style={{ background: 'var(--bg-card)', borderColor: 'var(--border)' }}>
        <button onClick={onBack} className="btn-ghost p-2 rounded-lg touch-target" aria-label="Go back to dashboard">
          <ArrowLeft className="w-4 h-4" />
        </button>
        <div className="flex items-center gap-2 flex-1 min-w-0">
          <span className="text-xl">{getSportEmoji(client.sport)}</span>
          <div className="min-w-0">
            <h1 className="font-bold text-sm truncate" style={{ color: 'var(--text-primary)' }}>{client.name}</h1>
            <p className="text-xs truncate" style={{ color: 'var(--text-secondary)' }}>{client.bookTitle}</p>
          </div>
        </div>
        <div className="flex items-center gap-2 flex-shrink-0">
          <div className="hidden sm:flex items-center gap-2">
            <span className="text-xs font-semibold" style={{ color: 'var(--text-secondary)' }}>{completedCount}/12</span>
            <div className="w-20"><ProgressBar value={overallProgress} /></div>
          </div>
          <AnimatePresence>
            {autoSaved && (
              <motion.span initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}
                className="text-xs text-green-500 hidden sm:block">✓</motion.span>
            )}
          </AnimatePresence>
          {completedCount >= 3 && (
            <button onClick={handleGenerateBook} disabled={generatingBook}
              className="btn-primary flex items-center gap-1.5 text-xs py-2">
              {generatingBook ? <LoadingSpinner size="sm" /> : <BookOpen className="w-3.5 h-3.5" />}
              <span className="hidden sm:inline">Generate Book</span>
            </button>
          )}
        </div>
      </header>

      <div className="flex-1 flex overflow-hidden">

        {/* ── Desktop: Chapter sidebar ── */}
        <aside className="hidden lg:flex flex-col w-64 border-r flex-shrink-0 overflow-y-auto"
          style={{ borderColor: 'var(--border)', background: 'var(--bg-card)' }}>
          <div className="p-3">
            <p className="text-xs font-semibold uppercase tracking-wider mb-3" style={{ color: 'var(--text-secondary)' }}>Book Chapters</p>
            {[1,2,3,4].map(part => (
              <div key={part} className="mb-3">
                <p className="text-xs font-bold mb-1.5 px-1" style={{ color: PART_COLORS[part] }}>
                  Part {part}: {PART_NAMES[part]}
                </p>
                {chapters.filter(c => c.part === part).map(ch => {
                  const chData = state?.chapterData[ch.num];
                  const isDone = chData?.isComplete;
                  const isActive = activeChapter?.num === ch.num && phase === 'interviewing';
                  const isLocked = ch.num > 1 && !state?.chapterData[ch.num - 1]?.isComplete;
                  return (
                    <button key={ch.num}
                      onClick={() => !isLocked && !isDone && phase !== 'interviewing' && startChapter(ch)}
                      disabled={isLocked || (phase === 'interviewing' && !isActive)}
                      className="w-full text-left px-2 py-2 rounded-lg mb-0.5 flex items-center gap-2 transition-all text-xs"
                      style={isActive ? { background: `${PART_COLORS[part]}18`, color: PART_COLORS[part], fontWeight: 600 }
                        : isDone ? { color: '#10b981' }
                        : isLocked ? { color: 'var(--text-secondary)', opacity: 0.4 }
                        : { color: 'var(--text-secondary)' }}>
                      <span className="flex-shrink-0">
                        {isDone ? <CheckCircle className="w-3.5 h-3.5 text-green-500" />
                          : isLocked ? <Lock className="w-3.5 h-3.5" />
                          : isActive ? <ChevronRight className="w-3.5 h-3.5" style={{ color: PART_COLORS[part] }} />
                          : <Circle className="w-3.5 h-3.5" />}
                      </span>
                      <span className="truncate">{ch.num}. {ch.title}</span>
                    </button>
                  );
                })}
              </div>
            ))}
          </div>

          {/* Live chapter preview */}
          {(livePreview || loadingPreview) && activeChapter && (
            <div className="mx-3 mb-3 p-3 rounded-xl border"
              style={{ background: `${PART_COLORS[activeChapter.part]}08`, borderColor: `${PART_COLORS[activeChapter.part]}30` }}>
              <p className="text-xs font-semibold mb-2 flex items-center gap-1"
                style={{ color: PART_COLORS[activeChapter.part] }}>
                ✍️ Live Preview
              </p>
              {loadingPreview ? (
                <div className="space-y-1.5">
                  <div className="skeleton h-3 w-full rounded" />
                  <div className="skeleton h-3 w-4/5 rounded" />
                  <div className="skeleton h-3 w-3/4 rounded" />
                </div>
              ) : (
                <p className="text-xs leading-relaxed italic" style={{ color: 'var(--text-secondary)' }}>
                  "{livePreview?.slice(0, 200)}..."
                </p>
              )}
            </div>
          )}
        </aside>

        {/* ── Main content ── */}
        <div className="flex-1 flex flex-col min-w-0 relative">

          {/* LOADING */}
          {phase === 'loading' && (
            <div className="flex-1 p-4 space-y-4">
              {[1,2,3].map(i => <SkeletonMessage key={i} isUser={i % 2 === 0} />)}
            </div>
          )}

          {/* CHAPTER SELECT */}
          {phase === 'chapter_select' && (
            <div className="flex-1 overflow-y-auto p-4 pb-safe">
              <div className="max-w-2xl mx-auto">
                <motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} className="text-center mb-6">
                  <div className="text-5xl mb-3">{getSportEmoji(client.sport)}</div>
                  <h2 className="text-xl font-bold mb-1" style={{ color: 'var(--text-primary)' }}>
                    {completedCount === 0 ? `Welcome, ${client.name}!` : 'Continue Your Story'}
                  </h2>
                  <p className="text-sm" style={{ color: 'var(--text-secondary)' }}>
                    {completedCount === 0
                      ? 'Your biography will be built chapter by chapter.'
                      : `${completedCount} of 12 chapters complete.`}
                  </p>
                  {completedCount > 0 && (
                    <div className="mt-3 max-w-xs mx-auto">
                      <ProgressBar value={overallProgress} />
                      <p className="text-xs mt-1" style={{ color: 'var(--text-secondary)' }}>{overallProgress}% complete</p>
                    </div>
                  )}
                </motion.div>

                {[1,2,3,4].map(part => (
                  <div key={part} className="mb-5">
                    <div className="flex items-center gap-2 mb-2">
                      <div className="h-px flex-1" style={{ background: PART_COLORS[part] + '40' }} />
                      <span className="text-xs font-bold px-2" style={{ color: PART_COLORS[part] }}>
                        PART {part}: {PART_NAMES[part]}
                      </span>
                      <div className="h-px flex-1" style={{ background: PART_COLORS[part] + '40' }} />
                    </div>
                    <div className="grid grid-cols-1 sm:grid-cols-3 gap-2">
                      {chapters.filter(c => c.part === part).map((ch, idx) => {
                        const chData = state?.chapterData[ch.num];
                        const isDone = chData?.isComplete;
                        const isLocked = ch.num > 1 && !state?.chapterData[ch.num - 1]?.isComplete;
                        return (
                          <motion.button key={ch.num}
                            initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }}
                            transition={{ delay: idx * 0.05 }}
                            onClick={() => !isLocked && !isDone && startChapter(ch)}
                            disabled={isLocked || isDone}
                            whileTap={{ scale: isLocked || isDone ? 1 : 0.97 }}
                            className="p-4 rounded-xl text-left border touch-target"
                            style={isDone
                              ? { background: 'rgba(16,185,129,0.08)', borderColor: '#10b981', cursor: 'default' }
                              : isLocked
                              ? { background: 'var(--bg-secondary)', borderColor: 'var(--border)', opacity: 0.5, cursor: 'not-allowed' }
                              : { background: `${PART_COLORS[part]}08`, borderColor: `${PART_COLORS[part]}40`, cursor: 'pointer' }}>
                            <div className="flex items-center justify-between mb-2">
                              <span className="text-xs font-bold" style={{ color: isDone ? '#10b981' : isLocked ? 'var(--text-secondary)' : PART_COLORS[part] }}>
                                Ch. {ch.num}
                              </span>
                              {isDone ? <CheckCircle className="w-4 h-4 text-green-500" />
                                : isLocked ? <Lock className="w-4 h-4" style={{ color: 'var(--text-secondary)' }} />
                                : <ChevronRight className="w-4 h-4" style={{ color: PART_COLORS[part] }} />}
                            </div>
                            <p className="text-sm font-semibold mb-1" style={{ color: 'var(--text-primary)' }}>{ch.title}</p>
                            <p className="text-xs" style={{ color: 'var(--text-secondary)' }}>
                              {ch.theme.split(',').slice(0, 2).join(', ')}
                            </p>
                          </motion.button>
                        );
                      })}
                    </div>
                  </div>
                ))}

                {completedCount >= 3 && (
                  <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }}
                    className="mt-4 p-4 rounded-xl text-center"
                    style={{ background: 'rgba(99,102,241,0.08)', border: '1px solid rgba(99,102,241,0.2)' }}>
                    <p className="text-sm font-semibold mb-2" style={{ color: 'var(--text-primary)' }}>
                      🎉 {completedCount} chapters ready!
                    </p>
                    <button onClick={handleGenerateBook} disabled={generatingBook} className="btn-primary">
                      {generatingBook ? <><LoadingSpinner size="sm" /> Generating...</> : <><BookOpen className="w-4 h-4 inline mr-1" /> Generate Book</>}
                    </button>
                  </motion.div>
                )}
              </div>
            </div>
          )}

          {/* INTERVIEWING */}
          {(phase === 'interviewing' || phase === 'chapter_complete') && activeChapter && (
            <>
              {/* Chapter banner */}
              <div className="flex-shrink-0 px-4 py-2 flex items-center justify-between"
                style={{ background: `${partColor}12`, borderBottom: `1px solid ${partColor}30` }}>
                <div className="min-w-0">
                  <span className="text-xs font-bold" style={{ color: partColor }}>
                    Ch. {activeChapter.num}: {activeChapter.title}
                  </span>
                  <span className="text-xs ml-2 hidden sm:inline" style={{ color: 'var(--text-secondary)' }}>
                    {PART_NAMES[activeChapter.part]}
                  </span>
                </div>
                <div className="flex items-center gap-2 flex-shrink-0">
                  <span className="text-xs" style={{ color: 'var(--text-secondary)' }}>
                    {chapterResponses}/{activeChapter.minResponses}
                  </span>
                  {phase === 'interviewing' && canComplete && (
                    <motion.button initial={{ scale: 0.9 }} animate={{ scale: 1 }}
                      onClick={completeChapter} disabled={sending}
                      className="flex items-center gap-1 px-2.5 py-1.5 rounded-lg text-xs font-semibold text-white touch-target"
                      style={{ background: partColor }}>
                      <CheckCircle className="w-3 h-3" /> Complete
                    </motion.button>
                  )}
                  {phase === 'chapter_complete' && (
                    <button onClick={() => setPhase('chapter_select')}
                      className="px-2.5 py-1.5 rounded-lg text-xs font-semibold text-white touch-target"
                      style={{ background: '#10b981' }}>
                      Next →
                    </button>
                  )}
                </div>
              </div>

              {/* Messages */}
              <div className={`flex-1 overflow-y-auto p-4 space-y-4 ${isMobile ? 'mobile-voice-space' : ''}`}>
                <AnimatePresence initial={false}>
                  {currentChapterMsgs.map((msg, i) => (
                    <motion.div key={i}
                      initial={{ opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.2 }}
                      className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'} gap-2`}>
                      {msg.role === 'assistant' && (
                        <div className="w-7 h-7 rounded-full flex items-center justify-center text-white text-xs font-bold flex-shrink-0 mt-1"
                          style={{ background: `linear-gradient(135deg, ${partColor}, #a855f7)` }}>J</div>
                      )}
                      <div className={msg.role === 'user' ? 'msg-user' : 'msg-ai'}>
                        <div className="text-sm leading-relaxed">
                          <ReactMarkdown>{msg.content || ''}</ReactMarkdown>
                        </div>
                        {msg.role === 'assistant' && (
                          <button onClick={() => speakMessage(msg.content || '')}
                            className="mt-1 flex items-center gap-1 text-xs opacity-40 hover:opacity-80 transition-opacity"
                            style={{ color: 'var(--text-secondary)' }}>
                            <Volume2 className="w-3 h-3" /> Read aloud
                          </button>
                        )}
                      </div>
                      {msg.role === 'user' && (
                        <div className="w-7 h-7 rounded-full flex items-center justify-center text-white text-xs font-bold flex-shrink-0 mt-1"
                          style={{ background: 'linear-gradient(135deg, #a855f7, #6366f1)' }}>
                          {client.name[0].toUpperCase()}
                        </div>
                      )}
                    </motion.div>
                  ))}
                </AnimatePresence>

                {typing && (
                  <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} className="flex items-center gap-2">
                    <div className="w-7 h-7 rounded-full flex items-center justify-center text-white text-xs font-bold"
                      style={{ background: `linear-gradient(135deg, ${partColor}, #a855f7)` }}>J</div>
                    <div className="msg-ai flex items-center gap-1.5 py-3 px-4">
                      <div className="typing-dot" /><div className="typing-dot" style={{ animationDelay: '0.2s' }} /><div className="typing-dot" style={{ animationDelay: '0.4s' }} />
                    </div>
                  </motion.div>
                )}
                <div ref={messagesEndRef} />
              </div>

              {/* Desktop input */}
              {phase === 'interviewing' && !isMobile && (
                <div className="flex-shrink-0 p-4 border-t" style={{ borderColor: 'var(--border)', background: 'var(--bg-card)' }}>
                  {canComplete && (
                    <motion.div initial={{ opacity: 0, y: -4 }} animate={{ opacity: 1, y: 0 }}
                      className="mb-2 px-3 py-2 rounded-lg text-xs"
                      style={{ background: `${partColor}12`, border: `1px solid ${partColor}30`, color: partColor }}>
                      ✓ Great coverage! You can complete this chapter or keep going.
                    </motion.div>
                  )}
                  <div className="flex gap-2 items-end">
                    <button onClick={() => { setVoiceSheetOpen(true); handleVoiceTap(); }}
                      className="w-10 h-10 rounded-xl flex items-center justify-center flex-shrink-0 transition-all"
                      style={{ background: voiceState !== 'idle' ? 'linear-gradient(135deg, #ef4444, #dc2626)' : 'var(--bg-secondary)', border: '1.5px solid var(--border)' }}>
                      <Mic className="w-4 h-4" style={{ color: voiceState !== 'idle' ? 'white' : 'var(--text-secondary)' }} />
                    </button>
                    <textarea ref={textareaRef} value={input}
                      onChange={e => { setInput(e.target.value); e.target.style.height = 'auto'; e.target.style.height = Math.min(e.target.scrollHeight, 120) + 'px'; }}
                      onKeyDown={e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(input); } }}
                      placeholder={sending ? 'James is thinking...' : 'Share your story...'}
                      disabled={sending} rows={1}
                      className="input-field flex-1 resize-none" style={{ minHeight: '44px', maxHeight: '120px' }} />
                    <button onClick={() => sendMessage(input)} disabled={sending || !input.trim()}
                      className="btn-primary w-10 h-10 p-0 flex items-center justify-center flex-shrink-0 disabled:opacity-40">
                      {sending ? <LoadingSpinner size="sm" /> : <Send className="w-4 h-4" />}
                    </button>
                  </div>
                </div>
              )}

              {/* Mobile: Floating voice button */}
              {phase === 'interviewing' && isMobile && (
                <div className="fixed bottom-0 left-0 right-0 z-30 safe-bottom">
                  {/* Text input bar */}
                  <div className="px-4 py-2 flex gap-2 items-end"
                    style={{ background: 'var(--bg-card)', borderTop: '1px solid var(--border)' }}>
                    <textarea value={input}
                      onChange={e => setInput(e.target.value)}
                      onKeyDown={e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(input); } }}
                      placeholder="Type or use voice..."
                      disabled={sending} rows={1}
                      className="input-field flex-1 resize-none text-sm" style={{ minHeight: '40px', maxHeight: '80px' }} />
                    <button onClick={() => sendMessage(input)} disabled={sending || !input.trim()}
                      className="btn-primary w-10 h-10 p-0 flex items-center justify-center flex-shrink-0 disabled:opacity-40">
                      {sending ? <LoadingSpinner size="sm" /> : <Send className="w-4 h-4" />}
                    </button>
                  </div>
                  {/* Gemini voice button */}
                  <div className="flex justify-center pb-4 pt-2" style={{ background: 'var(--bg-card)' }}>
                    <GeminiVoiceButton
                      state={voiceState}
                      audioLevel={audioLevel}
                      onTap={() => { setVoiceSheetOpen(true); handleVoiceTap(); }}
                      size="md"
                    />
                  </div>
                </div>
              )}

              {/* Chapter complete */}
              {phase === 'chapter_complete' && (
                <div className="flex-shrink-0 p-4 border-t text-center safe-bottom"
                  style={{ borderColor: 'var(--border)', background: 'var(--bg-card)' }}>
                  <p className="text-sm font-semibold mb-3" style={{ color: 'var(--text-primary)' }}>
                    ✅ Chapter {activeChapter.num} complete!
                  </p>
                  <div className="flex gap-3 justify-center">
                    <button onClick={() => setPhase('chapter_select')} className="btn-secondary">← Chapters</button>
                    {activeChapter.num < 12 && (
                      <button onClick={() => { const next = chapters.find(c => c.num === activeChapter.num + 1); if (next) startChapter(next); }}
                        className="btn-primary flex items-center gap-1.5">
                        Chapter {activeChapter.num + 1} <ChevronRight className="w-4 h-4" />
                      </button>
                    )}
                  </div>
                </div>
              )}
            </>
          )}

          {/* ALL DONE */}
          {phase === 'all_done' && (
            <div className="flex-1 flex items-center justify-center p-6">
              <motion.div initial={{ opacity: 0, scale: 0.95 }} animate={{ opacity: 1, scale: 1 }} className="text-center max-w-md">
                <div className="text-6xl mb-4">🏆</div>
                <h2 className="text-2xl font-bold mb-2" style={{ color: 'var(--text-primary)' }}>All 12 Chapters Complete!</h2>
                <p className="text-sm mb-6" style={{ color: 'var(--text-secondary)' }}>Time to generate the book.</p>
                <button onClick={handleGenerateBook} disabled={generatingBook} className="btn-primary text-base px-8 py-3">
                  {generatingBook ? <><LoadingSpinner size="sm" /> Generating...</> : <><BookOpen className="w-5 h-5 inline mr-2" /> Generate Full Book</>}
                </button>
              </motion.div>
            </div>
          )}

        </div>
      </div>

      {/* Voice Bottom Sheet (Gemini style) */}
      <VoiceBottomSheet
        isOpen={voiceSheetOpen}
        voiceState={voiceState}
        transcript={transcript}
        interimTranscript={interimTranscript}
        audioLevel={audioLevel}
        recentMessages={currentChapterMsgs.slice(-8)}
        onClose={handleVoiceSheetClose}
        onTap={handleVoiceTap}
        clientName={client.name}
      />
    </div>
  );
}
