import { useEffect, useRef, useState } from 'react'
import { api, streamSuggestionChat, type ChatMessage } from '../../api/client'

interface Props {
  suggestionId: string
  // The English explanation (shown in the card body). Petal's opening bubble is
  // its Simplified-Chinese translation, fetched on open — so the panel doesn't
  // just repeat the same English text twice. Falls back to this on failure.
  explanation: string
}

// CJK fallback stack — Nunito has no Chinese glyphs, and the user asks questions
// in Mandarin (spec Note #17). Applied to the bubbles specifically, not the
// serif editor body.
const CHAT_FONT = "'Nunito', 'PingFang SC', 'Microsoft YaHei', 'Noto Sans CJK SC', sans-serif"

// AskPetal is the mini chat panel inside an expanded SuggestionCard. The whole
// conversation lives in this component's state — nothing is persisted; closing
// the card (unmounting) clears it. Each send streams Petal's reply token-by-
// token into the latest assistant bubble.
export function AskPetal({ suggestionId, explanation }: Props) {
  // Opening bubble starts empty (caret-only) and fills with the Mandarin
  // translation once it lands; `seeding` drives that loading caret.
  const [messages, setMessages] = useState<ChatMessage[]>([{ role: 'assistant', content: '' }])
  const [seeding, setSeeding] = useState(true)
  const [input, setInput] = useState('')
  const [streaming, setStreaming] = useState(false)
  const scrollRef = useRef<HTMLDivElement>(null)
  const inputRef = useRef<HTMLInputElement>(null)

  // Keep the latest bubble in view as tokens arrive.
  useEffect(() => {
    const el = scrollRef.current
    if (el) el.scrollTop = el.scrollHeight
  }, [messages])

  // Focus the input when the panel opens.
  useEffect(() => {
    inputRef.current?.focus()
  }, [])

  // Fetch the Chinese translation of the explanation to seed the first bubble.
  // Only replaces the seed bubble if the user hasn't started chatting yet (the
  // conversation always opens with this one assistant turn). Falls back to the
  // English explanation if the translation can't be fetched.
  useEffect(() => {
    let cancelled = false
    api
      .translateSuggestion(suggestionId)
      .then((res) => {
        if (cancelled) return
        const text = res.translation.trim() || explanation
        setMessages((prev) => (prev.length === 1 ? [{ role: 'assistant', content: text }] : prev))
      })
      .catch(() => {
        if (cancelled) return
        setMessages((prev) => (prev.length === 1 ? [{ role: 'assistant', content: explanation }] : prev))
      })
      .finally(() => {
        if (!cancelled) setSeeding(false)
      })
    return () => {
      cancelled = true
    }
  }, [suggestionId, explanation])

  async function send() {
    const text = input.trim()
    if (!text || streaming) return
    setInput('')

    // Append the user turn plus an empty assistant bubble to stream into.
    const history: ChatMessage[] = [...messages, { role: 'user', content: text }]
    setMessages([...history, { role: 'assistant', content: '' }])
    setStreaming(true)

    try {
      await streamSuggestionChat(suggestionId, history, (token) => {
        setMessages((prev) => {
          const next = prev.slice()
          const last = next[next.length - 1]
          next[next.length - 1] = { ...last, content: last.content + token }
          return next
        })
      })
    } catch (err) {
      setMessages((prev) => {
        const next = prev.slice()
        next[next.length - 1] = {
          role: 'assistant',
          content: 'Sorry, I had trouble responding just now. Please try again. 🌸',
        }
        return next
      })
      console.error('Ask Petal chat failed:', err)
    } finally {
      setStreaming(false)
      inputRef.current?.focus()
    }
  }

  return (
    <div
      className="mt-3 flex flex-col"
      style={{
        borderTop: '1px solid var(--color-border)',
        paddingTop: '0.625rem',
        fontFamily: CHAT_FONT,
      }}
    >
      <div
        ref={scrollRef}
        className="flex flex-col gap-2 overflow-y-auto pr-1"
        style={{ maxHeight: 220 }}
      >
        {messages.map((m, i) => (
          <Bubble
            key={i}
            role={m.role}
            content={m.content}
            streaming={(streaming && i === messages.length - 1) || (seeding && i === 0)}
          />
        ))}
      </div>

      <form
        className="mt-2 flex items-center gap-1.5"
        onSubmit={(e) => {
          e.preventDefault()
          void send()
        }}
      >
        <input
          ref={inputRef}
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder="Ask why… / 问为什么…"
          className="min-w-0 flex-1 rounded-full px-3 py-1.5 text-xs focus:outline-none"
          style={{
            background: 'var(--color-surface-alt)',
            border: '1px solid var(--color-border)',
            color: 'var(--color-plum)',
            fontFamily: CHAT_FONT,
          }}
        />
        <button
          type="submit"
          disabled={streaming || input.trim() === ''}
          className="rounded-full px-3 py-1.5 text-xs font-bold text-white disabled:opacity-50"
          style={{ background: 'var(--color-accent)' }}
        >
          Send
        </button>
      </form>
    </div>
  )
}

// Bubble renders one chat turn: Petal rose-tinted and left-aligned, the user
// lavender and right-aligned. A trailing caret marks the actively streaming
// reply until its first token lands.
function Bubble({
  role,
  content,
  streaming,
}: {
  role: ChatMessage['role']
  content: string
  streaming: boolean
}) {
  const isPetal = role === 'assistant'
  return (
    <div className={`flex ${isPetal ? 'justify-start' : 'justify-end'}`}>
      <div
        className="max-w-[85%] rounded-2xl px-3 py-1.5 text-xs leading-snug"
        style={{
          background: isPetal ? 'var(--color-surface-alt)' : 'var(--color-lavender)',
          color: 'var(--color-plum)',
          fontFamily: CHAT_FONT,
          whiteSpace: 'pre-wrap',
        }}
      >
        {content}
        {streaming && content === '' && (
          <span className="petal-chat-caret" aria-hidden>
            ▍
          </span>
        )}
      </div>
    </div>
  )
}
