'use client'
import React, { useState, useRef, useEffect, useCallback } from 'react'
import type { R42SSEEvent } from '@/types'
import { Button } from '@/components/ui/Button'

interface CitationTopic {
  id: string
  title: string
}

interface Message {
  role: 'user' | 'assistant'
  text: string
  citations?: CitationTopic[]
  outOfScope?: boolean
}

interface R42DrawerProps {
  open: boolean
  onClose: () => void
  userId: string
}

const CHAT_URL = process.env.NEXT_PUBLIC_CHAT_URL ?? 'http://localhost:3004'

export function R42Drawer({ open, onClose, userId }: R42DrawerProps) {
  const [messages, setMessages] = useState<Message[]>([])
  const [input, setInput] = useState('')
  const [streaming, setStreaming] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const bottomRef = useRef<HTMLDivElement>(null)
  const abortRef = useRef<AbortController | null>(null)

  useEffect(() => {
    if (open) {
      bottomRef.current?.scrollIntoView({ behavior: 'smooth' })
    }
  }, [messages, open])

  const handleClose = useCallback(() => {
    abortRef.current?.abort()
    onClose()
  }, [onClose])

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

    setInput('')
    setError(null)
    const userMsg: Message = { role: 'user', text }
    setMessages((prev) => [...prev, userMsg])

    const ctrl = new AbortController()
    abortRef.current = ctrl
    setStreaming(true)

    let assistantText = ''
    let citations: CitationTopic[] = []
    let outOfScope = false

    setMessages((prev) => [...prev, { role: 'assistant', text: '' }])

    try {
      const res = await fetch(`${CHAT_URL}/chat`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ userId, message: text }),
        signal: ctrl.signal,
      })

      if (!res.ok) {
        throw new Error(`Chat service error: ${res.status}`)
      }

      const reader = res.body?.getReader()
      if (!reader) throw new Error('No response body')

      const decoder = new TextDecoder()
      let buffer = ''

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

        buffer += decoder.decode(value, { stream: true })
        const lines = buffer.split('\n')
        buffer = lines.pop() ?? ''

        for (const line of lines) {
          if (!line.startsWith('data: ')) continue
          const raw = line.slice(6).trim()
          if (raw === '[DONE]') continue

          try {
            const event = JSON.parse(raw) as R42SSEEvent
            if (event.type === 'chunk') {
              assistantText += event.text
              setMessages((prev) => {
                const copy = [...prev]
                copy[copy.length - 1] = { role: 'assistant', text: assistantText }
                return copy
              })
            } else if (event.type === 'citations') {
              citations = event.topics
            } else if (event.type === 'out_of_scope') {
              outOfScope = true
              assistantText = event.text
              setMessages((prev) => {
                const copy = [...prev]
                copy[copy.length - 1] = { role: 'assistant', text: assistantText, outOfScope: true }
                return copy
              })
            } else if (event.type === 'done') {
              setMessages((prev) => {
                const copy = [...prev]
                copy[copy.length - 1] = {
                  role: 'assistant',
                  text: assistantText,
                  citations: citations.length > 0 ? citations : undefined,
                  outOfScope,
                }
                return copy
              })
            }
          } catch {
            // skip malformed SSE lines
          }
        }
      }
    } catch (err) {
      if ((err as Error).name === 'AbortError') return
      setError(err instanceof Error ? err.message : 'Failed to send message')
      setMessages((prev) => prev.slice(0, -1))
    } finally {
      setStreaming(false)
    }
  }

  function handleKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>) {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault()
      void sendMessage()
    }
  }

  if (!open) return null

  return (
    <>
      {/* Backdrop */}
      <div
        onClick={handleClose}
        style={{
          position: 'fixed',
          inset: 0,
          background: 'rgba(0,0,0,0.35)',
          zIndex: 300,
        }}
        aria-hidden="true"
      />

      {/* Panel */}
      <div
        role="dialog"
        aria-label="R42 Assistant"
        style={{
          position: 'fixed',
          bottom: 0,
          left: 0,
          right: 0,
          top: 'auto',
          maxHeight: '85dvh',
          background: 'var(--bg)',
          borderTopLeftRadius: 'var(--r-xl)',
          borderTopRightRadius: 'var(--r-xl)',
          boxShadow: '0 -8px 40px rgba(0,0,0,0.18)',
          zIndex: 301,
          display: 'flex',
          flexDirection: 'column',
          // Desktop: side panel
        }}
      >
        {/* Header */}
        <div
          style={{
            padding: 'var(--s-4) var(--s-5)',
            borderBottom: '1px solid var(--cream)',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'space-between',
            flexShrink: 0,
          }}
        >
          <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--s-3)' }}>
            <div
              style={{
                width: '32px',
                height: '32px',
                borderRadius: '50%',
                background: 'var(--accent)',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                color: 'var(--paper)',
                fontWeight: 700,
                fontSize: 'var(--t-small)',
              }}
            >
              R
            </div>
            <span style={{ fontWeight: 600, fontSize: 'var(--t-body)', color: 'var(--fg)' }}>
              R42
            </span>
          </div>
          <button
            onClick={handleClose}
            aria-label="Close R42"
            style={{
              background: 'none',
              border: 'none',
              cursor: 'pointer',
              color: 'var(--fg-muted)',
              fontSize: '24px',
              lineHeight: 1,
              padding: 'var(--s-1)',
              minWidth: '44px',
              minHeight: '44px',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
            }}
          >
            ×
          </button>
        </div>

        {/* Messages */}
        <div
          style={{
            flex: 1,
            overflowY: 'auto',
            padding: 'var(--s-4) var(--s-5)',
            display: 'flex',
            flexDirection: 'column',
            gap: 'var(--s-4)',
          }}
        >
          {messages.length === 0 && (
            <div
              style={{
                textAlign: 'center',
                color: 'var(--fg-muted)',
                fontSize: 'var(--t-body)',
                marginTop: 'var(--s-6)',
              }}
            >
              Ask R42 anything about the knowledge base.
            </div>
          )}

          {messages.map((msg, idx) => (
            <div
              key={idx}
              style={{
                display: 'flex',
                flexDirection: 'column',
                alignItems: msg.role === 'user' ? 'flex-end' : 'flex-start',
                gap: 'var(--s-2)',
              }}
            >
              <div
                style={{
                  maxWidth: '85%',
                  background: msg.role === 'user' ? 'var(--accent)' : 'var(--bg-warm)',
                  color: msg.role === 'user' ? 'var(--paper)' : 'var(--fg)',
                  borderRadius:
                    msg.role === 'user'
                      ? 'var(--r-md) var(--r-md) var(--r-sm) var(--r-md)'
                      : 'var(--r-md) var(--r-md) var(--r-md) var(--r-sm)',
                  padding: 'var(--s-3) var(--s-4)',
                  fontSize: 'var(--t-body)',
                  lineHeight: 1.6,
                  opacity: msg.outOfScope ? 0.75 : 1,
                }}
              >
                {msg.text || (msg.role === 'assistant' && streaming && idx === messages.length - 1 ? (
                  <StreamingDots />
                ) : null)}
              </div>
              {msg.citations && msg.citations.length > 0 && (
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 'var(--s-2)', maxWidth: '85%' }}>
                  {msg.citations.map((c) => (
                    <span
                      key={c.id}
                      style={{
                        display: 'inline-block',
                        background: 'var(--accent-soft)',
                        color: 'var(--teal-900)',
                        borderRadius: 'var(--r-pill)',
                        fontSize: 'var(--t-small)',
                        padding: '2px var(--s-3)',
                      }}
                    >
                      {c.title}
                    </span>
                  ))}
                </div>
              )}
            </div>
          ))}

          {error && (
            <div
              style={{
                color: '#c0392b',
                fontSize: 'var(--t-small)',
                padding: 'var(--s-2) var(--s-4)',
                background: '#f8d7da',
                borderRadius: 'var(--r-sm)',
              }}
            >
              {error}
            </div>
          )}
          <div ref={bottomRef} />
        </div>

        {/* Input */}
        <div
          style={{
            padding: 'var(--s-3) var(--s-5) var(--s-5)',
            borderTop: '1px solid var(--cream)',
            display: 'flex',
            gap: 'var(--s-2)',
            alignItems: 'flex-end',
            flexShrink: 0,
          }}
        >
          <textarea
            value={input}
            onChange={(e) => setInput(e.target.value)}
            onKeyDown={handleKeyDown}
            placeholder="Ask anything…"
            rows={1}
            disabled={streaming}
            style={{
              flex: 1,
              borderRadius: 'var(--r-md)',
              border: '1.5px solid var(--cream)',
              padding: 'var(--s-3) var(--s-4)',
              fontSize: 'var(--t-body)',
              fontFamily: 'var(--font-sans)',
              color: 'var(--fg)',
              background: 'var(--bg)',
              resize: 'none',
              outline: 'none',
              lineHeight: 1.5,
              minHeight: '44px',
              maxHeight: '120px',
              overflowY: 'auto',
            }}
          />
          <Button
            variant="primary"
            size="md"
            onClick={() => void sendMessage()}
            loading={streaming}
            disabled={!input.trim() || streaming}
            style={{ flexShrink: 0, minWidth: '44px', minHeight: '44px' }}
          >
            {streaming ? '' : '↑'}
          </Button>
        </div>
      </div>

      <style>{`
        @media (min-width: 768px) {
          [role="dialog"][aria-label="R42 Assistant"] {
            right: 0;
            left: auto;
            top: 0;
            bottom: 0;
            max-height: 100dvh;
            width: 400px;
            border-radius: var(--r-lg) 0 0 var(--r-lg);
          }
        }
      `}</style>
    </>
  )
}

function StreamingDots() {
  return (
    <span style={{ display: 'inline-flex', gap: '4px', alignItems: 'center' }}>
      {[0, 1, 2].map((i) => (
        <span
          key={i}
          style={{
            width: '6px',
            height: '6px',
            borderRadius: '50%',
            background: 'var(--fg-muted)',
            animation: `bounce 1s ${i * 0.15}s infinite`,
          }}
        />
      ))}
      <style>{`
        @keyframes bounce {
          0%, 80%, 100% { transform: scale(0.7); opacity: 0.5; }
          40% { transform: scale(1); opacity: 1; }
        }
      `}</style>
    </span>
  )
}
