import { useState, useRef, useEffect, useCallback } from 'react'
import { Input, Button, theme, Typography, App } from 'antd'
import {
  SendOutlined, RobotOutlined, PlusOutlined, ToolOutlined,
  DeleteOutlined, StopOutlined, MessageOutlined, UserOutlined,
  CheckOutlined, CloseOutlined,
} from '@ant-design/icons'
import { streamChat, resolveApproval, type StreamEvent } from '@/services/ai-chat'
import {
  listConversations, createConversation, deleteConversation,
  getMessages, updateConversation, type Conversation,
} from '@/services/conversation-api'
import Markdown from '@/components/Markdown'

const { Text } = Typography

interface Message {
  id: string; role: 'user' | 'assistant'; content: string; timestamp: number
  streaming?: boolean
  toolCalls?: { tool: string; preview?: string; done: boolean; duration?: number; error?: boolean }[]
  approval?: { command: string; description: string; choices: string[]; runId: string; resolved?: boolean }
}

function ChatPage() {
  const { modal, message } = App.useApp()
  const [conversations, setConversations] = useState<Conversation[]>([])
  const [activeId, setActiveId] = useState<string | null>(null)
  const [messages, setMessages] = useState<Message[]>([])
  const [input, setInput] = useState('')
  const [streaming, setStreaming] = useState(false)
  const [waitingApproval, setWaitingApproval] = useState(false)
  const [editingId, setEditingId] = useState<string | null>(null)
  const [editTitle, setEditTitle] = useState('')
  const [deleting, setDeleting] = useState(false)
  const composingRef = useRef(false)
  const abortRef = useRef<AbortController | null>(null)
  const messagesEndRef = useRef<HTMLDivElement>(null)
  const editInputRef = useRef<any>(null)
  const { token } = theme.useToken()

  const loadConversations = useCallback(async () => { try { setConversations(await listConversations()) } catch {} }, [])
  useEffect(() => { loadConversations() }, [loadConversations])
  useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }) }, [messages])
  useEffect(() => { if (!activeId && conversations.length > 0) switchConversation(conversations[0].id) }, [conversations])

  const switchConversation = useCallback(async (id: string) => {
    if (streaming) { abortRef.current?.abort(); setStreaming(false); setWaitingApproval(false) }
    setActiveId(id); setMessages([])
    try { const records = await getMessages(id); setMessages(records.map(m => ({ id: m.id, role: m.role, content: m.content, timestamp: new Date(m.createdAt).getTime() }))) } catch {}
  }, [streaming])

  const handleNew = async () => {
    if (streaming) { abortRef.current?.abort(); setStreaming(false) }
    try { const conv = await createConversation(); setConversations(prev => [conv, ...prev]); setActiveId(conv.id); setMessages([]); setInput('') } catch {}
  }

  const handleDelete = (id: string) => modal.confirm({
    title: '删除对话', okText: '删除', okType: 'danger', cancelText: '取消',
    onOk: async () => {
      setDeleting(true)
      try { await deleteConversation(id); setConversations(prev => prev.filter(c => c.id !== id)); if (activeId === id) { setActiveId(null); setMessages([]) } } catch {}
      setDeleting(false)
    },
  })

  const startEdit = (conv: Conversation) => { setEditingId(conv.id); setEditTitle(conv.title); setTimeout(() => editInputRef.current?.focus(), 50) }
  const saveTitle = async (id: string) => {
    const t = editTitle.trim()
    if (t && t !== conversations.find(c => c.id === id)?.title) { await updateConversation(id, t).catch(() => {}); setConversations(prev => prev.map(c => c.id === id ? { ...c, title: t } : c)) }
    setEditingId(null)
  }

  const handleApprove = async (approvalMsg: Message, choice: string) => {
    setMessages(prev => prev.map(m => m.id === approvalMsg.id ? { ...m, approval: { ...m.approval!, resolved: true } } : m))
    setWaitingApproval(false)
    await resolveApproval(approvalMsg.approval!.runId, choice)
    message.success(choice === 'deny' ? '已拒绝' : '已批准')
  }

  const handleSend = async () => {
    const text = input.trim(); if (!text || streaming) return; setInput('')
    const userMsg: Message = { id: Date.now().toString(), role: 'user', content: text, timestamp: Date.now() }
    const prevMessages = [...messages, userMsg]; setMessages(prevMessages); setStreaming(true)
    const controller = new AbortController(); abortRef.current = controller
    const streamMsgId = (Date.now() + 1).toString()
    const streamMsg: Message = { id: streamMsgId, role: 'assistant', content: '', timestamp: Date.now(), streaming: true }
    setMessages(prev => [...prev, streamMsg])
    let currentContent = ''
    const currentTools: any[] = []
    let completedConvId: string | undefined
    const update = (u: Partial<Message>) => setMessages(prev => prev.map(m => m.id === streamMsgId ? { ...m, ...u } : m))

    try {
      await streamChat(prevMessages.map(m => ({ role: m.role, content: m.content })), activeId, (event: StreamEvent) => {
        switch (event.event) {
          case 'meta':
            completedConvId = event.conversationId
            if (event.conversationId && event.conversationId !== activeId) { setActiveId(event.conversationId); loadConversations() }
            break
          case 'tool.started':
            currentTools.push({ tool: event.tool, preview: event.preview, done: false })
            update({ toolCalls: [...currentTools] })
            break
          case 'tool.completed': {
            const i = currentTools.findIndex((t: any) => t.tool === event.tool && !t.done)
            if (i >= 0) { currentTools[i] = { ...currentTools[i], done: true, duration: event.duration, error: event.error }; update({ toolCalls: [...currentTools] }) }
            break
          }
          case 'approval.request':
            setWaitingApproval(true)
            update({ approval: { command: event.command, description: event.description, choices: event.choices, runId: event.runId } })
            break
          case 'message.delta':
            currentContent += event.delta || ''
            update({ content: currentContent, streaming: true })
            break
          case 'run.completed':
            if (event.output) currentContent = event.output
            update({ content: currentContent, streaming: false })
            break
          case 'done':
            completedConvId = event.conversationId || completedConvId
            update({ streaming: false })
            break
          case 'error':
            update({ content: 'Error: ' + event.error, streaming: false })
            break
        }
      }, controller.signal)
      if (completedConvId) loadConversations()
    } catch (err: any) {
      if (err.name !== 'AbortError') update({ content: 'Error: ' + err.message, streaming: false })
      else update({ streaming: false })
    } finally { setStreaming(false); setWaitingApproval(false); abortRef.current = null }
  }

  const handleStop = () => { abortRef.current?.abort(); setStreaming(false) }

  return (
    <div style={{ display: 'flex', height: 'calc(100vh - 112px)' }}>
      {/* Sidebar */}
      <div style={{ width: 260, flexShrink: 0, display: 'flex', flexDirection: 'column', background: token.colorBgContainer, borderRight: '1px solid ' + token.colorBorderSecondary }}>
        <div style={{ padding: '12px 16px', borderBottom: '1px solid ' + token.colorBorderSecondary }}>
          <Button type="primary" icon={<PlusOutlined />} block onClick={handleNew}>新对话</Button>
        </div>
        <div style={{ flex: 1, overflowY: 'auto', padding: 8 }}>
          {conversations.map(conv => (
            <div key={conv.id} onClick={() => activeId !== conv.id && switchConversation(conv.id)}
              style={{ display: 'flex', alignItems: 'center', padding: '8px 12px', borderRadius: 8, cursor: 'pointer', marginBottom: 2,
                background: activeId === conv.id ? token.colorFillSecondary : 'transparent' }}>
              <MessageOutlined style={{ color: token.colorTextQuaternary, fontSize: 13, marginRight: 8, flexShrink: 0 }} />
              {editingId === conv.id ? (
                <Input ref={editInputRef} size="small" value={editTitle} onChange={e => setEditTitle(e.target.value)}
                  onBlur={() => saveTitle(conv.id)} onPressEnter={() => saveTitle(conv.id)}
                  onClick={e => e.stopPropagation()} style={{ flex: 1, fontSize: 13 }} bordered={false} />
              ) : (
                <Text ellipsis style={{ flex: 1, fontSize: 13 }} onDoubleClick={e => { e.stopPropagation(); startEdit(conv) }}>{conv.title}</Text>
              )}
              <Button type="text" size="small" danger icon={<DeleteOutlined />} disabled={deleting}
                onClick={e => { e.stopPropagation(); handleDelete(conv.id) }} style={{ opacity: 0.4 }} />
            </div>
          ))}
        </div>
      </div>

      {/* Chat area */}
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', background: token.colorBgLayout }}>
        <div style={{ flex: 1, overflowY: 'auto', padding: '32px 0' }}>
          {messages.length === 0 ? (
            <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%', gap: 12 }}>
              <div style={{ width: 64, height: 64, borderRadius: 16, background: token.colorFillSecondary, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <RobotOutlined style={{ fontSize: 28, color: token.colorPrimary }} />
              </div>
              <Text style={{ fontSize: 16, fontWeight: 500 }}>有什么可以帮你的？</Text>
              <Text type="secondary" style={{ fontSize: 13 }}>Hermes Agent · 可执行任务、操作文件</Text>
            </div>
          ) : (
            <div style={{ maxWidth: 768, margin: '0 auto', width: '100%', padding: '0 24px' }}>
              {messages.map(msg => (
                <div key={msg.id} style={{ marginBottom: 32 }}>
                  {/* Header */}
                  <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10 }}>
                    <div style={{ width: 30, height: 30, borderRadius: 8, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 14, fontWeight: 700,
                      background: msg.role === 'user' ? token.colorPrimary : token.colorSuccess, color: '#fff' }}>
                      {msg.role === 'user' ? 'Y' : 'H'}
                    </div>
                    <Text strong style={{ fontSize: 13, color: token.colorText }}>{msg.role === 'user' ? 'You' : 'Hermes'}</Text>
                    {msg.streaming && !msg.content && <Text type="secondary" style={{ fontSize: 12 }}>Thinking...</Text>}
                  </div>

                  {/* Approval card */}
                  {msg.approval && !msg.approval.resolved && (
                    <div style={{ marginLeft: 40, marginBottom: 12, padding: 16, borderRadius: 12, background: token.colorWarningBg, border: '1px solid ' + token.colorWarningBorder }}>
                      <div style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}>
                        <div style={{ width: 32, height: 32, borderRadius: 8, background: token.colorWarning, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                          <ToolOutlined style={{ color: '#fff', fontSize: 14 }} />
                        </div>
                        <div style={{ flex: 1 }}>
                          <Text strong style={{ fontSize: 14 }}>需要确认操作</Text>
                          <div style={{ marginTop: 6, padding: '8px 12px', borderRadius: 8, background: token.colorBgContainer, fontFamily: 'monospace', fontSize: 13 }}>
                            {msg.approval.command}
                          </div>
                          <Text type="secondary" style={{ fontSize: 12, marginTop: 6, display: 'block' }}>{msg.approval.description}</Text>
                          <div style={{ marginTop: 12, display: 'flex', gap: 8 }}>
                            {msg.approval.choices.map(c => (
                              <Button key={c} size="small" type={c === 'deny' ? 'default' : 'primary'}
                                danger={c === 'deny'}
                                onClick={() => handleApprove(msg, c)}>
                                {c === 'deny' ? '拒绝' : c === 'once' ? '允许本次' : c === 'session' ? '本次对话始终允许' : c === 'always' ? '始终允许' : c}
                              </Button>
                            ))}
                          </div>
                        </div>
                      </div>
                    </div>
                  )}

                  {/* Tool calls */}
                  {msg.toolCalls && msg.toolCalls.length > 0 && (
                    <div style={{ marginLeft: 40, marginBottom: 8, display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                      {msg.toolCalls.map((t, i) => (
                        <div key={i} style={{ display: 'inline-flex', alignItems: 'center', gap: 5, padding: '5px 10px', borderRadius: 6, fontSize: 12,
                          background: t.done ? (t.error ? token.colorErrorBg : token.colorSuccessBg) : token.colorFillSecondary,
                          border: '1px solid ' + (t.done ? (t.error ? token.colorErrorBorder : token.colorSuccessBorder) : token.colorBorderSecondary) }}>
                          <ToolOutlined style={{ fontSize: 11, color: t.done ? (t.error ? token.colorError : token.colorSuccess) : token.colorTextSecondary }} />
                          <Text style={{ fontSize: 12 }}>{t.preview || t.tool}</Text>
                          {t.done && <Text style={{ fontSize: 11, color: t.error ? token.colorError : token.colorSuccess }}>{t.error ? 'failed' : t.duration?.toFixed(1) + 's'}</Text>}
                        </div>
                      ))}
                    </div>
                  )}

                  {/* Content */}
                  <div style={{ marginLeft: 40, maxWidth: '100%' }}>
                    <div style={{ fontSize: 14, lineHeight: 1.85, color: token.colorText }}>
                      {msg.role === 'assistant'
                        ? (msg.content ? <Markdown content={msg.content + (msg.streaming ? '▊' : '')} /> : (!msg.toolCalls?.length && !msg.approval ? <Text type="secondary">Thinking...</Text> : null))
                        : <div style={{ padding: '10px 16px', borderRadius: 12, background: token.colorPrimary, color: '#fff', display: 'inline-block', maxWidth: '85%' }}>{msg.content}</div>}
                    </div>
                  </div>
                </div>
              ))}
              <div ref={messagesEndRef} />
            </div>
          )}
        </div>

        {/* Input */}
        <div style={{ padding: '16px 0 24px', background: token.colorBgLayout }}>
          <div style={{ maxWidth: 768, margin: '0 auto', padding: '0 24px' }}>
            <div style={{ display: 'flex', alignItems: 'flex-end', gap: 10, background: token.colorBgContainer, borderRadius: 16, padding: '10px 10px 10px 20px', border: '1px solid ' + token.colorBorderSecondary, boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
              <Input.TextArea value={input} onChange={e => setInput(e.target.value)}
                onCompositionStart={() => { composingRef.current = true }} onCompositionEnd={() => { composingRef.current = false }}
                onKeyDown={e => { if (composingRef.current) return; if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend() } }}
                placeholder={activeId ? 'Message Hermes...' : 'Select or create a conversation'}
                autoSize={{ minRows: 1, maxRows: 6 }} disabled={streaming || !activeId || waitingApproval}
                variant="borderless" style={{ flex: 1, resize: 'none', padding: '4px 0', fontSize: 14 }} />
              {streaming ? (
                <Button danger icon={<StopOutlined />} onClick={handleStop} style={{ borderRadius: 10, height: 36, width: 36 }} />
              ) : (
                <Button type="primary" icon={<SendOutlined />} onClick={handleSend}
                  disabled={!input.trim() || !activeId || waitingApproval} style={{ borderRadius: 10, height: 36, width: 36 }} />
              )}
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

export default function TaskAssistant() { return <App><ChatPage /></App> }
