'use client'

import { useState, useRef, useEffect, useMemo } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { X, Send, Bot, User, Sparkles, Maximize2, Minimize2, ArrowRight, Volume2, VolumeX } from 'lucide-react'
import { ChatMessage } from '@/lib/types'
import { t } from '@/lib/i18n'
import { SLIDE_ORDER } from '@/lib/hooks/useSlideNavigation'
import { matchFAQMultiple, buildFAQContext } from '@/lib/presenter/faq-matcher'
import {
  ChatFABProps,
  ParsedMessage,
  parseAgentResponse,
  cleanTextForTts,
  detectTtsLanguage,
} from './ChatFAB.helpers'

export default function ChatFAB({
  lang,
  currentSlide,
  currentIndex,
  visitedSlides,
  onGoToSlide,
  presenterState = 'idle',
  onPresenterInterrupt,
}: ChatFABProps) {
  const i = t(lang)
  const [isOpen, setIsOpen] = useState(false)
  const [isExpanded, setIsExpanded] = useState(false)
  const [messages, setMessages] = useState<ChatMessage[]>([])
  const [input, setInput] = useState('')
  const [isStreaming, setIsStreaming] = useState(false)
  const [isWaiting, setIsWaiting] = useState(false)
  const [parsedResponses, setParsedResponses] = useState<Map<number, ParsedMessage>>(new Map())
  const [chatTtsEnabled, setChatTtsEnabled] = useState(true)
  const [isChatSpeaking, setIsChatSpeaking] = useState(false)
  const messagesEndRef = useRef<HTMLDivElement>(null)
  const inputRef = useRef<HTMLInputElement>(null)
  const abortRef = useRef<AbortController | null>(null)
  const chatAudioRef = useRef<HTMLAudioElement | null>(null)
  const ttsAbortRef = useRef<AbortController | null>(null)

  const cancelChatAudio = () => {
    if (chatAudioRef.current) {
      chatAudioRef.current.pause()
      chatAudioRef.current = null
    }
    if (ttsAbortRef.current) {
      ttsAbortRef.current.abort()
      ttsAbortRef.current = null
    }
    setIsChatSpeaking(false)
  }

  const speakResponse = async (text: string) => {
    if (!chatTtsEnabled) return
    cancelChatAudio()

    const cleanText = cleanTextForTts(text)
    if (!cleanText) return

    const controller = new AbortController()
    ttsAbortRef.current = controller

    try {
      const textLang = detectTtsLanguage(cleanText, lang)
      const res = await fetch('/api/presenter/tts', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ text: cleanText, language: textLang }),
        signal: controller.signal,
      })
      if (!res.ok || controller.signal.aborted) return

      const blob = await res.blob()
      const url = URL.createObjectURL(blob)
      const audio = new Audio(url)
      chatAudioRef.current = audio
      setIsChatSpeaking(true)

      audio.onended = () => { setIsChatSpeaking(false); chatAudioRef.current = null }
      audio.onerror = () => { setIsChatSpeaking(false); chatAudioRef.current = null }

      await audio.play()
    } catch {
      setIsChatSpeaking(false)
    }
  }

  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
  }, [messages, parsedResponses])

  useEffect(() => {
    if (isOpen && inputRef.current) {
      setTimeout(() => inputRef.current?.focus(), 200)
    }
  }, [isOpen])

  // Parse the latest assistant message when streaming ends
  const lastAssistantIndex = useMemo(() => {
    for (let idx = messages.length - 1; idx >= 0; idx--) {
      if (messages[idx].role === 'assistant') return idx
    }
    return -1
  }, [messages])

  useEffect(() => {
    if (!isStreaming && lastAssistantIndex >= 0 && !parsedResponses.has(lastAssistantIndex)) {
      const msg = messages[lastAssistantIndex]
      const parsed = parseAgentResponse(msg.content, lang)
      setParsedResponses(prev => new Map(prev).set(lastAssistantIndex, parsed))
      speakResponse(parsed.text)
    }
  }, [isStreaming, lastAssistantIndex, messages, parsedResponses, lang])

  async function sendMessage(text?: string) {
    const message = text || input.trim()
    if (!message || isStreaming) return

    if (presenterState === 'presenting' && onPresenterInterrupt) {
      onPresenterInterrupt()
    }

    cancelChatAudio()
    setInput('')
    setMessages(prev => [...prev, { role: 'user', content: message }])
    setIsStreaming(true)
    setIsWaiting(true)

    const faqMatches = matchFAQMultiple(message, lang, 3)
    const faqContext = buildFAQContext(faqMatches, lang)

    abortRef.current = new AbortController()

    try {
      const requestBody: Record<string, unknown> = {
        message,
        history: messages.slice(-10),
        lang,
        slideContext: {
          currentSlide, currentIndex,
          visitedSlides: Array.from(visitedSlides),
          totalSlides: SLIDE_ORDER.length,
        },
      }

      if (faqContext) requestBody.faqContext = faqContext

      const res = await fetch('/api/chat', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(requestBody),
        signal: abortRef.current.signal,
      })

      if (!res.ok) throw new Error(`HTTP ${res.status}`)

      const reader = res.body!.getReader()
      const decoder = new TextDecoder()
      let content = ''
      let firstChunk = true

      while (true) {
        const { done, value } = await reader.read()
        if (done) break

        content += decoder.decode(value, { stream: true })

        if (firstChunk) {
          firstChunk = false
          setIsWaiting(false)
          setMessages(prev => [...prev, { role: 'assistant', content }])
        } else {
          const currentText = content
          setMessages(prev => {
            const updated = [...prev]
            updated[updated.length - 1] = { role: 'assistant', content: currentText }
            return updated
          })
        }
      }

      // If FAQ matched and has a goto_slide, add a GOTO marker to the response
      const topMatch = faqMatches[0]
      if (topMatch?.goto_slide) {
        const gotoIdx = SLIDE_ORDER.indexOf(topMatch.goto_slide)
        if (gotoIdx >= 0) {
          content += `\n\n[GOTO:${topMatch.goto_slide}]`
          setMessages(prev => {
            const updated = [...prev]
            updated[updated.length - 1] = { role: 'assistant', content }
            return updated
          })
        }
      }
    } catch (err: unknown) {
      if (err instanceof Error && err.name === 'AbortError') return
      console.error('Chat error:', err)
      setIsWaiting(false)
      setMessages(prev => [
        ...prev,
        { role: 'assistant', content: lang === 'de'
          ? 'Verbindung fehlgeschlagen. Bitte versuchen Sie es erneut.'
          : 'Connection failed. Please try again.'
        },
      ])
    } finally {
      setIsStreaming(false)
      setIsWaiting(false)
      abortRef.current = null
    }
  }

  function stopGeneration() {
    if (abortRef.current) { abortRef.current.abort(); setIsStreaming(false) }
  }

  const suggestions = i.aiqa.suggestions.slice(0, 3)

  function renderMessageContent(msg: ChatMessage, idx: number) {
    const parsed = parsedResponses.get(idx)
    const displayText = parsed ? parsed.text : msg.content

    return (
      <>
        <div className="whitespace-pre-wrap">{displayText}</div>
        {isStreaming && idx === messages.length - 1 && msg.role === 'assistant' && (
          <span className="inline-block w-1.5 h-3.5 bg-indigo-400 animate-pulse ml-0.5" />
        )}

        {parsed && parsed.gotos.length > 0 && (
          <div className="mt-2 space-y-1">
            {parsed.gotos.map((g, gi) => (
              <button
                key={gi}
                onClick={() => onGoToSlide(g.index)}
                className="flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg
                  bg-indigo-500/20 border border-indigo-500/30
                  hover:bg-indigo-500/30 transition-colors
                  text-xs text-indigo-300"
              >
                <ArrowRight className="w-3 h-3" />
                {g.label}
              </button>
            ))}
          </div>
        )}

        {parsed && parsed.followUps.length > 0 && !isStreaming && (
          <div className="mt-3 space-y-1.5 border-t border-white/10 pt-2">
            {parsed.followUps.map((q, qi) => (
              <button
                key={qi}
                onClick={() => sendMessage(q)}
                className="block w-full text-left px-2.5 py-2 rounded-lg
                  bg-white/[0.05] border border-white/10
                  hover:bg-white/[0.1] transition-colors
                  text-xs text-white/60 hover:text-white/90"
              >
                {q}
              </button>
            ))}
          </div>
        )}
      </>
    )
  }

  return (
    <>
      {/* FAB Button */}
      <AnimatePresence>
        {!isOpen && (
          <motion.button
            initial={{ scale: 0 }}
            animate={{ scale: 1 }}
            exit={{ scale: 0 }}
            whileHover={{ scale: 1.1 }}
            whileTap={{ scale: 0.95 }}
            onClick={() => setIsOpen(true)}
            className="fixed bottom-6 right-[5.5rem] z-50 w-14 h-14 rounded-full
              bg-indigo-600 hover:bg-indigo-500 text-white
              flex items-center justify-center shadow-lg shadow-indigo-600/30
              transition-colors"
            aria-label={lang === 'de' ? 'Investor Agent öffnen' : 'Open Investor Agent'}
          >
            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z" />
              <circle cx="9" cy="10" r="1" fill="currentColor" />
              <circle cx="12" cy="10" r="1" fill="currentColor" />
              <circle cx="15" cy="10" r="1" fill="currentColor" />
            </svg>
            {presenterState !== 'idle' && (
              <span className="absolute -top-1 -right-1 w-3 h-3 rounded-full bg-green-400 border-2 border-black animate-pulse" />
            )}
          </motion.button>
        )}
      </AnimatePresence>

      {/* Chat Panel */}
      <AnimatePresence>
        {isOpen && (
          <motion.div
            initial={{ opacity: 0, scale: 0.9, y: 20 }}
            animate={{ opacity: 1, scale: 1, y: 0 }}
            exit={{ opacity: 0, scale: 0.9, y: 20 }}
            transition={{ duration: 0.2 }}
            className={`fixed bottom-6 right-6 z-50
              ${isExpanded ? 'w-[700px] h-[80vh]' : 'w-[400px] h-[520px]'}
              rounded-2xl overflow-hidden
              bg-black/90 backdrop-blur-xl border border-white/10
              shadow-2xl shadow-black/50 flex flex-col
              transition-all duration-200`}
          >
            {/* Header */}
            <div className="flex items-center justify-between px-4 py-3 border-b border-white/10 shrink-0">
              <div className="flex items-center gap-2">
                <div className="w-7 h-7 rounded-full bg-indigo-500/20 flex items-center justify-center">
                  <Bot className="w-4 h-4 text-indigo-400" />
                </div>
                <div>
                  <span className="text-sm font-semibold text-white">Investor Agent</span>
                  <span className="text-xs text-white/30 ml-2">
                    {isStreaming
                      ? (lang === 'de' ? 'antwortet...' : 'responding...')
                      : presenterState !== 'idle'
                        ? (lang === 'de' ? 'Presenter aktiv' : 'Presenter active')
                        : (lang === 'de' ? 'online' : 'online')
                    }
                  </span>
                </div>
              </div>
              <div className="flex items-center gap-1">
                <button
                  onClick={() => { setChatTtsEnabled(prev => { if (prev) cancelChatAudio(); return !prev }) }}
                  className={`w-7 h-7 rounded-full flex items-center justify-center transition-colors ${
                    isChatSpeaking ? 'bg-indigo-500/30' : 'bg-white/10 hover:bg-white/20'
                  }`}
                  title={chatTtsEnabled
                    ? (lang === 'de' ? 'Sprachausgabe aus' : 'Mute voice')
                    : (lang === 'de' ? 'Sprachausgabe ein' : 'Unmute voice')
                  }
                >
                  {chatTtsEnabled
                    ? <Volume2 className={`w-3.5 h-3.5 ${isChatSpeaking ? 'text-indigo-400' : 'text-white/60'}`} />
                    : <VolumeX className="w-3.5 h-3.5 text-white/40" />
                  }
                </button>
                <button
                  onClick={() => setIsExpanded(prev => !prev)}
                  className="w-7 h-7 rounded-full bg-white/10 flex items-center justify-center hover:bg-white/20 transition-colors"
                >
                  {isExpanded ? <Minimize2 className="w-3.5 h-3.5 text-white/60" /> : <Maximize2 className="w-3.5 h-3.5 text-white/60" />}
                </button>
                <button
                  onClick={() => { cancelChatAudio(); setIsOpen(false) }}
                  className="w-7 h-7 rounded-full bg-white/10 flex items-center justify-center hover:bg-white/20 transition-colors"
                >
                  <X className="w-4 h-4 text-white/60" />
                </button>
              </div>
            </div>

            {/* Messages */}
            <div className="flex-1 overflow-y-auto px-4 py-3 space-y-3">
              {messages.length === 0 && (
                <div className="space-y-2">
                  <div className="flex items-center gap-2 text-white/40 text-xs mb-3">
                    <Sparkles className="w-3.5 h-3.5" />
                    <span>{lang === 'de' ? 'Fragen Sie den Investor Agent:' : 'Ask the Investor Agent:'}</span>
                  </div>
                  {suggestions.map((q, idx) => (
                    <motion.button
                      key={idx}
                      initial={{ opacity: 0, y: 8 }}
                      animate={{ opacity: 1, y: 0 }}
                      transition={{ delay: 0.1 + idx * 0.08 }}
                      onClick={() => sendMessage(q)}
                      className="block w-full text-left px-3 py-2.5 rounded-xl
                        bg-white/[0.05] border border-white/10
                        hover:bg-white/[0.1] transition-colors
                        text-xs text-white/70 hover:text-white"
                    >
                      {q}
                    </motion.button>
                  ))}
                </div>
              )}

              {/* Waiting indicator */}
              <AnimatePresence>
                {isWaiting && (
                  <motion.div
                    initial={{ opacity: 0, y: 6 }}
                    animate={{ opacity: 1, y: 0 }}
                    exit={{ opacity: 0 }}
                    className="flex gap-2.5"
                  >
                    <div className="w-7 h-7 rounded-full bg-indigo-500/20 flex items-center justify-center shrink-0 mt-0.5">
                      <Bot className="w-3.5 h-3.5 text-indigo-400" />
                    </div>
                    <div className="bg-white/[0.06] rounded-2xl px-3.5 py-3 flex items-center gap-1">
                      {[0, 1, 2].map(dotIdx => (
                        <motion.span
                          key={dotIdx}
                          className="block w-1.5 h-1.5 rounded-full bg-indigo-400/70"
                          animate={{ opacity: [0.3, 1, 0.3], y: [0, -3, 0] }}
                          transition={{ duration: 0.7, repeat: Infinity, delay: dotIdx * 0.15 }}
                        />
                      ))}
                    </div>
                  </motion.div>
                )}
              </AnimatePresence>

              {messages.map((msg, idx) => (
                <div key={idx} className={`flex gap-2.5 ${msg.role === 'user' ? 'justify-end' : ''}`}>
                  {msg.role === 'assistant' && (
                    <div className="w-7 h-7 rounded-full bg-indigo-500/20 flex items-center justify-center shrink-0 mt-0.5">
                      <Bot className="w-3.5 h-3.5 text-indigo-400" />
                    </div>
                  )}
                  <div className={`max-w-[85%] rounded-2xl px-3.5 py-2.5 text-xs leading-relaxed ${
                    msg.role === 'user' ? 'bg-indigo-500/20 text-white' : 'bg-white/[0.06] text-white/80'
                  }`}>
                    {msg.role === 'assistant' ? renderMessageContent(msg, idx) : (
                      <div className="whitespace-pre-wrap">{msg.content}</div>
                    )}
                  </div>
                  {msg.role === 'user' && (
                    <div className="w-7 h-7 rounded-full bg-white/10 flex items-center justify-center shrink-0 mt-0.5">
                      <User className="w-3.5 h-3.5 text-white/60" />
                    </div>
                  )}
                </div>
              ))}
              <div ref={messagesEndRef} />
            </div>

            {/* Input */}
            <div className="border-t border-white/10 px-4 py-3 shrink-0">
              {isStreaming && (
                <button
                  onClick={stopGeneration}
                  className="w-full mb-2 px-3 py-1.5 rounded-lg bg-white/[0.06] hover:bg-white/[0.1]
                    text-xs text-white/50 transition-colors"
                >
                  {lang === 'de' ? 'Antwort stoppen' : 'Stop response'}
                </button>
              )}
              <div className="flex gap-2">
                <input
                  ref={inputRef}
                  type="text"
                  value={input}
                  onChange={(e) => setInput(e.target.value)}
                  onKeyDown={(e) => e.key === 'Enter' && sendMessage()}
                  placeholder={lang === 'de' ? 'Frage stellen...' : 'Ask a question...'}
                  disabled={isStreaming}
                  className="flex-1 bg-white/[0.06] border border-white/10 rounded-xl px-3.5 py-2.5
                    text-xs text-white placeholder-white/30 outline-none
                    focus:border-indigo-500/50 focus:ring-1 focus:ring-indigo-500/20
                    disabled:opacity-50 transition-all"
                />
                <button
                  onClick={() => sendMessage()}
                  disabled={isStreaming || !input.trim()}
                  className="px-3.5 py-2.5 bg-indigo-500 hover:bg-indigo-600 disabled:opacity-30
                    rounded-xl transition-all text-white"
                >
                  <Send className="w-3.5 h-3.5" />
                </button>
              </div>
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </>
  )
}
