'use client'

import { motion, AnimatePresence } from 'framer-motion'
import { useEffect, useRef, useState } from 'react'
import { useTerminal } from '@/lib/TerminalContext'
import ReactMarkdown from 'react-markdown'

function Spinner() {
  const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
  const [frame, setFrame] = useState(0)
  
  useEffect(() => {
    const interval = setInterval(() => {
      setFrame(f => (f + 1) % frames.length)
    }, 80)
    return () => clearInterval(interval)
  }, [frames.length])
  
  return <span className="inline-block w-3">{frames[frame]}</span>
}

function useTheme() {
  const [isDark, setIsDark] = useState(true)

  useEffect(() => {
    const check = () => setIsDark(document.documentElement.classList.contains('dark'))
    check()

    const observer = new MutationObserver(check)
    observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] })
    return () => observer.disconnect()
  }, [])

  return isDark
}

const commands: Record<string, string> = {
  help: `Commands: help | ! kubectl ...

Quick questions:
  • etcd consensus issue at homelab?
  • Terraform drift detection?
  • Graph-RAG vs semantic search?
  • 2hr→20min deploy root cause?
  • How'd you reduce cloud costs 40%?
  • vLLM bottleneck & fix?
  • Temporal workflow orchestration?
  • ArgoCD vs Terraform split?

Kubectl examples:
  ! kubectl get pods -A
  ! kubectl get nodes
  ! kubectl top pods
  ! kubectl logs -f deployment/poimen-mem -n portfolio

Or just ask anything!`,
  about: `Rock Liang - Senior Software Engineer
6+ years | Infrastructure × Backend × LLM Systems
AWS → RBC → Building production homelab

Ask me anything!`,
}

interface HistoryEntry {
  cmd: string
  output: string
  thinking?: string
  isStreaming?: boolean
}

export function InteractiveTerminal() {
  const [input, setInput] = useState('')
  const [history, setHistory] = useState<HistoryEntry[]>([])
  const [isLoading, setIsLoading] = useState(false)
  const { isOpen, setIsOpen } = useTerminal()
  const [isMac, setIsMac] = useState(true)
  const [width, setWidth] = useState(448) // 28rem = 448px
  const [height, setHeight] = useState(512) // 32rem = 512px
  const [isResizing, setIsResizing] = useState(false)
  const terminalRef = useRef<HTMLDivElement>(null)
  const containerRef = useRef<HTMLDivElement>(null)
  const inputRef = useRef<HTMLInputElement>(null)
  const resizeHandleRef = useRef<HTMLDivElement>(null)
  const isDark = useTheme()

  // Close on click outside
  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (isOpen && containerRef.current && !containerRef.current.contains(e.target as Node)) {
        setIsOpen(false)
      }
    }
    document.addEventListener('mousedown', handleClickOutside)
    return () => document.removeEventListener('mousedown', handleClickOutside)
  }, [isOpen, setIsOpen])

  useEffect(() => {
    const isMacOS = /Mac|iPhone|iPad|iPod/.test(navigator.platform)
    setIsMac(isMacOS)

    const handleKeyDown = (e: KeyboardEvent) => {
      if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
        e.preventDefault()
        setIsOpen(!isOpen)
      }
    }

    window.addEventListener('keydown', handleKeyDown)
    return () => window.removeEventListener('keydown', handleKeyDown)
  }, [isOpen, setIsOpen])

  // Auto-scroll on history change
  useEffect(() => {
    terminalRef.current?.scrollTo(0, terminalRef.current.scrollHeight)
  }, [history])

  // Focus input when opened
  useEffect(() => {
    if (isOpen) inputRef.current?.focus()
  }, [isOpen])

  // Handle terminal resize (drag top-left, anchored bottom-right)
  useEffect(() => {
    const handleMouseMove = (e: MouseEvent) => {
      if (!isResizing) return
      e.preventDefault()
      const container = containerRef.current
      if (!container) return
      
      const rect = container.getBoundingClientRect()
      const newWidth = Math.max(320, rect.right - e.clientX)
      const newHeight = Math.max(300, rect.bottom - e.clientY)
      
      setWidth(newWidth)
      setHeight(newHeight)
    }

    const handleMouseUp = () => {
      setIsResizing(false)
      document.body.style.cursor = 'auto'
      document.body.style.userSelect = 'auto'
    }

    if (isResizing) {
      document.body.style.userSelect = 'none'
      document.body.style.cursor = 'nw-resize'
      document.addEventListener('mousemove', handleMouseMove, { passive: false })
      document.addEventListener('mouseup', handleMouseUp)
      return () => {
        document.removeEventListener('mousemove', handleMouseMove)
        document.removeEventListener('mouseup', handleMouseUp)
      }
    }
  }, [isResizing])

  const handleCommand = async (cmd: string) => {
    const trimmed = cmd.trim()
    if (!trimmed) return

    const lowerCmd = trimmed.toLowerCase()
    
    if (lowerCmd === 'clear' || lowerCmd === '/clear') {
      setHistory([])
      setInput('')
      return
    }

    // Handle ! kubectl commands
    if (trimmed.startsWith('!')) {
      const kubectlCmd = trimmed.slice(1).trim()
      if (!kubectlCmd.startsWith('kubectl ')) {
        setHistory(prev => [...prev, { cmd: trimmed, output: 'Error: only kubectl commands supported (e.g. ! kubectl get pods)' }])
        setInput('')
        return
      }

      setIsLoading(true)
      setInput('')
      setHistory(prev => [...prev, { cmd: trimmed, output: '', isStreaming: true }])
      const entryIndex = history.length

      try {
        const response = await fetch('/api/kubectl', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ command: kubectlCmd }),
        })

        const data = await response.json()
        setHistory(prev => {
          const updated = [...prev]
          const entry = updated[entryIndex]
          if (entry) {
            entry.output = data.error || data.output || 'No output'
            entry.isStreaming = false
          }
          return updated
        })
      } catch (err) {
        setHistory(prev => {
          const updated = [...prev]
          const entry = updated[entryIndex]
          if (entry) {
            entry.output = `Error: ${err instanceof Error ? err.message : 'Request failed'}`
            entry.isStreaming = false
          }
          return updated
        })
      } finally {
        setIsLoading(false)
      }
      return
    }

    // Check for built-in commands
    if (commands[lowerCmd]) {
      setHistory(prev => [...prev, { cmd: trimmed, output: commands[lowerCmd] }])
      setInput('')
      return
    }

    // Otherwise, call the LLM API
    setIsLoading(true)
    setInput('')
    
    const entryIndex = history.length
    setHistory(prev => [...prev, { cmd: trimmed, output: '', thinking: '', isStreaming: true }])

    try {
      const response = await fetch('/api/chat', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ message: trimmed }),
      })

      if (!response.ok) throw new Error('API error')

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

      const decoder = new TextDecoder()

      // eslint-disable-next-line no-constant-condition
      while (true) {
        const { done, value } = await reader.read()
        if (done) break

        const chunk = decoder.decode(value, { stream: true })
        const lines = chunk.split('\n')

        for (const line of lines) {
          if (!line.startsWith('data: ')) continue
          const data = line.slice(6)
          
          try {
            const json = JSON.parse(data)
            
            setHistory(prev => {
              const updated = [...prev]
              const entry = updated[entryIndex]
              if (!entry) return prev

              if (json.type === 'reasoning') {
                entry.thinking = json.text
              } else if (json.type === 'content') {
                entry.output = json.text
              } else if (json.type === 'done') {
                entry.isStreaming = false
              }
              
              return updated
            })
          } catch {
            // Skip invalid JSON
          }
        }
      }
    } catch {
      setHistory(prev => {
        const updated = [...prev]
        const entry = updated[entryIndex]
        if (entry) {
          entry.output = 'Error: Failed to get response. Try again.'
          entry.isStreaming = false
        }
        return updated
      })
    } finally {
      setIsLoading(false)
    }
  }

  return (
    <div className="fixed bottom-6 right-6 z-40">
      <AnimatePresence mode="wait">
      {!isOpen ? (
        <motion.button
          key="trigger"
          onClick={() => setIsOpen(true)}
          className="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg font-mono text-sm shadow-lg"
          initial={{ opacity: 0, scale: 0.9 }}
          animate={{ opacity: 1, scale: 1 }}
          exit={{ opacity: 0, scale: 0.9 }}
          transition={{ duration: 0.2 }}
        >
          Ask Poimen ({isMac ? 'Cmd' : 'Ctrl'}+K)
        </motion.button>
      ) : (
        <motion.div
          key="terminal"
          ref={containerRef}
          initial={{ opacity: 0, y: 20, scale: 0.95 }}
          animate={{ opacity: 1, y: 0, scale: 1 }}
          exit={{ opacity: 0, y: 20, scale: 0.95 }}
          transition={{ duration: 0.25, ease: 'easeInOut' }}
          style={{ width: `${width}px`, height: `${height}px` }}
          className={`rounded-lg shadow-2xl flex flex-col border relative user-select-none ${
            isDark 
              ? 'bg-gray-950 border-gray-700' 
              : 'bg-white border-gray-300'
          }`}
          tabIndex={-1}
          onMouseDown={(e) => {
            // Ensure terminal stays focused during interaction
            if (e.target === containerRef.current) {
              inputRef.current?.focus()
            }
          }}
        >
          <div className={`border-b px-4 py-3 flex justify-between items-center ${
            isDark 
              ? 'bg-gray-900 border-gray-700' 
              : 'bg-gray-100 border-gray-300'
          }`}>
            <span className={`font-mono text-xs ${isDark ? 'text-gray-300' : 'text-gray-700'}`}>
              Poimen (AI Assistant)
            </span>
            <button
              onClick={() => setIsOpen(false)}
              className={isDark ? 'text-gray-400 hover:text-white' : 'text-gray-500 hover:text-gray-900'}
            >
              ✕
            </button>
          </div>

          <div
            ref={terminalRef}
            className={`flex-1 overflow-y-auto px-4 py-3 font-mono text-sm space-y-4 ${
              isDark ? 'text-gray-200' : 'text-gray-800'
            }`}
          >
            {history.length === 0 && (
              <div className={isDark ? 'text-gray-500' : 'text-gray-400'}>
                Ask me about Rock&apos;s experience, projects, or skills!
                <br />
                <span className="text-xs">Type &apos;help&apos; for commands</span>
              </div>
            )}
            {history.map((entry, i) => (
              <div key={i} className="space-y-2">
                <div className={isDark ? 'text-green-400' : 'text-green-600'}>
                  <span className={isDark ? 'text-blue-400' : 'text-blue-600'}>→</span> {entry.cmd}
                </div>
                
                {entry.isStreaming && !entry.output && (
                  <div className={`space-y-2 text-xs ${isDark ? 'text-gray-400' : 'text-gray-500'}`}>
                    <div className="flex items-start gap-2">
                      <Spinner />
                      <span className="italic truncate max-w-[300px]">
                        {entry.thinking ? entry.thinking.slice(-80) : 'Working...'}
                      </span>
                    </div>
                    <div className={`text-[11px] ${isDark ? 'text-gray-500' : 'text-gray-400'}`}>
                      (Reasoning on V100 32GB, slight delay expected)
                    </div>
                  </div>
                )}
                
                {entry.output && (
                  <div className={`prose prose-sm max-w-none ${isDark ? 'prose-invert' : ''}`}>
                    <ReactMarkdown>{entry.output}</ReactMarkdown>
                    {entry.isStreaming && (
                      <span className="animate-pulse">▊</span>
                    )}
                  </div>
                )}
              </div>
            ))}
          </div>

          <div className={`border-t px-4 py-3 ${isDark ? 'border-gray-700' : 'border-gray-300'}`}>
            <div className="flex items-center gap-2">
              <span className={isDark ? 'text-blue-400' : 'text-blue-600'}>→</span>
              <input
                ref={inputRef}
                type="text"
                value={input}
                onChange={(e) => setInput(e.target.value)}
                onKeyDown={(e) => {
                  if (e.key === 'Enter' && !isLoading) handleCommand(input)
                }}
                placeholder={isLoading ? 'Thinking...' : 'Ask anything...'}
                disabled={isLoading}
                className={`flex-1 bg-transparent text-sm outline-none ${
                  isDark ? 'text-gray-200 placeholder-gray-600' : 'text-gray-800 placeholder-gray-400'
                } ${isLoading ? 'opacity-50' : ''}`}
                autoFocus
              />
            </div>
          </div>

          {/* Resize handle — top-left corner */}
          <div
            ref={resizeHandleRef}
            onMouseDown={(e) => {
              e.preventDefault()
              e.stopPropagation()
              setIsResizing(true)
            }}
            className={`absolute top-0 left-0 w-4 h-4 cursor-nw-resize ${
              isDark ? 'hover:bg-gray-600' : 'hover:bg-gray-400'
            } transition-colors z-10 select-none`}
            style={{
              borderTopLeftRadius: 'inherit',
              opacity: isResizing ? 1 : 0.5,
            }}
          >
            <svg width="10" height="10" viewBox="0 0 10 10" className="m-0.5 opacity-40 pointer-events-none">
              <line x1="0" y1="10" x2="10" y2="0" stroke="currentColor" strokeWidth="1.5" />
              <line x1="0" y1="6" x2="6" y2="0" stroke="currentColor" strokeWidth="1.5" />
            </svg>
          </div>
        </motion.div>
      )}
      </AnimatePresence>
    </div>
  )
}
