import { useState, useRef, useEffect, useCallback } from 'react'
import { Terminal as XTerm } from '@xterm/xterm'
import { FitAddon } from '@xterm/addon-fit'
import { WebLinksAddon } from '@xterm/addon-web-links'
import { Plus, X, Monitor, Globe, ChevronDown, Pencil, Trash2 } from 'lucide-react'
import '@xterm/xterm/css/xterm.css'
import { useI18n } from '../i18n'

const MAX_TABS = 7

const THEMES = {
  default: {
    background: '#0A0A0C', foreground: '#EAE0E2', cursor: '#FF0033',
    cursorAccent: '#0A0A0C', selectionBackground: '#FF003344', selectionForeground: '#ffffff',
    black: '#0A0A0C', red: '#FF0033', green: '#00E676', yellow: '#FFD740',
    blue: '#448AFF', magenta: '#FF1A5E', cyan: '#00BCD4', white: '#EAE0E2',
    brightBlack: '#5A4F52', brightRed: '#FF5252', brightGreen: '#69F0AE',
    brightYellow: '#FFFF00', brightBlue: '#82B1FF', brightMagenta: '#FF80AB',
    brightCyan: '#84FFFF', brightWhite: '#FFFFFF',
  },
  monokai: {
    background: '#272822', foreground: '#F8F8F2', cursor: '#F8F8F0',
    cursorAccent: '#272822', selectionBackground: '#F8F8F244', selectionForeground: '#ffffff',
    black: '#272822', red: '#F92672', green: '#A6E22E', yellow: '#E6DB74',
    blue: '#66D9EF', magenta: '#AE81FF', cyan: '#A1EFE4', white: '#F8F8F2',
    brightBlack: '#75715E', brightRed: '#F92672', brightGreen: '#A6E22E',
    brightYellow: '#E6DB74', brightBlue: '#66D9EF', brightMagenta: '#AE81FF',
    brightCyan: '#A1EFE4', brightWhite: '#F8F8F2',
  },
  gruvbox: {
    background: '#282828', foreground: '#EBDBB2', cursor: '#FB4934',
    cursorAccent: '#282828', selectionBackground: '#EBDBB244', selectionForeground: '#ffffff',
    black: '#282828', red: '#CC241D', green: '#98971A', yellow: '#D79921',
    blue: '#458588', magenta: '#B16286', cyan: '#689D6A', white: '#EBDBB2',
    brightBlack: '#928374', brightRed: '#FB4934', brightGreen: '#B8BB26',
    brightYellow: '#FABC2A', brightBlue: '#83A598', brightMagenta: '#D3869B',
    brightCyan: '#8EC07C', brightWhite: '#EBDBB2',
  },
  nord: {
    background: '#2E3440', foreground: '#D8DEE9', cursor: '#D8DEE9',
    cursorAccent: '#2E3440', selectionBackground: '#D8DEE944', selectionForeground: '#ffffff',
    black: '#2E3440', red: '#BF616A', green: '#A3BE8C', yellow: '#EBCB8B',
    blue: '#81A1C1', magenta: '#B48EAD', cyan: '#88C0D0', white: '#D8DEE9',
    brightBlack: '#4C566A', brightRed: '#BF616A', brightGreen: '#A3BE8C',
    brightYellow: '#EBCB8B', brightBlue: '#81A1C1', brightMagenta: '#B48EAD',
    brightCyan: '#8FBCBB', brightWhite: '#ECEFF4',
  },
  'solarized-dark': {
    background: '#002B36', foreground: '#839496', cursor: '#D33682',
    cursorAccent: '#002B36', selectionBackground: '#83949644', selectionForeground: '#ffffff',
    black: '#002B36', red: '#DC322F', green: '#859900', yellow: '#B58900',
    blue: '#268BD2', magenta: '#D33682', cyan: '#2AA198', white: '#FDF6E3',
    brightBlack: '#073642', brightRed: '#CB4B16', brightGreen: '#586E75',
    brightYellow: '#657B83', brightBlue: '#6C71C4', brightMagenta: '#6C71C4',
    brightCyan: '#93A1A1', brightWhite: '#FDF6E3',
  },
  dracula: {
    background: '#282A36', foreground: '#F8F8F2', cursor: '#F8F8F2',
    cursorAccent: '#282A36', selectionBackground: '#F8F8F244', selectionForeground: '#ffffff',
    black: '#282A36', red: '#FF5555', green: '#50FA7B', yellow: '#F1FA8C',
    blue: '#BD93F9', magenta: '#FF79C6', cyan: '#8BE9FD', white: '#F8F8F2',
    brightBlack: '#6272A4', brightRed: '#FF6E6E', brightGreen: '#69FF94',
    brightYellow: '#FFFFA5', brightBlue: '#D6ACFF', brightMagenta: '#FF92DF',
    brightCyan: '#A4FFFF', brightWhite: '#FFFFFF',
  },
}

function getTheme(themeName) {
  return THEMES[themeName] || THEMES.default
}

function createTerminal(container, settings = {}) {
  const theme = getTheme(settings.theme || 'default')
  const term = new XTerm({
    cursorBlink: true,
    fontSize: settings.fontSize || 14,
    fontFamily: settings.fontFamily || "'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'SF Mono', 'Menlo', monospace",
    theme,
    allowTransparency: false,
    scrollback: 5000,
  })

  const fitAddon = new FitAddon()
  const webLinksAddon = new WebLinksAddon()
  term.loadAddon(fitAddon)
  term.loadAddon(webLinksAddon)
  term.open(container)
  fitAddon.fit()

  return { term, fitAddon }
}

function connectWebSocket(term, fitAddon, initPayload) {
  const proto = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
  const ws = new WebSocket(`${proto}//${window.location.host}/api/ws/terminal`)

  ws.addEventListener('open', () => {
    ws.send(JSON.stringify(initPayload))
    const dims = fitAddon.proposeDimensions()
    if (dims) {
      ws.send(JSON.stringify({ type: 'resize', rows: dims.rows, cols: dims.cols }))
    }
  })

  ws.addEventListener('message', (event) => {
    try {
      const msg = JSON.parse(event.data)
      if (msg.type === 'output') {
        term.write(msg.data)
      } else if (msg.type === 'error') {
        term.write(`\r\n\x1b[31mError: ${msg.data}\x1b[0m\r\n`)
      }
    } catch {
      term.write(event.data)
    }
  })

  ws.addEventListener('close', () => {
    term.write('\r\n\x1b[33m— Connection closed —\x1b[0m\r\n')
  })

  ws.addEventListener('error', () => {
    term.write('\r\n\x1b[31m— Connection error —\x1b[0m\r\n')
  })

  term.onData((data) => {
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify({ type: 'input', data }))
    }
  })

  term.onResize(({ rows, cols }) => {
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify({ type: 'resize', rows, cols }))
    }
  })

  return ws
}

export default function Shell({ api }) {
  const { t } = useI18n()
  const tabsRef = useRef({})
  const nextIdRef = useRef(1)

  const [tabs, setTabs] = useState([
    { id: 1, name: 'Local Shell', type: 'local', shell: '', connected: false },
  ])
  const [activeTab, setActiveTab] = useState(1)
  const [sshConnections, setSshConnections] = useState([])
  const [systemTerminals, setSystemTerminals] = useState([])
  const [showMenu, setShowMenu] = useState(false)
  const [showSshModal, setShowSshModal] = useState(false)
  const [editingTab, setEditingTab] = useState(null)
  const [editName, setEditName] = useState('')
  const [terminalSettings, setTerminalSettings] = useState({
    fontSize: 14,
    fontFamily: "'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'SF Mono', 'Menlo', monospace",
    theme: 'default',
  })

  const [sshForm, setSshForm] = useState({
    name: '', host: '', port: 22, user: '', key_path: '',
  })

  const [aiMessages, setAiMessages] = useState([
    { role: 'ai', content: t('shell.aiWelcome') }
  ])
  const [aiInput, setAiInput] = useState('')
  const [aiLoading, setAiLoading] = useState(false)
  const aiMessagesRef = useRef(null)

  useEffect(() => {
    aiMessagesRef.current?.scrollTo(0, aiMessagesRef.current.scrollHeight)
  }, [aiMessages])

  useEffect(() => {
    api.getTerminalSessions().then(d => {
      setSshConnections(d.ssh || [])
      setSystemTerminals(d.system || [])
    }).catch(() => {})
    api.getConfig().then(d => {
      if (d.terminal) {
        setTerminalSettings({
          fontSize: d.terminal.font_size || 14,
          fontFamily: d.terminal.font_family || "'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'SF Mono', 'Menlo', monospace",
          theme: d.terminal.theme || 'default',
        })
      }
    }).catch(() => {})
  }, [])

  const initTerminal = useCallback((tabId, tab) => {
    if (tabsRef.current[tabId]) return

    const container = document.getElementById(`terminal-${tabId}`)
    if (!container) return

    const { term, fitAddon } = createTerminal(container, {
      fontSize: terminalSettings.fontSize,
      fontFamily: terminalSettings.fontFamily,
      theme: terminalSettings.theme,
    })

    let initPayload
    if (tab.type === 'ssh') {
      initPayload = {
        type: 'ssh',
        data: JSON.stringify({
          host: tab.host,
          port: tab.port || 22,
          user: tab.user || 'root',
          key_path: tab.key_path || '',
        }),
      }
    } else {
      initPayload = {
        type: 'shell',
        data: tab.shell || '',
      }
    }

    const ws = connectWebSocket(term, fitAddon, initPayload)

    ws.onopen = () => {
      setTabs(prev => prev.map(t => t.id === tabId ? { ...t, connected: true } : t))
    }

    ws.onclose = () => {
      setTabs(prev => prev.map(t => t.id === tabId ? { ...t, connected: false } : t))
    }

    ws.onerror = () => {
      setTabs(prev => prev.map(t => t.id === tabId ? { ...t, connected: false } : t))
    }

    const onResize = () => {
      const el = document.getElementById(`terminal-${tabId}`)
      if (el && el.offsetParent !== null) {
        fitAddon.fit()
      }
    }

    const resizeObserver = new ResizeObserver(onResize)
    resizeObserver.observe(container)
    window.addEventListener('resize', onResize)

    tabsRef.current[tabId] = { term, fitAddon, ws, resizeObserver, onResize }
  }, [])

  useEffect(() => {
    const tab = tabs.find(t => t.id === activeTab)
    if (!tab) return

    const container = document.getElementById(`terminal-${tab.id}`)
    if (!container) return

    if (!tabsRef.current[tab.id]) {
      const timer = setTimeout(() => {
        initTerminal(tab.id, tab)
        requestAnimationFrame(() => {
          const entry = tabsRef.current[tab.id]
          if (entry) entry.fitAddon.fit()
        })
      }, 100)
      return () => clearTimeout(timer)
    } else {
      requestAnimationFrame(() => {
        const entry = tabsRef.current[tab.id]
        if (entry) entry.fitAddon.fit()
      })
    }
  }, [activeTab, tabs, initTerminal])

  useEffect(() => {
    const onKey = (e) => {
      if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return
      if (!e.altKey) return

      const num = parseInt(e.key)
      if (num >= 1 && num <= tabs.length) {
        e.preventDefault()
        setActiveTab(tabs[num - 1].id)
      }
    }
    window.addEventListener('keydown', onKey)
    return () => window.removeEventListener('keydown', onKey)
  }, [tabs])

  const addLocalTab = (shell, name) => {
    if (tabs.length >= MAX_TABS) return
    const id = nextIdRef.current++
    const newTab = { id, name: name || `${t('shell.localShell')} ${tabs.length + 1}`, type: 'local', shell: shell || '', connected: false }
    setTabs(prev => [...prev, newTab])
    setActiveTab(id)
    setShowMenu(false)
  }

  const addSSHTab = (conn) => {
    if (tabs.length >= MAX_TABS) return
    const id = nextIdRef.current++
    const newTab = {
      id,
      name: conn.name || `${conn.user}@${conn.host}`,
      type: 'ssh',
      host: conn.host,
      port: conn.port || 22,
      user: conn.user || 'root',
      key_path: conn.key_path || '',
      connected: false,
    }
    setTabs(prev => [...prev, newTab])
    setActiveTab(id)
    setShowMenu(false)
  }

  const closeTab = (tabId, e) => {
    if (e) e.stopPropagation()
    if (tabs.length <= 1) return

    if (tabsRef.current[tabId]) {
      const { ws, resizeObserver, onResize, term } = tabsRef.current[tabId]
      window.removeEventListener('resize', onResize)
      resizeObserver.disconnect()
      ws.close()
      term.dispose()
      delete tabsRef.current[tabId]
    }

    setTabs(prev => {
      const next = prev.filter(t => t.id !== tabId)
      if (activeTab === tabId && next.length > 0) {
        setActiveTab(next[next.length - 1].id)
      }
      return next
    })
  }

  const startRename = (tabId, e) => {
    if (e) e.stopPropagation()
    const tab = tabs.find(t => t.id === tabId)
    setEditingTab(tabId)
    setEditName(tab.name)
  }

  const finishRename = () => {
    if (editName.trim() && editingTab) {
      setTabs(prev => prev.map(t => t.id === editingTab ? { ...t, name: editName.trim() } : t))
    }
    setEditingTab(null)
    setEditName('')
  }

  const saveSSHConnection = async () => {
    if (!sshForm.name.trim() || !sshForm.host.trim()) return
    try {
      await api.addSSHConnection(sshForm)
      setSshConnections(prev => [...prev, { ...sshForm }])
      setSshForm({ name: '', host: '', port: 22, user: '', key_path: '' })
      setShowSshModal(false)
    } catch (err) {
      console.error(err)
    }
  }

  const deleteSSHConnection = async (name) => {
    try {
      await api.deleteSSHConnection(name)
      setSshConnections(prev => prev.filter(c => c.name !== name))
    } catch (err) {
      console.error(err)
    }
  }

  const handleAiSend = async () => {
    if (!aiInput.trim() || aiLoading) return
    const text = aiInput.trim()
    setAiMessages(prev => [...prev, { role: 'user', content: text }])
    setAiInput('')
    setAiLoading(true)

    const currentTab = tabs.find(t => t.id === activeTab)
    const context = {
      cwd: currentTab?.cwd || '',
      platform: navigator.platform || '',
    }

    try {
      let accumulated = ''
      await api.sendShellChat(text, context, true, (partial, event) => {
        if (event && event.tool_call) {
          setAiMessages(prev => [...prev, {
            role: 'tool',
            content: `${t('shell.toolLaunched')}: ${event.tool_call.name || 'tool'}`,
            args: event.tool_call.args ? JSON.stringify(event.tool_call.args).slice(0, 100) : '',
          }])
          return
        }
        if (event && event.tool_result) {
          const resultText = event.tool_result.result?.content || event.tool_result.error || 'completed'
          setAiMessages(prev => [...prev, {
            role: 'tool_result',
            content: resultText,
            isError: event.tool_result.result?.is_error,
          }])
          return
        }
        if (event && event.done) return
        accumulated = partial
        setAiMessages(prev => {
          const filtered = prev.filter(m => !m._streaming)
          return [...filtered, { role: 'ai', content: partial, _streaming: true }]
        })
      })

      setAiMessages(prev => prev.filter(m => !m._streaming))
      if (accumulated) {
        setAiMessages(prev => [...prev.filter(m => !m._streaming), { role: 'ai', content: accumulated }])
      }
    } catch (err) {
      setAiMessages(prev => [...prev.filter(m => !m._streaming), { role: 'ai', content: `${t('shell.error')}: ${err.message}` }])
    }
    setAiLoading(false)
  }

  return (
    <div className="shell-layout">
      <div className="shell-terminal-col">
        <div className="shell-tabs-bar">
          <div className="shell-tabs">
            {tabs.map((tab, i) => (
              <div
                key={tab.id}
                className={`shell-tab ${activeTab === tab.id ? 'active' : ''}`}
                onClick={() => setActiveTab(tab.id)}
                onDoubleClick={(e) => startRename(tab.id, e)}
              >
                <span className={`connection-dot ${tab.connected ? 'on' : 'off'}`} />
                {tab.type === 'ssh' && <Globe size={12} />}
                {tab.type === 'local' && <Monitor size={12} />}
                {editingTab === tab.id ? (
                  <input
                    className="shell-tab-rename"
                    value={editName}
                    onChange={e => setEditName(e.target.value)}
                    onBlur={finishRename}
                    onKeyDown={e => { if (e.key === 'Enter') finishRename(); if (e.key === 'Escape') setEditingTab(null) }}
                    autoFocus
                    onClick={e => e.stopPropagation()}
                  />
                ) : (
                  <span className="shell-tab-name">{tab.name}</span>
                )}
                <span className="shell-tab-index">{i + 1}</span>
                {tabs.length > 1 && (
                  <button
                    className="shell-tab-close"
                    onClick={(e) => closeTab(tab.id, e)}
                    title={t('shell.closeTab')}
                  >
                    <X size={12} />
                  </button>
                )}
              </div>
            ))}
          </div>

          <div className="shell-tab-actions">
            {tabs.length < MAX_TABS && (
              <div className="shell-new-tab-wrapper">
                <button className="shell-new-tab-btn" onClick={() => setShowMenu(!showMenu)} title={t('shell.newTab')}>
                  <Plus size={16} />
                  <ChevronDown size={12} />
                </button>
                {showMenu && (
                  <>
                    <div className="shell-menu-overlay" onClick={() => setShowMenu(false)} />
                    <div className="shell-new-tab-menu">
                      <div className="shell-menu-label">{t('shell.systemTerminals')}</div>
                      {systemTerminals.map(st => (
                        <button
                          key={st.name}
                          className="shell-menu-item"
                          onClick={() => addLocalTab(st.shell, st.name)}
                        >
                          <Monitor size={14} />
                          <span>{st.name}</span>
                          <span className="shell-menu-item-sub">{st.shell}</span>
                        </button>
                      ))}
                      <div className="shell-menu-divider" />
                      <div className="shell-menu-label">{t('shell.savedConnections')}</div>
                      {sshConnections.length === 0 && (
                        <div className="shell-menu-empty">{t('shell.noConnections')}</div>
                      )}
                      {sshConnections.map(conn => (
                        <div key={conn.name} className="shell-menu-item-row">
                          <button
                            className="shell-menu-item"
                            onClick={() => addSSHTab(conn)}
                          >
                            <Globe size={14} />
                            <span>{conn.name}</span>
                            <span className="shell-menu-item-sub">{conn.user}@{conn.host}:{conn.port}</span>
                          </button>
                          <button
                            className="shell-menu-item-icon"
                            onClick={(e) => { e.stopPropagation(); deleteSSHConnection(conn.name) }}
                            title={t('shell.deleteConnection')}
                          >
                            <Trash2 size={12} />
                          </button>
                        </div>
                      ))}
                      <div className="shell-menu-divider" />
                      <button className="shell-menu-item accent" onClick={() => { setShowSshModal(true); setShowMenu(false) }}>
                        <Plus size={14} />
                        <span>{t('shell.addConnection')}</span>
                      </button>
                    </div>
                  </>
                )}
              </div>
            )}
          </div>
        </div>

        <div className="shell-xterm-wrapper">
          {tabs.map(tab => (
            <div
              key={tab.id}
              id={`terminal-${tab.id}`}
              className="shell-xterm-instance"
              style={{ display: activeTab === tab.id ? 'block' : 'none' }}
            />
          ))}
        </div>
      </div>

      <div className="shell-ai-col">
        <div className="ai-panel-header">{t('shell.aiAssistant')}</div>
        <div className="ai-panel-messages" ref={aiMessagesRef}>
          {aiMessages.map((msg, i) => (
            <div key={i} className={`ai-message ${msg.role}`}>
              {msg.content}
              {msg.args && <div className="tool-args">{msg.args}</div>}
            </div>
          ))}
          {aiLoading && <div style={{ textAlign: 'center', padding: 8 }}><span className="spinner" /></div>}
        </div>
        <div className="ai-panel-input">
          <input
            value={aiInput}
            onChange={e => setAiInput(e.target.value)}
            onKeyDown={e => e.key === 'Enter' && handleAiSend()}
            placeholder={t('shell.askAi')}
          />
          <button className="sm" onClick={handleAiSend} disabled={!aiInput.trim()}>{t('shell.send')}</button>
        </div>
      </div>

      {showSshModal && (
        <div className="shell-modal-overlay" onClick={() => setShowSshModal(false)}>
          <div className="shell-modal" onClick={e => e.stopPropagation()}>
            <div className="shell-modal-header">{t('shell.addConnection')}</div>
            <div className="shell-modal-body">
              <label className="shell-modal-label">{t('shell.connectionName')}</label>
              <input
                value={sshForm.name}
                onChange={e => setSshForm(f => ({ ...f, name: e.target.value }))}
                placeholder="prod-server"
              />
              <label className="shell-modal-label">{t('shell.host')}</label>
              <input
                value={sshForm.host}
                onChange={e => setSshForm(f => ({ ...f, host: e.target.value }))}
                placeholder="192.168.1.100"
              />
              <div className="shell-modal-row">
                <div className="shell-modal-field">
                  <label className="shell-modal-label">{t('shell.port')}</label>
                  <input
                    type="number"
                    value={sshForm.port}
                    onChange={e => setSshForm(f => ({ ...f, port: parseInt(e.target.value) || 22 }))}
                  />
                </div>
                <div className="shell-modal-field">
                  <label className="shell-modal-label">{t('shell.user')}</label>
                  <input
                    value={sshForm.user}
                    onChange={e => setSshForm(f => ({ ...f, user: e.target.value }))}
                    placeholder="root"
                  />
                </div>
              </div>
              <label className="shell-modal-label">{t('shell.keyPath')} ({t('shell.local')})</label>
              <input
                value={sshForm.key_path}
                onChange={e => setSshForm(f => ({ ...f, key_path: e.target.value }))}
                placeholder="~/.ssh/id_rsa"
              />
            </div>
            <div className="shell-modal-footer">
              <button className="ghost" onClick={() => setShowSshModal(false)}>{t('shell.cancel')}</button>
              <button className="primary" onClick={saveSSHConnection}>{t('shell.save')}</button>
            </div>
          </div>
        </div>
      )}
    </div>
  )
}
