import { useState, useRef, useEffect, useCallback } from 'react'
import { toast } from 'sonner'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { Bot, Send, FileSearch, Scale, Sparkles, Loader2, Mic, Plus, MessageSquare, Trash2, Save, BookOpen, History, Database, User, AlertTriangle, FileText, Shield, Download, TrendingUp, UserCheck, Phone } from 'lucide-react'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import rehypeRaw from 'rehype-raw'
import { Document, Packer, Paragraph, HeadingLevel, TextRun, Table, TableRow, TableCell, WidthType, BorderStyle, AlignmentType } from 'docx'
import { saveAs } from 'file-saver'
import api from '../lib/api'
import { useAuthStore } from '../store/authStore'
import Card from '../components/ui/Card'
import Button from '../components/ui/Button'
import { Input, Label, Select } from '../components/ui/Input'
import Modal from '../components/ui/Modal'

type Tab = 'chat' | 'predict' | 'review' | 'case' | 'knowledge' | 'hr-report'

/** 解析 markdown 内联格式（**bold** 和 `code`）为 TextRun 数组 */
function parseInlineBold(text: string): TextRun[] {
  const runs: TextRun[] = []
  const regex = /(\*\*(.+?)\*\*|`(.+?)`)/g
  let lastIndex = 0
  let match
  while ((match = regex.exec(text)) !== null) {
    if (match.index > lastIndex) {
      runs.push(new TextRun({ text: text.slice(lastIndex, match.index) }))
    }
    if (match[2]) {
      runs.push(new TextRun({ text: match[2], bold: true }))
    } else if (match[3]) {
      runs.push(new TextRun({ text: match[3], font: 'Courier New', size: 20 }))
    }
    lastIndex = regex.lastIndex
  }
  if (lastIndex < text.length) {
    runs.push(new TextRun({ text: text.slice(lastIndex) }))
  }
  return runs.length ? runs : [new TextRun({ text })]
}

/** 导出 Markdown 文本为 Word 文档 */
async function exportMarkdownToWord(markdown: string, fileName: string) {
  const lines = markdown.split('\n')
  const children: (Paragraph | Table)[] = []
  let i = 0

  while (i < lines.length) {
    const line = lines[i]
    if (!line.trim()) { i++; continue }
    if (line.includes('|') && i + 1 < lines.length && lines[i + 1].includes('---')) {
      const headerCells = line.split('|').map(c => c.trim()).filter(Boolean)
      i += 2
      const rows: TableRow[] = []
      rows.push(new TableRow({
        children: headerCells.map(text => new TableCell({
          children: [new Paragraph({ children: [new TextRun({ text, bold: true })] })],
          shading: { fill: 'F3F4F6' },
        })),
      }))
      while (i < lines.length && lines[i].includes('|') && lines[i].trim()) {
        const cells = lines[i].split('|').map(c => c.trim()).filter(Boolean)
        rows.push(new TableRow({
          children: cells.map(text => new TableCell({
            children: [new Paragraph({ children: [new TextRun({ text })] })],
          })),
        }))
        i++
      }
      children.push(new Table({ rows, width: { size: 100, type: WidthType.PERCENTAGE } }))
      continue
    }
    if (line.startsWith('### ')) {
      children.push(new Paragraph({ heading: HeadingLevel.HEADING_3, children: [new TextRun({ text: line.slice(4), bold: true })] }))
    } else if (line.startsWith('## ')) {
      children.push(new Paragraph({ heading: HeadingLevel.HEADING_2, children: [new TextRun({ text: line.slice(3), bold: true })] }))
    } else if (line.startsWith('# ')) {
      children.push(new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun({ text: line.slice(2), bold: true })] }))
    } else if (line.startsWith('> ')) {
      children.push(new Paragraph({ children: [new TextRun({ text: line.slice(2), italics: true })], indent: { left: 720 } }))
    } else if (line.startsWith('- ') || line.startsWith('* ')) {
      children.push(new Paragraph({ children: parseInlineBold(line.slice(2)), bullet: { level: 0 } }))
    } else if (/^\d+\.\s/.test(line)) {
      children.push(new Paragraph({ children: parseInlineBold(line.replace(/^\d+\.\s/, '')), numbering: { reference: 'default-numbering', level: 0 } }))
    } else if (line === '---' || line === '***') {
      children.push(new Paragraph({ children: [], border: { bottom: { style: BorderStyle.SINGLE, size: 6, color: 'E5E7EB' } } }))
    } else {
      children.push(new Paragraph({ children: parseInlineBold(line) }))
    }
    i++
  }

  const doc = new Document({
    numbering: { config: [{ reference: 'default-numbering', levels: [{ level: 0, format: 'decimal', text: '%1.', alignment: AlignmentType.START }] }] },
    sections: [{ children }],
  })
  const blob = await Packer.toBlob(doc)
  saveAs(blob, fileName)
}

// 通用 AI 历史记录 hook
function useAIHistory(type: 'predict' | 'review' | 'case') {
  const queryClient = useQueryClient()
  const queryKey = [`ai-history-${type}`]

  const { data: history } = useQuery<any[]>({
    queryKey,
    queryFn: async () => {
      const res = await api.get(`/ai/conversations?type=${type}`) as any
      return res.data
    },
  })

  const saveMutation = useMutation({
    mutationFn: async ({ title, input, result }: { title: string; input: string; result: string }) => {
      const res = await api.post('/ai/conversations', {
        title: `${type}:${title}`,
        messages: [{ role: 'user', content: input }, { role: 'assistant', content: result }],
      }) as any
      return res.data
    },
    onSuccess: () => queryClient.invalidateQueries({ queryKey }),
  })

  const deleteMutation = useMutation({
    mutationFn: (id: string) => api.delete(`/ai/conversations/${id}`),
    onSuccess: () => queryClient.invalidateQueries({ queryKey }),
  })

  const loadHistory = useCallback(async (id: string) => {
    const res = await api.get(`/ai/conversations/${id}`) as any
    return res.data
  }, [])

  return { history, saveMutation, deleteMutation, loadHistory }
}

// 通用历史记录栏组件
function HistoryBar({ history, onLoad, onDelete }: {
  history: any[]
  onLoad: (id: string) => void
  onDelete: (id: string) => void
}) {
  return (
    <div className="border-b pb-2 max-h-40 overflow-y-auto">
      {history.length > 0 ? history.map((c: any) => (
        <div key={c.id} className="flex items-center justify-between px-2 py-1.5 hover:bg-gray-50 rounded cursor-pointer text-xs">
          <span className="flex-1 truncate" onClick={() => onLoad(c.id)}>
            {c.title.replace(/^(predict:|review:|case:)/, '')}
          </span>
          <span className="text-gray-400 ml-2">{new Date(c.updatedAt).toLocaleDateString('zh-CN', { month: '2-digit', day: '2-digit' })}</span>
          <button onClick={(e) => { e.stopPropagation(); onDelete(c.id) }} className="ml-2 text-gray-400 hover:text-danger"><Trash2 className="w-3 h-3" /></button>
        </div>
      )) : <div className="text-xs text-gray-400 py-2 text-center">暂无历史记录</div>}
    </div>
  )
}

interface Message {
  role: 'user' | 'assistant'
  content: string
}

const QUICK_QUESTIONS = [
  '员工入职没签合同怎么办？',
  '加班费怎么算？',
  '辞退员工需要赔多少？',
  '试用期最长可以约定几个月？',
]

export default function AIAssistant() {
  const [tab, setTab] = useState<Tab>('chat')

  const tabs: { key: Tab; label: string; icon: typeof Bot }[] = [
    { key: 'chat', label: '智能问答', icon: Bot },
    { key: 'predict', label: '风险预测', icon: Sparkles },
    { key: 'review', label: '合同审查', icon: FileSearch },
    { key: 'case', label: '案例匹配', icon: Scale },
    { key: 'hr-report', label: '人力报告', icon: TrendingUp },
    { key: 'knowledge', label: '知识库', icon: BookOpen },
  ]

  return (
    <div className="space-y-4">
      <div className="flex items-center gap-2">
        <Bot className="h-5 w-5 text-primary" />
        <div>
          <h1 className="text-base font-semibold">AI 合规顾问</h1>
          <p className="mt-1 text-sm text-gray-500">智能分析用工风险，辅助合同审查与合规决策</p>
        </div>
      </div>

      <div className="flex gap-1 border-b overflow-x-auto">
        {tabs.map((t) => {
          const Icon = t.icon
          return (
            <button
              key={t.key}
              onClick={() => setTab(t.key)}
              className={`flex items-center gap-1.5 px-4 py-2 text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${
                tab === t.key ? 'border-primary text-primary' : 'border-transparent text-gray-500 hover:text-gray-700'
              }`}
            >
              <Icon className="w-4 h-4" />
              {t.label}
            </button>
          )
        })}
      </div>

      {tab === 'chat' && <ChatTab />}
      {tab === 'predict' && <PredictTab />}
      {tab === 'review' && <ReviewTab />}
      {tab === 'case' && <CaseTab />}
      {tab === 'hr-report' && <HRReportTab />}
      {tab === 'knowledge' && <KnowledgeTab />}
    </div>
  )
}

function ChatTab() {
  const queryClient = useQueryClient()
  const [messages, setMessages] = useState<Message[]>([
    { role: 'assistant', content: '你好！我是你的用工合规顾问，有什么劳动法问题可以直接问我。\n\n你可以问我：\n· 员工入职没签合同怎么办？\n· 加班费怎么算？\n· 辞退员工需要赔多少？' },
  ])
  const [input, setInput] = useState('')
  const [loading, setLoading] = useState(false)
  const [recording, setRecording] = useState(false)
  const [showHistory, setShowHistory] = useState(false)
  const [currentConvId, setCurrentConvId] = useState<string | null>(null)
  const [showConsultModal, setShowConsultModal] = useState(false)
  const [consultForm, setConsultForm] = useState({ type: 'LEGAL' as string, title: '', description: '', contactName: '', contactPhone: '', remark: '' })
  const scrollRef = useRef<HTMLDivElement>(null)
  const recognitionRef = useRef<any>(null)
  const saveTimerRef = useRef<any>(null)

  const { data: conversations } = useQuery<any[]>({
    queryKey: ['ai-conversations'],
    queryFn: async () => {
      const res = await api.get('/ai/conversations?type=chat') as any
      return res.data
    },
  })

  const deleteConvMutation = useMutation({
    mutationFn: (id: string) => api.delete(`/ai/conversations/${id}`),
    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['ai-conversations'] }),
  })

  const consultMutation = useMutation({
    mutationFn: async (data: typeof consultForm) => {
      const res = await api.post('/ai/consultation', data) as any
      return res.data
    },
    onSuccess: () => {
      toast.success('已提交咨询请求，专业律师将尽快与您联系')
      setShowConsultModal(false)
      setConsultForm({ type: 'LEGAL', title: '', description: '', contactName: '', contactPhone: '', remark: '' })
    },
    onError: (err: any) => {
      toast.error(err?.message || '提交失败，请稍后重试')
    },
  })

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

  // 自动保存会话（debounce）
  useEffect(() => {
    if (messages.length <= 1) return
    if (saveTimerRef.current) clearTimeout(saveTimerRef.current)
    saveTimerRef.current = setTimeout(async () => {
      const title = `chat:${messages.find(m => m.role === 'user')?.content.slice(0, 30) || '新对话'}`
      if (currentConvId) {
        await api.put(`/ai/conversations/${currentConvId}`, { messages }).catch(() => {})
      } else {
        const res = await api.post('/ai/conversations', { title, messages }) as any
        if (res.data?.id) {
          setCurrentConvId(res.data.id)
          queryClient.invalidateQueries({ queryKey: ['ai-conversations'] })
        }
      }
    }, 2000)
    return () => { if (saveTimerRef.current) clearTimeout(saveTimerRef.current) }
  }, [messages])

  const loadConversation = async (id: string) => {
    try {
      const res = await api.get(`/ai/conversations/${id}`) as any
      if (res.data?.messages) {
        setMessages(res.data.messages)
        setCurrentConvId(id)
        setShowHistory(false)
      }
    } catch {}
  }

  const newConversation = () => {
    setMessages([{ role: 'assistant', content: '你好！我是你的用工合规顾问，有什么劳动法问题可以直接问我。\n\n你可以问我：\n· 员工入职没签合同怎么办？\n· 加班费怎么算？\n· 辞退员工需要赔多少？' }])
    setCurrentConvId(null)
    setShowHistory(false)
  }

  const toggleVoice = () => {
    const SpeechRecognition = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition
    if (!SpeechRecognition) {
      toast.error('当前浏览器不支持语音输入，请使用 Chrome 或 Edge')
      return
    }
    if (recording) {
      recognitionRef.current?.stop()
      setRecording(false)
      return
    }
    const recognition = new SpeechRecognition()
    recognition.lang = 'zh-CN'
    recognition.continuous = false
    recognition.interimResults = false
    recognition.onresult = (event: any) => {
      const transcript = event.results[0]?.[0]?.transcript || ''
      setInput((prev) => prev + transcript)
    }
    recognition.onerror = () => setRecording(false)
    recognition.onend = () => setRecording(false)
    recognition.start()
    recognitionRef.current = recognition
    setRecording(true)
  }

  const send = async (text?: string) => {
    const content = text || input.trim()
    if (!content || loading) return

    const newMessages = [...messages, { role: 'user' as const, content }]
    setMessages([...newMessages, { role: 'assistant', content: '' }])
    setInput('')
    setLoading(true)

    try {
      const token = useAuthStore.getState().accessToken
      const controller = new AbortController()
      const timeoutId = setTimeout(() => controller.abort(), 60 * 1000)
      const chatUrl = import.meta.env.DEV ? 'http://localhost:3000/api/v1/ai/chat-stream' : '/api/v1/ai/chat-stream'
      const response = await fetch(chatUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          ...(token ? { Authorization: `Bearer ${token}` } : {}),
        },
        body: JSON.stringify({ messages: newMessages }),
        signal: controller.signal,
      })
      clearTimeout(timeoutId)

      if (!response.ok) {
        const errData = await response.json().catch(() => null)
        throw new Error(errData?.error?.message || '请求失败')
      }

      const reader = response.body?.getReader()
      const decoder = new TextDecoder()
      let accumulated = ''
      let buffer = ''
      let rafId: number | null = null
      let pendingFlush = false

      // 用 RAF 批量刷新，避免每个 token 触发一次 React 重渲染
      const flush = () => {
        pendingFlush = false
        rafId = null
        setMessages([...newMessages, { role: 'assistant', content: accumulated }])
      }
      const scheduleFlush = () => {
        if (!pendingFlush) {
          pendingFlush = true
          rafId = requestAnimationFrame(flush)
        }
      }

      if (reader) {
        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: ')) {
              const data = line.slice(6).trim()
              if (data === '[DONE]') continue
              try {
                const parsed = JSON.parse(data)
                if (parsed.delta) {
                  accumulated += parsed.delta
                  scheduleFlush()
                }
                if (parsed.error) {
                  throw new Error(parsed.error)
                }
              } catch (parseErr: any) {
                // 只有业务错误（有 message 且不是 SyntaxError）才抛出
                if (parseErr instanceof SyntaxError) {
                  // JSON 解析失败，可能是 SSE 分块截断，跳过等下一块
                  continue
                }
                throw parseErr
              }
            }
          }
        }
        // 确保最后一批内容被刷新
        if (rafId) cancelAnimationFrame(rafId)
        if (accumulated) {
          setMessages([...newMessages, { role: 'assistant', content: accumulated }])
        }
      }
      if (!accumulated) {
        setMessages([...newMessages, { role: 'assistant', content: '（无回复内容）' }])
      }
    } catch (err: any) {
      const isTimeout = err.name === 'AbortError'
      setMessages([...newMessages, { role: 'assistant', content: isTimeout ? '请求超时，AI 服务响应时间过长，请稍后重试或简化问题。' : `抱歉，出错了：${err.message || '请稍后重试'}` }])
    } finally {
      setLoading(false)
    }
  }

  return (
    <div className="flex flex-col" style={{ height: 'calc(100vh - 220px)', minHeight: '400px' }}>
      {/* 顶部操作栏 */}
      <div className="flex items-center gap-2 pb-2 border-b">
        <Button size="sm" variant="secondary" onClick={newConversation}><Plus className="w-4 h-4 mr-1" />新对话</Button>
        <Button size="sm" variant="secondary" onClick={() => setShowHistory(!showHistory)}><MessageSquare className="w-4 h-4 mr-1" />历史会话</Button>
        <Button size="sm" variant="secondary" onClick={() => setShowConsultModal(true)}><UserCheck className="w-4 h-4 mr-1" />联系专业律师</Button>
        {conversations && conversations.length > 0 && (
          <span className="text-xs text-gray-400">{conversations.length} 条历史</span>
        )}
      </div>

      {/* 历史会话列表 */}
      {showHistory && (
        <div className="border-b pb-2 max-h-40 overflow-y-auto">
          {conversations && conversations.length > 0 ? conversations.map((c: any) => (
            <div key={c.id} className="flex items-center justify-between px-2 py-1.5 hover:bg-gray-50 rounded cursor-pointer text-xs">
              <span className="flex-1 truncate" onClick={() => loadConversation(c.id)}>{c.title.replace(/^chat:/, '')}</span>
              <span className="text-gray-400 ml-2">{new Date(c.updatedAt).toLocaleDateString('zh-CN', { month: '2-digit', day: '2-digit' })}</span>
              <button onClick={(e) => { e.stopPropagation(); deleteConvMutation.mutate(c.id) }} className="ml-2 text-gray-400 hover:text-danger"><Trash2 className="w-3 h-3" /></button>
            </div>
          )) : <div className="text-xs text-gray-400 py-2 text-center">暂无历史会话</div>}
        </div>
      )}

      <div ref={scrollRef} className="flex-1 overflow-y-auto space-y-4 pb-4">
        {messages.map((msg, i) => (
          <div key={i} className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}>
            <div className={`max-w-[85%] px-4 py-3 rounded-lg text-sm leading-relaxed ${
              msg.role === 'user' ? 'bg-primary text-white whitespace-pre-wrap' : 'bg-white border border-gray-200 text-gray-800 shadow-sm'
            }`}>
              {msg.role === 'assistant' ? (
                msg.content ? (
                  <div className="prose prose-sm max-w-none
                    prose-headings:text-gray-900 prose-headings:font-semibold
                    prose-h1:text-base prose-h1:mt-4 prose-h1:mb-2
                    prose-h2:text-sm prose-h2:mt-3 prose-h2:mb-2
                    prose-h3:text-sm prose-h3:mt-2 prose-h3:mb-1
                    prose-p:my-2 prose-p:leading-relaxed
                    prose-li:my-0.5 prose-li:leading-relaxed
                    prose-ul:my-2 prose-ol:my-2
                    prose-code:text-pink-600 prose-code:bg-gray-100 prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:text-xs prose-code:before:content-none prose-code:after:content-none
                    prose-pre:bg-gray-900 prose-pre:text-gray-100 prose-pre:rounded-lg prose-pre:p-3 prose-pre:my-3
                    prose-blockquote:border-l-primary prose-blockquote:bg-primary/5 prose-blockquote:py-1 prose-blockquote:px-3 prose-blockquote:rounded-r prose-blockquote:not-italic
                    prose-table:text-xs prose-table:border-collapse
                    prose-th:bg-gray-50 prose-th:px-3 prose-th:py-1.5 prose-th:font-semibold prose-th:border prose-th:border-gray-200
                    prose-td:px-3 prose-td:py-1.5 prose-td:border prose-td:border-gray-200
                    prose-a:text-primary prose-a:no-underline hover:prose-a:underline
                    prose-strong:text-gray-900
                    prose-hr:border-gray-200 prose-hr:my-4
                  ">
                    <ReactMarkdown remarkPlugins={[remarkGfm]}>{msg.content}</ReactMarkdown>
                  </div>
                ) : loading && i === messages.length - 1 ? (
                  <span className="inline-flex items-center gap-1.5 text-gray-500">
                    <Loader2 className="w-3.5 h-3.5 animate-spin" />
                    思考中...
                  </span>
                ) : null
              ) : (
                msg.content
              )}
            </div>
          </div>
        ))}
      </div>

      {/* 快捷问题 */}
      {messages.length <= 1 && (
        <div className="flex flex-wrap gap-2 pb-3">
          {QUICK_QUESTIONS.map((q) => (
            <button
              key={q}
              onClick={() => send(q)}
              className="px-3 py-1.5 text-xs rounded-full border border-gray-300 text-gray-600 hover:bg-gray-50"
            >
              {q}
            </button>
          ))}
        </div>
      )}

      {/* 输入框 */}
      <div className="flex gap-2 pt-2 border-t">
        <Input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyDown={(e) => e.key === 'Enter' && send()}
          placeholder="输入问题..."
          disabled={loading}
        />
        <Button variant="secondary" onClick={toggleVoice} disabled={loading} className={recording ? 'text-danger' : ''}>
          <Mic className="w-4 h-4" />
        </Button>
        <Button onClick={() => send()} disabled={loading || !input.trim()}>
          {loading ? <Loader2 className="w-4 h-4 animate-spin" /> : <Send className="w-4 h-4" />}
        </Button>
      </div>

      {/* 转人工咨询 Modal */}
      {showConsultModal && (
        <Modal open={true} title="联系专业律师" onClose={() => setShowConsultModal(false)}>
          <div className="space-y-3">
            <div className="rounded-md bg-blue-50 border border-blue-200 p-3 text-xs text-blue-700">
              <p className="font-medium mb-1">服务说明</p>
              <p>· <strong>法律咨询</strong>：专业律师在线解答劳动法问题</p>
              <p>· <strong>仲裁代理</strong>：律师代理劳动仲裁案件（付费服务）</p>
              <p>· <strong>出庭服务</strong>：律师代理法院诉讼（付费服务）</p>
              <p className="mt-1">提交后律师将在 24 小时内与您联系。</p>
            </div>
            <div>
              <Label>服务类型</Label>
              <Select value={consultForm.type} onChange={(e) => setConsultForm({ ...consultForm, type: e.target.value })}>
                <option value="LEGAL">法律咨询</option>
                <option value="ARBITRATION">仲裁代理（付费）</option>
                <option value="COURT">出庭服务（付费）</option>
              </Select>
            </div>
            <div>
              <Label>问题标题</Label>
              <Input value={consultForm.title} onChange={(e) => setConsultForm({ ...consultForm, title: e.target.value })} placeholder="简要描述您的问题" />
            </div>
            <div>
              <Label>详细描述</Label>
              <textarea
                className="w-full px-3 py-2 rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent text-sm min-h-[80px] resize-y"
                value={consultForm.description}
                onChange={(e) => setConsultForm({ ...consultForm, description: e.target.value })}
                placeholder="请详细描述您遇到的法律问题、涉及的员工情况等"
              />
            </div>
            <div className="grid grid-cols-2 gap-3">
              <div>
                <Label>联系人姓名</Label>
                <Input value={consultForm.contactName} onChange={(e) => setConsultForm({ ...consultForm, contactName: e.target.value })} placeholder="您的姓名" />
              </div>
              <div>
                <Label>联系电话</Label>
                <Input value={consultForm.contactPhone} onChange={(e) => setConsultForm({ ...consultForm, contactPhone: e.target.value })} placeholder="手机号码" maxLength={11} />
              </div>
            </div>
            <div>
              <Label>备注（可选）</Label>
              <Input value={consultForm.remark} onChange={(e) => setConsultForm({ ...consultForm, remark: e.target.value })} placeholder="其他需要说明的信息" />
            </div>
            <div className="flex gap-2 justify-end pt-2">
              <Button variant="secondary" size="sm" onClick={() => setShowConsultModal(false)}>取消</Button>
              <Button
                size="sm"
                onClick={() => consultMutation.mutate(consultForm)}
                disabled={consultMutation.isPending || !consultForm.title || !consultForm.description || !consultForm.contactName || !consultForm.contactPhone}
              >
                {consultMutation.isPending ? '提交中...' : '提交咨询'}
              </Button>
            </div>
          </div>
        </Modal>
      )}
    </div>
  )
}

/** 12 类争议场景 */
const SCENARIO_TYPES = [
  { value: 'discipline', label: '违纪解除' },
  { value: 'incompetence', label: '不胜任解除' },
  { value: 'probation', label: '试用期解除' },
  { value: 'layoff', label: '经济性裁员' },
  { value: 'expiry', label: '合同到期不续签' },
  { value: 'negotiated', label: '协商解除' },
  { value: 'transfer', label: '调岗调薪争议' },
  { value: 'overtime', label: '加班费争议' },
  { value: 'injury', label: '工伤待遇争议' },
  { value: 'noncompete', label: '竞业限制争议' },
  { value: 'confidentiality', label: '保密协议争议' },
  { value: 'social_insurance', label: '社保公积金争议' },
]

function PredictTab() {
  const [result, setResult] = useState('')
  const [loading, setLoading] = useState(false)
  const [mode, setMode] = useState<'general' | 'structured'>('general')
  const [scope, setScope] = useState('all')
  const [riskType, setRiskType] = useState('all')
  const [department, setDepartment] = useState('')
  const [employeeId, setEmployeeId] = useState('')
  const [showHistory, setShowHistory] = useState(false)
  const abortRef = useRef<AbortController | null>(null)
  const { history, saveMutation, deleteMutation, loadHistory } = useAIHistory('predict')

  // 结构化表单状态
  const [scenarioType, setScenarioType] = useState('discipline')
  const [structEmployeeName, setStructEmployeeName] = useState('')
  const [violationFact, setViolationFact] = useState('')
  const [region, setRegion] = useState('')
  const [monthlySalary, setMonthlySalary] = useState('')
  const [democracyStatus, setDemocracyStatus] = useState('')
  const [disciplinaryRecord, setDisciplinaryRecord] = useState('')
  const [extraInfo, setExtraInfo] = useState('')
  // 系统带出字段标记（区分自动填充 vs HR 手动修改）
  const [autoFilledFields, setAutoFilledFields] = useState<{ salary?: boolean; region?: boolean; disciplinary?: boolean; violationFact?: boolean; extraInfo?: boolean }>({})
  // 员工特殊状态提示
  const [employeeSpecialStatus, setEmployeeSpecialStatus] = useState('')
  // 员工违纪记录摘要（系统带出）
  const [disciplinarySummary, setDisciplinarySummary] = useState('')

  const { data: employees } = useQuery<any[]>({
    queryKey: ['roster-list'],
    queryFn: async () => {
      const res = await api.get('/roster?pageSize=999') as any
      return res.data?.items || res.data || []
    },
  })

  const departments = [...new Set((employees || []).map((e: any) => e.department).filter(Boolean))]

  /** 选择员工后自动带出系统已有数据 */
  const handleStructEmployeeChange = async (employeeName: string) => {
    setStructEmployeeName(employeeName)
    // 清空之前带出的数据
    setAutoFilledFields({})
    setEmployeeSpecialStatus('')
    setDisciplinarySummary('')
    setExtraInfo('')
    if (!employeeName) return

    // 从已加载的员工列表中查找（列表数据已含 monthlySalary/isPregnant/city 等字段）
    const emp = (employees || []).find((e: any) => e.name === employeeName)
    if (!emp) return

    // 1. 直接从列表数据带出月薪（已解密）
    if (emp.monthlySalary && Number(emp.monthlySalary) > 0) {
      setMonthlySalary(String(emp.monthlySalary))
      setAutoFilledFields((prev) => ({ ...prev, salary: true }))
    }
    // 2. 直接从列表数据带出地区
    if (emp.city) {
      setRegion(emp.city)
      setAutoFilledFields((prev) => ({ ...prev, region: true }))
    }
    // 3. 直接从列表数据带出特殊状态
    const statusParts: string[] = []
    if (emp.isPregnant) statusParts.push('孕期/哺乳期')
    if (emp.isInMedicalPeriod) statusParts.push('医疗期')
    if (emp.isWorkInjured) statusParts.push('工伤')
    const specialStatus = statusParts.join('、')
    setEmployeeSpecialStatus(specialStatus)
    // 自动将三期/特殊状态填入补充信息
    if (specialStatus) {
      setExtraInfo(`员工特殊状态：${specialStatus}`)
      setAutoFilledFields((prev) => ({ ...prev, extraInfo: true }))
    }

    // 4. 获取违纪记录（列表接口未含明细，需调用专用接口）
    try {
      const res = await api.get(`/roster/${emp.id}/disciplinary`) as any
      const records = res?.data || res || []
      if (Array.isArray(records) && records.length > 0) {
        const typeMap: Record<string, string> = { LATE: '迟到', ABSENT: '旷工', INSUBORDINATION: '不服从管理', MISCONDUCT: '违纪', VIOLATE_POLICY: '违反制度', OTHER: '其他' }
        const actionMap: Record<string, string> = { ORAL_WARNING: '口头警告', WRITTEN_WARNING: '书面警告', DEDUCTION: '扣款', DEMOTION: '降职', TERMINATION: '辞退' }
        const summary = records.map((r: any) =>
          `${r.violationDate?.slice(0, 10) || ''} ${typeMap[r.violationType] || r.violationType}：${r.description || ''}（处理：${actionMap[r.action] || r.action}${r.employeeAck ? '，已签字' : '，未签字'}）`
        ).join('；')
        setDisciplinarySummary(`系统已有 ${records.length} 条违纪记录：${summary}`)
        // 自动填充"违纪/争议事实"文本框
        const factText = `【系统已有违纪记录】\n${records.map((r: any) =>
          `- ${r.violationDate?.slice(0, 10) || ''} ${typeMap[r.violationType] || r.violationType}：${r.description || ''}（处理：${actionMap[r.action] || r.action}${r.employeeAck ? '，已签字' : '，未签字'}）`
        ).join('\n')}\n\n【本次争议事实】请在此描述当前拟处理的具体情况...`
        setViolationFact(factText)
        setAutoFilledFields((prev) => ({ ...prev, violationFact: true }))
        // 自动填充"违纪记录留痕情况"下拉
        const hasWrittenAck = records.some((r: any) => r.action === 'WRITTEN_WARNING' && r.employeeAck)
        const hasWrittenNoAck = records.some((r: any) => r.action === 'WRITTEN_WARNING' && !r.employeeAck)
        const hasOralOnly = records.every((r: any) => r.action === 'ORAL_WARNING')
        if (hasWrittenAck) {
          setDisciplinaryRecord('有书面警告信且员工签收')
          setAutoFilledFields((prev) => ({ ...prev, disciplinary: true }))
        } else if (hasWrittenNoAck) {
          setDisciplinaryRecord('有书面记录但未签收')
          setAutoFilledFields((prev) => ({ ...prev, disciplinary: true }))
        } else if (hasOralOnly) {
          setDisciplinaryRecord('仅有口头警告')
          setAutoFilledFields((prev) => ({ ...prev, disciplinary: true }))
        }
      } else {
        setDisciplinarySummary('系统无违纪记录')
      }
    } catch (err) {
      console.error('[PredictTab] 获取违纪记录失败:', err)
    }
  }

  /** 通用 SSE 流读取（复用于两种模式） */
  const streamSSE = async (response: Response, onDone: (accumulated: string) => void) => {
    const reader = response.body?.getReader()
    const decoder = new TextDecoder()
    let accumulated = ''
    let buffer = ''
    let rafId: number | null = null
    let pendingFlush = false

    const flush = () => {
      pendingFlush = false
      rafId = null
      setResult(accumulated)
    }
    const scheduleFlush = () => {
      if (!pendingFlush) {
        pendingFlush = true
        rafId = requestAnimationFrame(flush)
      }
    }

    if (reader) {
      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: ')) {
            const data = line.slice(6).trim()
            if (data === '[DONE]') continue
            try {
              const parsed = JSON.parse(data)
              if (parsed.delta) {
                accumulated += parsed.delta
                scheduleFlush()
              }
              if (parsed.error) {
                throw new Error(parsed.error)
              }
            } catch (parseErr: any) {
              if (parseErr instanceof SyntaxError) continue
              throw parseErr
            }
          }
        }
      }
      if (rafId) cancelAnimationFrame(rafId)
      setResult(accumulated)
      if (accumulated && !accumulated.startsWith('**出错了**')) {
        onDone(accumulated)
      }
    }
  }

  const fetchPrediction = async () => {
    if (loading) return
    abortRef.current?.abort()
    const controller = new AbortController()
    abortRef.current = controller

    setLoading(true)
    setResult('')

    try {
      const token = useAuthStore.getState().accessToken
      const params = new URLSearchParams()
      if (scope === 'department' && department) params.set('department', department)
      if (scope === 'employee' && employeeId) params.set('employeeId', employeeId)
      if (riskType !== 'all') params.set('riskType', riskType)

      const predictUrl = import.meta.env.DEV
        ? `http://localhost:3000/api/v1/ai/predict-stream?${params}`
        : `/api/v1/ai/predict-stream?${params}`

      const response = await fetch(predictUrl, {
        method: 'GET',
        headers: {
          ...(token ? { Authorization: `Bearer ${token}` } : {}),
        },
        signal: controller.signal,
      })

      if (!response.ok) {
        const errData = await response.json().catch(() => null)
        throw new Error(errData?.error?.message || '请求失败')
      }

      await streamSSE(response, (accumulated) => {
        const scopeLabel = scope === 'all' ? '全部员工' : scope === 'department' ? department : employees?.find((e: any) => e.id === employeeId)?.name || '指定员工'
        const riskLabel = riskType === 'all' ? '全部类型' : riskType
        saveMutation.mutate({ title: `${scopeLabel}-${riskLabel}`, input: `范围:${scopeLabel} 类型:${riskLabel}`, result: accumulated })
      })
    } catch (err: any) {
      if (err.name === 'AbortError') return
      setResult(`**出错了**：${err.message || '请稍后重试'}`)
    } finally {
      setLoading(false)
    }
  }

  /** 结构化判赔预测 */
  const fetchStructuredPrediction = async () => {
    if (loading) return
    abortRef.current?.abort()
    const controller = new AbortController()
    abortRef.current = controller

    setLoading(true)
    setResult('')

    try {
      const token = useAuthStore.getState().accessToken
      const predictUrl = import.meta.env.DEV
        ? `http://localhost:3000/api/v1/ai/predict-structured`
        : `/api/v1/ai/predict-structured`

      const response = await fetch(predictUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          ...(token ? { Authorization: `Bearer ${token}` } : {}),
        },
        body: JSON.stringify({
          scenarioType,
          keyFacts: {
            employeeName: structEmployeeName || undefined,
            violationFact: violationFact || undefined,
            region: region || undefined,
            monthlySalary: monthlySalary || undefined,
            democracyStatus: democracyStatus || undefined,
            disciplinaryRecord: disciplinaryRecord || undefined,
            extraInfo: extraInfo || undefined,
          },
        }),
        signal: controller.signal,
      })

      if (!response.ok) {
        const errData = await response.json().catch(() => null)
        throw new Error(errData?.error?.message || '请求失败')
      }

      const scenarioLabel = SCENARIO_TYPES.find((s) => s.value === scenarioType)?.label || scenarioType
      await streamSSE(response, (accumulated) => {
        saveMutation.mutate({
          title: `判赔-${scenarioLabel}${structEmployeeName ? '-' + structEmployeeName : ''}`,
          input: `场景:${scenarioLabel} 员工:${structEmployeeName || '未指定'}`,
          result: accumulated,
        })
      })
    } catch (err: any) {
      if (err.name === 'AbortError') return
      setResult(`**出错了**：${err.message || '请稍后重试'}`)
    } finally {
      setLoading(false)
    }
  }

  const handleLoadHistory = async (id: string) => {
    const data = await loadHistory(id)
    if (data?.messages) {
      const assistantMsg = data.messages.find((m: any) => m.role === 'assistant')
      if (assistantMsg) {
        setResult(assistantMsg.content)
        setShowHistory(false)
      }
    }
  }

  const handlePredict = () => {
    if (mode === 'structured') {
      fetchStructuredPrediction()
    } else {
      fetchPrediction()
    }
  }

  /** 解析 markdown 内联格式（**bold** 和 `code`）为 TextRun 数组 */
  const parseInlineBold = (text: string): TextRun[] => {
    const runs: TextRun[] = []
    const regex = /(\*\*(.+?)\*\*|`(.+?)`)/g
    let lastIndex = 0
    let match
    while ((match = regex.exec(text)) !== null) {
      if (match.index > lastIndex) {
        runs.push(new TextRun({ text: text.slice(lastIndex, match.index) }))
      }
      if (match[2]) {
        runs.push(new TextRun({ text: match[2], bold: true }))
      } else if (match[3]) {
        runs.push(new TextRun({ text: match[3], font: 'Courier New', size: 20 }))
      }
      lastIndex = regex.lastIndex
    }
    if (lastIndex < text.length) {
      runs.push(new TextRun({ text: text.slice(lastIndex) }))
    }
    return runs.length ? runs : [new TextRun({ text })]
  }

  /** 导出 AI 分析结果为 Word 文档 */
  const handleExportWord = async () => {
    if (!result) return
    try {
      const lines = result.split('\n')
      const children: (Paragraph | Table)[] = []
      let i = 0

      while (i < lines.length) {
        const line = lines[i]

        // 跳过空行
        if (!line.trim()) { i++; continue }

        // 表格（markdown GFM 表格语法）
        if (line.includes('|') && i + 1 < lines.length && lines[i + 1].includes('---')) {
          const headerCells = line.split('|').map(c => c.trim()).filter(Boolean)
          i += 2 // 跳过分隔行
          const rows: TableRow[] = []
          // 表头
          rows.push(new TableRow({
            children: headerCells.map(text => new TableCell({
              children: [new Paragraph({ children: [new TextRun({ text, bold: true })] })],
              shading: { fill: 'F3F4F6' },
            })),
          }))
          // 数据行
          while (i < lines.length && lines[i].includes('|') && lines[i].trim()) {
            const cells = lines[i].split('|').map(c => c.trim()).filter(Boolean)
            rows.push(new TableRow({
              children: cells.map(text => new TableCell({
                children: [new Paragraph({ children: [new TextRun({ text })] })],
              })),
            }))
            i++
          }
          children.push(new Table({
            rows,
            width: { size: 100, type: WidthType.PERCENTAGE },
          }))
          continue
        }

        // 标题
        if (line.startsWith('### ')) {
          children.push(new Paragraph({ heading: HeadingLevel.HEADING_3, children: [new TextRun({ text: line.slice(4), bold: true })] }))
        } else if (line.startsWith('## ')) {
          children.push(new Paragraph({ heading: HeadingLevel.HEADING_2, children: [new TextRun({ text: line.slice(3), bold: true })] }))
        } else if (line.startsWith('# ')) {
          children.push(new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun({ text: line.slice(2), bold: true })] }))
        } else if (line.startsWith('> ')) {
          // 引用块
          children.push(new Paragraph({
            children: [new TextRun({ text: line.slice(2), italics: true })],
            indent: { left: 720 },
          }))
        } else if (line.startsWith('- ') || line.startsWith('* ')) {
          // 无序列表
          children.push(new Paragraph({
            children: parseInlineBold(line.slice(2)),
            bullet: { level: 0 },
          }))
        } else if (/^\d+\.\s/.test(line)) {
          // 有序列表
          children.push(new Paragraph({
            children: parseInlineBold(line.replace(/^\d+\.\s/, '')),
            numbering: { reference: 'default-numbering', level: 0 },
          }))
        } else if (line === '---' || line === '***') {
          // 分隔线
          children.push(new Paragraph({
            children: [],
            border: { bottom: { style: BorderStyle.SINGLE, size: 6, color: 'E5E7EB' } },
          }))
        } else {
          // 普通段落（支持 **bold** 和 `code`）
          children.push(new Paragraph({
            children: parseInlineBold(line),
          }))
        }
        i++
      }

      const doc = new Document({
        numbering: {
          config: [{
            reference: 'default-numbering',
            levels: [{ level: 0, format: 'decimal', text: '%1.', alignment: AlignmentType.START }],
          }],
        },
        sections: [{ children }],
      })

      const blob = await Packer.toBlob(doc)
      const fileName = mode === 'structured'
        ? `判赔预测报告_${structEmployeeName || '未指定员工'}_${new Date().toISOString().slice(0, 10)}.docx`
        : `风险预测报告_${new Date().toISOString().slice(0, 10)}.docx`
      saveAs(blob, fileName)
      toast.success('Word 文档已导出')
    } catch (err) {
      console.error('导出 Word 失败:', err)
      toast.error('导出失败，请重试')
    }
  }

  return (
    <Card>
      <div className="flex items-center gap-2 mb-4">
        <Sparkles className="w-5 h-5 text-primary" />
        <h2 className="text-sm font-medium">AI 风险预测</h2>
        <Button size="sm" variant="secondary" className="ml-auto" onClick={() => setShowHistory(!showHistory)}><History className="w-4 h-4 mr-1" />历史记录</Button>
      </div>

      {showHistory && (
        <div className="mt-2">
          <HistoryBar history={history || []} onLoad={handleLoadHistory} onDelete={(id) => deleteMutation.mutate(id)} />
        </div>
      )}

      {/* 模式切换 */}
      <div className="flex gap-1 mb-4 mt-3 border-b pb-2">
        <button
          onClick={() => { setMode('general'); setResult('') }}
          className={`px-3 py-1.5 text-xs font-medium rounded-md transition-colors ${
            mode === 'general' ? 'bg-primary text-white' : 'text-gray-500 hover:bg-gray-50'
          }`}
        >
          全员风险扫描
        </button>
        <button
          onClick={() => { setMode('structured'); setResult('') }}
          className={`px-3 py-1.5 text-xs font-medium rounded-md transition-colors ${
            mode === 'structured' ? 'bg-primary text-white' : 'text-gray-500 hover:bg-gray-50'
          }`}
        >
          判赔预测（结构化输入）
        </button>
      </div>

      {/* === 通用模式筛选条件 === */}
      {mode === 'general' && (
        <div className="flex items-center gap-2 mb-4 flex-wrap">
          <div className="min-w-[120px]">
            <Button size="sm" onClick={handlePredict} disabled={loading}>
              {loading ? '分析中...' : result ? '重新预测' : '开始预测'}
            </Button>
          </div>
          <div className="flex items-center gap-2">
            <Label className="whitespace-nowrap">预测范围</Label>
            <Select value={scope} onChange={(e) => setScope(e.target.value)}>
              <option value="all">全部员工</option>
              <option value="department">按部门</option>
              <option value="employee">指定员工</option>
            </Select>
          </div>
          <div className="flex items-center gap-2">
            <Label className="whitespace-nowrap">风险类型</Label>
            <Select value={riskType} onChange={(e) => setRiskType(e.target.value)}>
              <option value="all">全部类型</option>
              <option value="contract">合同风险</option>
              <option value="salary">薪酬风险</option>
              <option value="termination">解聘风险</option>
            </Select>
          </div>
          {scope === 'department' && (
            <div className="flex items-center gap-2">
              <Label className="whitespace-nowrap">部门</Label>
              <Select value={department} onChange={(e) => setDepartment(e.target.value)}>
                <option value="">选择部门</option>
                {departments.map((d: string) => <option key={d} value={d}>{d}</option>)}
              </Select>
            </div>
          )}
          {scope === 'employee' && (
            <div className="flex items-center gap-2">
              <Label className="whitespace-nowrap">员工</Label>
              <Select value={employeeId} onChange={(e) => setEmployeeId(e.target.value)}>
                <option value="">选择员工</option>
                {(employees || []).map((e: any) => <option key={e.id} value={e.id}>{e.name}</option>)}
              </Select>
            </div>
          )}
        </div>
      )}

      {/* === 通用模式 AI 结果 === */}
      {mode === 'general' && loading && !result && (
        <div className="flex items-center gap-2 text-gray-400 py-8">
          <Loader2 className="w-5 h-5 animate-spin" /> 正在分析企业用工风险...
        </div>
      )}
      {mode === 'general' && result && (
        <div className="prose prose-sm max-w-none mt-4 overflow-x-auto
          prose-headings:text-gray-900 prose-headings:font-semibold
          prose-h1:text-base prose-h1:mt-4 prose-h1:mb-2
          prose-h2:text-sm prose-h2:mt-3 prose-h2:mb-2
          prose-h3:text-sm prose-h3:mt-2 prose-h3:mb-1
          prose-p:my-2 prose-p:leading-relaxed
          prose-li:my-0.5 prose-li:leading-relaxed
          prose-ul:my-2 prose-ol:my-2
          prose-code:text-pink-600 prose-code:bg-gray-100 prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:text-xs prose-code:before:content-none prose-code:after:content-none
          prose-pre:bg-gray-900 prose-pre:text-gray-100 prose-pre:rounded-lg prose-pre:p-3 prose-pre:my-3
          prose-blockquote:border-l-primary prose-blockquote:bg-primary/5 prose-blockquote:py-1 prose-blockquote:px-3 prose-blockquote:rounded-r prose-blockquote:not-italic
          prose-table:text-xs prose-table:border-collapse
          prose-th:bg-gray-100 prose-th:px-2 prose-th:py-1.5 prose-th:font-semibold prose-th:border prose-th:border-gray-300 prose-th:whitespace-nowrap
          prose-td:px-2 prose-td:py-1.5 prose-td:border prose-td:border-gray-300 prose-td:align-top
          prose-a:text-primary prose-a:no-underline hover:prose-a:underline
          prose-strong:text-gray-900
          prose-hr:border-gray-200 prose-hr:my-4">
          <ReactMarkdown remarkPlugins={[remarkGfm]}>{result}</ReactMarkdown>
          {loading && <Loader2 className="w-4 h-4 animate-spin inline-block text-gray-400 ml-1" />}
        </div>
      )}
      {mode === 'general' && !result && !loading && (
        <div className="text-center py-8 text-gray-400">
          <Sparkles className="w-8 h-8 mx-auto mb-2 text-gray-300" />
          <p className="text-xs">选择筛选条件后点击「开始预测」按钮进行AI风险分析</p>
        </div>
      )}

      {/* === 结构化判赔预测：左右两栏布局 === */}
      {mode === 'structured' && (
        <div className="grid grid-cols-1 lg:grid-cols-5 gap-4 mb-4">
          {/* 左栏：表单（占 2/5） */}
          <div className="space-y-3 lg:col-span-2">
            {/* 卡片1：员工信息 */}
            <div className="border border-gray-200 rounded-lg p-3 bg-white">
              <div className="flex items-center gap-1.5 mb-2.5 text-xs font-semibold text-gray-700">
                <User className="w-3.5 h-3.5 text-primary" />
                员工信息
              </div>
              <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                <div>
                  <Label>争议场景 <span className="text-danger">*</span></Label>
                  <Select value={scenarioType} onChange={(e) => setScenarioType(e.target.value)}>
                    {SCENARIO_TYPES.map((s) => <option key={s.value} value={s.value}>{s.label}</option>)}
                  </Select>
                </div>
                <div>
                  <Label>涉及员工</Label>
                  <Select value={structEmployeeName} onChange={(e) => handleStructEmployeeChange(e.target.value)}>
                    <option value="">选择员工（可选）</option>
                    {(employees || []).map((e: any) => <option key={e.id} value={e.name}>{e.name}（{e.department}）</option>)}
                  </Select>
                  {employeeSpecialStatus && (
                    <div className="mt-1 flex items-center gap-1 text-xs text-amber-700 bg-amber-50 border border-amber-200 px-2 py-1 rounded">
                      <AlertTriangle className="w-3 h-3 flex-shrink-0" />
                      该员工处于：<strong>{employeeSpecialStatus}</strong>
                    </div>
                  )}
                </div>
              </div>
              <div className="grid grid-cols-1 md:grid-cols-2 gap-3 mt-3">
                <div>
                  <Label className="flex items-center gap-1">
                    所在地区
                    {autoFilledFields.region && <span title="系统带出"><Database className="w-3 h-3 text-primary" /></span>}
                  </Label>
                  <Input
                    placeholder="如：北京"
                    value={region}
                    onChange={(e) => { setRegion(e.target.value); setAutoFilledFields((prev) => ({ ...prev, region: false })) }}
                  />
                </div>
                <div>
                  <Label className="flex items-center gap-1">
                    员工月薪（元）
                    {autoFilledFields.salary && <span title="系统带出"><Database className="w-3 h-3 text-primary" /></span>}
                  </Label>
                  <Input
                    type="number"
                    placeholder="如：8000"
                    value={monthlySalary}
                    onChange={(e) => { setMonthlySalary(e.target.value); setAutoFilledFields((prev) => ({ ...prev, salary: false })) }}
                  />
                </div>
              </div>
            </div>

            {/* 卡片2：争议事实 */}
            <div className="border border-gray-200 rounded-lg p-3 bg-white">
              <div className="flex items-center gap-1.5 mb-2.5 text-xs font-semibold text-gray-700">
                <FileText className="w-3.5 h-3.5 text-primary" />
                争议事实
              </div>
              <Label className="flex items-center gap-1">
                违纪/争议事实
                {autoFilledFields.violationFact && <span title="系统带出，请补充本次争议事实"><Database className="w-3 h-3 text-primary" /></span>}
              </Label>
              <textarea
                className="w-full px-3 py-2 rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent text-xs min-h-[80px] resize-y"
                placeholder="描述具体的违纪事实或争议情况，例如：员工连续旷工3天，公司拟以严重违纪为由解除劳动合同..."
                value={violationFact}
                onChange={(e) => { setViolationFact(e.target.value); setAutoFilledFields((prev) => ({ ...prev, violationFact: false })) }}
              />
              <div className="mt-2">
                <Label>
                  补充信息（可选）
                  {autoFilledFields.extraInfo && <span title="系统带出"><Database className="w-3 h-3 text-primary inline" /></span>}
                </Label>
                <textarea
                  className="w-full px-3 py-2 rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent text-xs min-h-[50px] resize-y"
                  placeholder="其他需要说明的情况，如是否有工会等..."
                  value={extraInfo}
                  onChange={(e) => { setExtraInfo(e.target.value); setAutoFilledFields((prev) => ({ ...prev, extraInfo: false })) }}
                />
              </div>
            </div>

            {/* 卡片3：制度合规 */}
            <div className="border border-gray-200 rounded-lg p-3 bg-white">
              <div className="flex items-center gap-1.5 mb-2.5 text-xs font-semibold text-gray-700">
                <Shield className="w-3.5 h-3.5 text-primary" />
                制度合规
              </div>
              <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                <div>
                  <Label>制度民主公示状态</Label>
                  <Select value={democracyStatus} onChange={(e) => setDemocracyStatus(e.target.value)}>
                    <option value="">请选择</option>
                    <option value="已履行民主程序并公示">已履行民主程序并公示</option>
                    <option value="已公示但未履行民主程序">已公示但未履行民主程序</option>
                    <option value="未公示未履行民主程序">未公示未履行民主程序</option>
                    <option value="不确定">不确定</option>
                  </Select>
                </div>
                <div>
                  <Label className="flex items-center gap-1">
                    违纪记录留痕情况
                    {autoFilledFields.disciplinary && <span title="系统带出"><Database className="w-3 h-3 text-primary" /></span>}
                  </Label>
                  <Select value={disciplinaryRecord} onChange={(e) => { setDisciplinaryRecord(e.target.value); setAutoFilledFields((prev) => ({ ...prev, disciplinary: false })) }}>
                    <option value="">请选择</option>
                    <option value="有书面警告信且员工签收">有书面警告信且员工签收</option>
                    <option value="有书面记录但未签收">有书面记录但未签收</option>
                    <option value="仅有口头警告">仅有口头警告</option>
                    <option value="无任何记录">无任何记录</option>
                  </Select>
                </div>
              </div>
            </div>

            <div className="flex items-center gap-3">
              <Button size="sm" onClick={handlePredict} disabled={loading}>
                {loading ? '分析中...' : result ? '重新预测' : '开始判赔预测'}
              </Button>
              <span className="text-xs text-gray-400">AI 分析结果仅供参考，实际以仲裁裁决为准</span>
            </div>
          </div>

          {/* 右栏：AI 结果（占 3/5） */}
          <div className="border border-gray-200 rounded-lg p-3 bg-gray-50 flex flex-col lg:col-span-3" style={{ height: 'calc(100vh - 320px)', maxHeight: 'calc(100vh - 320px)' }}>
            <div className="flex items-center justify-between mb-2.5 flex-shrink-0">
              <div className="flex items-center gap-1.5 text-xs font-semibold text-gray-700">
                <Sparkles className="w-3.5 h-3.5 text-primary" />
                AI 分析结果
              </div>
              {result && !loading && (
                <button
                  onClick={handleExportWord}
                  className="flex items-center gap-1 text-xs text-primary hover:text-primary/80 transition-colors"
                >
                  <Download className="w-3.5 h-3.5" />
                  导出 Word
                </button>
              )}
            </div>
            <div className="flex-1 overflow-y-auto">
            {loading && !result && (
              <div className="flex items-center gap-2 text-gray-400 py-8">
                <Loader2 className="w-5 h-5 animate-spin" /> 正在分析判赔风险...
              </div>
            )}
            {result && (
              <div className="prose prose-sm max-w-none overflow-x-auto
                prose-headings:text-gray-900 prose-headings:font-semibold
                prose-h1:text-base prose-h1:mt-4 prose-h1:mb-2
                prose-h2:text-sm prose-h2:mt-3 prose-h2:mb-2
                prose-h3:text-sm prose-h3:mt-2 prose-h3:mb-1
                prose-p:my-2 prose-p:leading-relaxed
                prose-li:my-0.5 prose-li:leading-relaxed
                prose-ul:my-2 prose-ol:my-2
                prose-code:text-pink-600 prose-code:bg-gray-100 prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:text-xs prose-code:before:content-none prose-code:after:content-none
                prose-pre:bg-gray-900 prose-pre:text-gray-100 prose-pre:rounded-lg prose-pre:p-3 prose-pre:my-3
                prose-blockquote:border-l-primary prose-blockquote:bg-primary/5 prose-blockquote:py-1 prose-blockquote:px-3 prose-blockquote:rounded-r prose-blockquote:not-italic
                prose-table:text-xs prose-table:border-collapse
                prose-th:bg-gray-100 prose-th:px-2 prose-th:py-1.5 prose-th:font-semibold prose-th:border prose-th:border-gray-300 prose-th:whitespace-nowrap
                prose-td:px-2 prose-td:py-1.5 prose-td:border prose-td:border-gray-300 prose-td:align-top
                prose-a:text-primary prose-a:no-underline hover:prose-a:underline
                prose-strong:text-gray-900
                prose-hr:border-gray-200 prose-hr:my-4">
                <ReactMarkdown remarkPlugins={[remarkGfm]}>{result}</ReactMarkdown>
                {loading && <Loader2 className="w-4 h-4 animate-spin inline-block text-gray-400 ml-1" />}
              </div>
            )}
            {!result && !loading && (
              <div className="text-center py-12 text-gray-400">
                <Sparkles className="w-8 h-8 mx-auto mb-2 text-gray-300" />
                <p className="text-xs">填写争议场景和关键事实后点击「开始判赔预测」</p>
              </div>
            )}
            </div>
          </div>
        </div>
      )}
    </Card>
  )
}

const REVIEW_DOC_TYPES = [
  { value: 'labor_contract', label: '劳动合同' },
  { value: 'rescission', label: '协商解除协议' },
  { value: 'labor_service', label: '劳务协议' },
  { value: 'internship', label: '实习协议' },
  { value: 'nda', label: '保密协议' },
  { value: 'other', label: '其他' },
]

function ReviewTab() {
  const [contractText, setContractText] = useState('')
  const [result, setResult] = useState<any>(null)
  const [loading, setLoading] = useState(false)
  const [uploading, setUploading] = useState(false)
  const [docType, setDocType] = useState('labor_contract')
  const [fileName, setFileName] = useState('')
  const [showSaveModal, setShowSaveModal] = useState(false)
  const [saveEmployeeId, setSaveEmployeeId] = useState('')
  const [showHistory, setShowHistory] = useState(false)
  const fileInputRef = useRef<HTMLInputElement>(null)
  const { history, saveMutation, deleteMutation, loadHistory } = useAIHistory('review')

  const handleFileUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0]
    if (!file) return
    const ext = file.name.toLowerCase().split('.').pop()
    if (ext !== 'docx' && ext !== 'doc') {
      toast.error('仅支持 .docx 格式文件')
      return
    }
    if (file.size > 100 * 1024 * 1024) {
      toast.error('文件大小不能超过 100MB')
      return
    }
    setUploading(true)
    try {
      const formData = new FormData()
      formData.append('file', file)
      const res = await api.post('/ai/review/upload', formData, {
        headers: { 'Content-Type': 'multipart/form-data' },
      }) as any
      if (res.data?.text) {
        setContractText(res.data.text)
        setFileName(file.name)
        toast.success(`已提取文件内容（${res.data.text.length} 字）`)
      }
    } catch (err: any) {
      toast.error(err?.response?.data?.error?.message || '文件上传失败')
    } finally {
      setUploading(false)
      if (fileInputRef.current) fileInputRef.current.value = ''
    }
  }

  const { data: employees } = useQuery<any[]>({
    queryKey: ['roster-list'],
    queryFn: async () => {
      const res = await api.get('/roster') as any
      return res.data?.items || res.data || []
    },
  })

  const handleReview = async () => {
    if (!contractText.trim()) return
    setLoading(true)
    setResult(null)
    try {
      const res = await api.post('/ai/review', { contractText }) as any
      setResult(res.data)
      // 自动保存到历史
      if (res.data && !res.data.error) {
        const title = contractText.slice(0, 30).replace(/\n/g, ' ')
        saveMutation.mutate({ title, input: contractText, result: res.data.text || JSON.stringify(res.data) })
      }
    } catch (err: any) {
      setResult({ error: `出错了：${err.response?.data?.error?.message || '请稍后重试'}` })
    } finally {
      setLoading(false)
    }
  }

  const handleLoadHistory = async (id: string) => {
    const data = await loadHistory(id)
    if (data?.messages) {
      const userMsg = data.messages.find((m: any) => m.role === 'user')
      const assistantMsg = data.messages.find((m: any) => m.role === 'assistant')
      if (userMsg) setContractText(userMsg.content)
      if (assistantMsg) {
        try { setResult(JSON.parse(assistantMsg.content)) } catch { setResult({ text: assistantMsg.content }) }
      }
      setShowHistory(false)
    }
  }

  const handleSave = async () => {
    if (!saveEmployeeId || !result) return
    try {
      await api.post('/ai/review/save', { employeeId: saveEmployeeId, type: 'REVIEW', input: contractText, result: result.text || JSON.stringify(result) })
      setShowSaveModal(false)
      setSaveEmployeeId('')
      toast.success('已保存到员工档案')
    } catch (err: any) {
      toast.error('保存失败：' + (err.response?.data?.error?.message || '请稍后重试'))
    }
  }

  const levelConfig: Record<string, { color: string; bg: string; label: string }> = {
    RED: { color: 'text-red-600', bg: 'bg-red-50', label: '高风险' },
    YELLOW: { color: 'text-yellow-600', bg: 'bg-yellow-50', label: '中风险' },
    GREEN: { color: 'text-green-600', bg: 'bg-green-50', label: '低风险' },
  }

  return (
    <div className="space-y-4">
      <Card>
        <div className="flex items-center gap-2 mb-4">
          <FileSearch className="w-5 h-5 text-primary" />
          <h2 className="text-sm font-medium">合同审查</h2>
          <Button size="sm" variant="secondary" className="ml-auto" onClick={() => setShowHistory(!showHistory)}><History className="w-4 h-4 mr-1" />历史记录</Button>
        </div>

        {showHistory && (
          <div className="mt-2 mb-3">
            <HistoryBar history={history || []} onLoad={handleLoadHistory} onDelete={(id) => deleteMutation.mutate(id)} />
          </div>
        )}
        <div className="mt-3 space-y-3">
        {/* 文件上传区 */}
        <div>
          <Label>上传文件审查（可选）</Label>
          <div className="flex items-center gap-2">
            <Select value={docType} onChange={(e) => setDocType(e.target.value)} className="w-40">
              {REVIEW_DOC_TYPES.map(t => <option key={t.value} value={t.value}>{t.label}</option>)}
            </Select>
            <input ref={fileInputRef} type="file" accept=".docx,.doc" onChange={handleFileUpload} className="hidden" />
            <Button size="sm" variant="secondary" onClick={() => fileInputRef.current?.click()} disabled={uploading}>
              {uploading ? (<><Loader2 className="w-4 h-4 animate-spin mr-1" />提取中...</>) : (<><FileText className="w-4 h-4 mr-1" />上传 .docx 文件</>)}
            </Button>
            {fileName && <span className="text-xs text-gray-500 truncate max-w-[200px]">{fileName}</span>}
          </div>
        </div>

        <Label>粘贴或上传合同条款文本</Label>
        <textarea
          className="w-full px-3 py-2 rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent text-xs min-h-[200px] resize-y"
          placeholder="粘贴劳动合同文本..."
          value={contractText}
          onChange={(e) => setContractText(e.target.value)}
        />
        <div className="mt-3">
          <Button onClick={handleReview} disabled={loading || !contractText.trim()}>
            {loading ? <><Loader2 className="w-4 h-4 animate-spin mr-1" />审查中...</> : '开始审查'}
          </Button>
        </div>
        </div>
      </Card>

      {result && (
        <Card>
          <div className="flex items-center justify-between mb-3">
            <h3 className="font-medium">审查结果</h3>
            <Button size="sm" variant="secondary" onClick={() => setShowSaveModal(true)}><Save className="w-4 h-4 mr-1" />保存到员工档案</Button>
          </div>
          {result.error ? (
            <div className="text-xs text-danger">{result.error}</div>
          ) : result.structured ? (
            <div className="space-y-3">
              {/* 合规评分 */}
              <div className="flex items-center gap-3">
                <span className="text-xs text-gray-500">合规评分</span>
                <span className={`text-lg font-bold ${result.structured.score >= 80 ? 'text-safe' : result.structured.score >= 60 ? 'text-warning' : 'text-danger'}`}>
                  {result.structured.score}/100
                </span>
              </div>

              {/* 风险项列表 */}
              {result.structured.riskItems.length > 0 && (
                <div className="space-y-2">
                  <h4 className="text-xs font-medium">风险项（{result.structured.riskItems.length}）</h4>
                  {result.structured.riskItems.map((item: any, i: number) => {
                    const cfg = levelConfig[item.level] || levelConfig.YELLOW
                    return (
                      <div key={i} className={`rounded-md p-3 ${cfg.bg}`}>
                        <div className="flex items-center gap-2 mb-1">
                          <span className={`text-xs font-medium ${cfg.color}`}>{cfg.label}</span>
                          <span className="text-xs font-medium">{item.title}</span>
                        </div>
                        <div className="text-xs text-gray-600 mb-1">{item.description}</div>
                        <div className="text-xs text-gray-500">建议：{item.suggestion}</div>
                      </div>
                    )
                  })}
                </div>
              )}

              {/* 总体建议 */}
              {result.structured.summary && (
                <div className="border-t pt-2">
                  <h4 className="text-xs font-medium mb-1">总体建议</h4>
                  <p className="text-xs text-gray-600">{result.structured.summary}</p>
                </div>
              )}

              {/* 原始文本可展开 */}
              <details className="border-t pt-2">
                <summary className="text-xs text-gray-400 cursor-pointer">查看原始文本</summary>
                <div className="text-xs text-gray-700 whitespace-pre-wrap mt-2">{result.text}</div>
              </details>
            </div>
          ) : (
            <div className="text-xs text-gray-700 whitespace-pre-wrap">{result.text || JSON.stringify(result)}</div>
          )}
        </Card>
      )}

      {showSaveModal && (
        <Modal open onClose={() => setShowSaveModal(false)} size="sm">
          <div className="space-y-3">
            <h3 className="font-medium">保存到员工档案</h3>
            <Label>选择员工</Label>
            <Select value={saveEmployeeId} onChange={(e) => setSaveEmployeeId(e.target.value)}>
              <option value="">选择员工</option>
              {(employees || []).map((e: any) => <option key={e.id} value={e.id}>{e.name}（{e.department}）</option>)}
            </Select>
            <div className="flex gap-2 justify-end">
              <Button variant="secondary" size="sm" onClick={() => setShowSaveModal(false)}>取消</Button>
              <Button size="sm" onClick={handleSave} disabled={!saveEmployeeId}>保存</Button>
            </div>
          </div>
        </Modal>
      )}
    </div>
  )
}

function CaseTab() {
  const [scenario, setScenario] = useState('')
  const [result, setResult] = useState('')
  const [loading, setLoading] = useState(false)
  const [showSaveModal, setShowSaveModal] = useState(false)
  const [saveEmployeeId, setSaveEmployeeId] = useState('')
  const [showHistory, setShowHistory] = useState(false)
  const [showTodoModal, setShowTodoModal] = useState(false)
  const [todoEmployeeId, setTodoEmployeeId] = useState('')
  const [todoTitle, setTodoTitle] = useState('')
  const [todoLevel, setTodoLevel] = useState('MEDIUM')
  const [todoType, setTodoType] = useState('TERMINATION')
  const [creatingTodo, setCreatingTodo] = useState(false)
  const { history, saveMutation, deleteMutation, loadHistory } = useAIHistory('case')

  const { data: employees } = useQuery<any[]>({
    queryKey: ['roster-list'],
    queryFn: async () => {
      const res = await api.get('/roster') as any
      return res.data?.items || res.data || []
    },
  })

  const handleMatch = async () => {
    if (!scenario.trim()) return
    setLoading(true)
    setResult('')
    try {
      const res = await api.post('/ai/match-case', { scenario }) as any
      setResult(res.data.result)
      // 自动保存到历史
      if (res.data?.result && !res.data.result.startsWith('出错了')) {
        const title = scenario.slice(0, 30).replace(/\n/g, ' ')
        saveMutation.mutate({ title, input: scenario, result: res.data.result })
      }
    } catch (err: any) {
      setResult(`出错了：${err.response?.data?.error?.message || '请稍后重试'}`)
    } finally {
      setLoading(false)
    }
  }

  const handleLoadHistory = async (id: string) => {
    const data = await loadHistory(id)
    if (data?.messages) {
      const userMsg = data.messages.find((m: any) => m.role === 'user')
      const assistantMsg = data.messages.find((m: any) => m.role === 'assistant')
      if (userMsg) setScenario(userMsg.content)
      if (assistantMsg) setResult(assistantMsg.content)
      setShowHistory(false)
    }
  }

  const handleSave = async () => {
    if (!saveEmployeeId || !result) return
    try {
      await api.post('/ai/review/save', { employeeId: saveEmployeeId, type: 'CASE', input: scenario, result })
      setShowSaveModal(false)
      setSaveEmployeeId('')
      toast.success('已保存到员工档案')
    } catch (err: any) {
      toast.error('保存失败：' + (err.response?.data?.error?.message || '请稍后重试'))
    }
  }

  const handleCreateTodo = async () => {
    if (!todoEmployeeId || !todoTitle) return
    setCreatingTodo(true)
    try {
      await api.post('/ai/case-to-todo', {
        employeeId: todoEmployeeId,
        title: todoTitle,
        description: result.slice(0, 500),
        level: todoLevel,
        type: todoType,
      })
      setShowTodoModal(false)
      setTodoEmployeeId('')
      setTodoTitle('')
      toast.success('已创建待办风险项')
    } catch (err: any) {
      toast.error('创建失败：' + (err.response?.data?.error?.message || '请稍后重试'))
    } finally {
      setCreatingTodo(false)
    }
  }

  return (
    <div className="space-y-4">
      <Card>
        <div className="flex items-center gap-2 mb-4">
          <Scale className="w-5 h-5 text-primary" />
          <h2 className="text-sm font-medium">案例匹配</h2>
          <Button size="sm" variant="secondary" className="ml-auto" onClick={() => setShowHistory(!showHistory)}><History className="w-4 h-4 mr-1" />历史记录</Button>
        </div>

        {showHistory && (
          <div className="mt-2 mb-3">
            <HistoryBar history={history || []} onLoad={handleLoadHistory} onDelete={(id) => deleteMutation.mutate(id)} />
          </div>
        )}
        <div className="mt-3">
        <Label>描述你的争议情形</Label>
        <textarea
          className="w-full px-3 py-2 rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent text-xs min-h-[150px] resize-y"
          placeholder="例如：员工入职3个月没签合同，现在要辞退他..."
          value={scenario}
          onChange={(e) => setScenario(e.target.value)}
        />
        <div className="mt-3">
          <Button onClick={handleMatch} disabled={loading || !scenario.trim()}>
            {loading ? <><Loader2 className="w-4 h-4 animate-spin mr-1" />分析中...</> : '分析'}
          </Button>
        </div>
        </div>
      </Card>

      {result && (
        <Card>
          <div className="flex items-center justify-between mb-3">
            <h3 className="font-medium">分析结果</h3>
            <div className="flex gap-2">
              <Button size="sm" variant="secondary" onClick={() => setShowTodoModal(true)}><Plus className="w-4 h-4 mr-1" />转待办</Button>
              <Button size="sm" variant="secondary" onClick={() => setShowSaveModal(true)}><Save className="w-4 h-4 mr-1" />保存到员工档案</Button>
            </div>
          </div>
          <div className="text-xs text-gray-700 whitespace-pre-wrap">{result}</div>
        </Card>
      )}

      {showSaveModal && (
        <Modal open onClose={() => setShowSaveModal(false)} size="sm">
          <div className="space-y-3">
            <h3 className="font-medium">保存到员工档案</h3>
            <Label>选择员工</Label>
            <Select value={saveEmployeeId} onChange={(e) => setSaveEmployeeId(e.target.value)}>
              <option value="">选择员工</option>
              {(employees || []).map((e: any) => <option key={e.id} value={e.id}>{e.name}（{e.department}）</option>)}
            </Select>
            <div className="flex gap-2 justify-end">
              <Button variant="secondary" size="sm" onClick={() => setShowSaveModal(false)}>取消</Button>
              <Button size="sm" onClick={handleSave} disabled={!saveEmployeeId}>保存</Button>
            </div>
          </div>
        </Modal>
      )}

      {showTodoModal && (
        <Modal open onClose={() => setShowTodoModal(false)}>
          <div className="space-y-3">
            <h3 className="font-medium">转为待办风险项</h3>
            <div>
              <Label>选择员工</Label>
              <Select value={todoEmployeeId} onChange={(e) => setTodoEmployeeId(e.target.value)}>
                <option value="">选择员工</option>
                {(employees || []).map((e: any) => <option key={e.id} value={e.id}>{e.name}（{e.department}）</option>)}
              </Select>
            </div>
            <div>
              <Label>待办标题</Label>
              <Input value={todoTitle} onChange={(e) => setTodoTitle(e.target.value)} placeholder="如：未签合同风险处理" />
            </div>
            <div className="grid grid-cols-2 gap-3">
              <div>
                <Label>风险等级</Label>
                <Select value={todoLevel} onChange={(e) => setTodoLevel(e.target.value)}>
                  <option value="HIGH">高</option>
                  <option value="MEDIUM">中</option>
                  <option value="LOW">低</option>
                </Select>
              </div>
              <div>
                <Label>风险类型</Label>
                <Select value={todoType} onChange={(e) => setTodoType(e.target.value)}>
                  <option value="CONTRACT">合同</option>
                  <option value="SALARY">薪酬</option>
                  <option value="TERMINATION">解聘</option>
                  <option value="MONTHLY">月度</option>
                  <option value="ONBOARDING">入职</option>
                </Select>
              </div>
            </div>
            <div className="text-xs text-gray-400">分析结果将作为待办描述自动填入</div>
            <div className="flex gap-2 justify-end">
              <Button variant="secondary" size="sm" onClick={() => setShowTodoModal(false)}>取消</Button>
              <Button size="sm" onClick={handleCreateTodo} disabled={!todoEmployeeId || !todoTitle || creatingTodo}>
                {creatingTodo ? '创建中...' : '创建待办'}
              </Button>
            </div>
          </div>
        </Modal>
      )}
    </div>
  )
}

function KnowledgeTab() {
  const queryClient = useQueryClient()
  const [showAdd, setShowAdd] = useState(false)
  const [newItem, setNewItem] = useState({ title: '', content: '', source: '自定义', category: '其他' })
  const [adding, setAdding] = useState(false)

  const { data: knowledgeList, isLoading } = useQuery<any[]>({
    queryKey: ['rag-knowledge'],
    queryFn: async () => {
      const res = await api.get('/ai/rag/list') as any
      return res.data
    },
  })

  const addMutation = useMutation({
    mutationFn: async (data: typeof newItem) => {
      return await api.post('/ai/rag/add', data)
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['rag-knowledge'] })
      setShowAdd(false)
      setNewItem({ title: '', content: '', source: '自定义', category: '其他' })
    },
  })

  const deleteMutation = useMutation({
    mutationFn: (id: string) => api.delete(`/ai/rag/${id}`),
    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['rag-knowledge'] }),
  })

  const seedMutation = useMutation({
    mutationFn: () => api.post('/ai/rag/seed'),
    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['rag-knowledge'] }),
  })

  const handleAdd = async () => {
    if (!newItem.title || !newItem.content) return
    setAdding(true)
    try {
      await addMutation.mutateAsync(newItem)
    } finally {
      setAdding(false)
    }
  }

  return (
    <div className="space-y-3">
      <div className="flex items-center justify-between">
        <span className="text-xs text-gray-500">共 {knowledgeList?.length || 0} 条知识</span>
        <div className="flex gap-2">
          <Button variant="secondary" size="sm" onClick={() => seedMutation.mutate()} disabled={seedMutation.isPending}>
            {seedMutation.isPending ? '初始化中...' : '初始化知识库'}
          </Button>
          <Button size="sm" onClick={() => setShowAdd(true)}>
            <Plus className="w-4 h-4 mr-1" />添加知识
          </Button>
        </div>
      </div>

      {isLoading ? (
        <div className="text-center py-8 text-gray-400">加载中...</div>
      ) : !knowledgeList || knowledgeList.length === 0 ? (
        <Card><div className="text-center py-8 text-gray-400">知识库为空，请点击「初始化知识库」</div></Card>
      ) : (
        <div className="space-y-2">
          {knowledgeList.map((item: any) => (
            <Card key={item.id}>
              <div className="flex items-start justify-between gap-2">
                <div className="flex-1 min-w-0">
                  <div className="flex items-center gap-2 mb-1">
                    <span className="text-xs font-medium">{item.title}</span>
                    <span className="px-1.5 py-0.5 rounded bg-gray-100 text-gray-500 text-xs">{item.category}</span>
                  </div>
                  <p className="text-xs text-gray-500 line-clamp-2">{item.content}</p>
                  <div className="text-xs text-gray-400 mt-1">来源：{item.source}</div>
                </div>
                <button
                  onClick={() => deleteMutation.mutate(item.id)}
                  className="text-gray-400 hover:text-danger flex-shrink-0"
                >
                  <Trash2 className="w-4 h-4" />
                </button>
              </div>
            </Card>
          ))}
        </div>
      )}

      {showAdd && (
        <Modal open onClose={() => setShowAdd(false)}>
          <div className="space-y-3">
            <h3 className="font-medium">添加知识条目</h3>
            <div>
              <Label>标题</Label>
              <Input value={newItem.title} onChange={(e) => setNewItem({ ...newItem, title: e.target.value })} placeholder="如：劳动合同法第十条" />
            </div>
            <div>
              <Label>内容</Label>
              <textarea
                value={newItem.content}
                onChange={(e) => setNewItem({ ...newItem, content: e.target.value })}
                placeholder="法律条文或知识内容"
                rows={5}
                className="w-full px-3 py-2 rounded-md border border-gray-300 text-sm"
              />
            </div>
            <div className="grid grid-cols-2 gap-3">
              <div>
                <Label>来源</Label>
                <Input value={newItem.source} onChange={(e) => setNewItem({ ...newItem, source: e.target.value })} placeholder="如：劳动合同法" />
              </div>
              <div>
                <Label>分类</Label>
                <Select value={newItem.category} onChange={(e) => setNewItem({ ...newItem, category: e.target.value })}>
                  <option value="其他">其他</option>
                  <option value="法律法规">法律法规</option>
                  <option value="司法解释">司法解释</option>
                  <option value="地方性法规">地方性法规</option>
                  <option value="案例分析">案例分析</option>
                </Select>
              </div>
            </div>
            <div className="flex gap-2 justify-end">
              <Button variant="secondary" size="sm" onClick={() => setShowAdd(false)}>取消</Button>
              <Button size="sm" onClick={handleAdd} disabled={!newItem.title || !newItem.content || adding}>
                {adding ? '添加中...' : '添加'}
              </Button>
            </div>
          </div>
        </Modal>
      )}
    </div>
  )
}

function HRReportTab() {
  const [result, setResult] = useState('')
  const [loading, setLoading] = useState(false)
  const abortRef = useRef<AbortController | null>(null)

  const handleGenerate = async () => {
    if (loading) return
    abortRef.current?.abort()
    const controller = new AbortController()
    abortRef.current = controller

    setLoading(true)
    setResult('')

    try {
      const token = useAuthStore.getState().accessToken
      const url = import.meta.env.DEV
        ? `http://localhost:3000/api/v1/ai/hr-report-stream`
        : `/api/v1/ai/hr-report-stream`

      const response = await fetch(url, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json',
        },
        signal: controller.signal,
      })

      if (!response.ok) {
        const errData = await response.json().catch(() => null)
        throw new Error(errData?.error?.message || '请求失败')
      }

      const reader = response.body?.getReader()
      const decoder = new TextDecoder()
      let accumulated = ''
      let buffer = ''

      if (reader) {
        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: ')) {
              const data = line.slice(6).trim()
              if (data === '[DONE]') continue
              try {
                const parsed = JSON.parse(data)
                if (parsed.delta) {
                  accumulated += parsed.delta
                  setResult(accumulated)
                }
                if (parsed.error) {
                  throw new Error(parsed.error)
                }
              } catch (parseErr: any) {
                if (parseErr instanceof SyntaxError) continue
                throw parseErr
              }
            }
          }
        }
        setResult(accumulated)
      }
    } catch (err: any) {
      if (err.name !== 'AbortError') {
        toast.error(err.message || '生成报告失败')
      }
    } finally {
      setLoading(false)
    }
  }

  const handleExport = async () => {
    if (!result) return
    try {
      await exportMarkdownToWord(result, `人力分析报告_${new Date().toISOString().slice(0, 10)}.docx`)
      toast.success('Word 文档已导出')
    } catch {
      toast.error('导出失败')
    }
  }

  return (
    <div className="space-y-3">
      <Card>
        <div className="flex items-center justify-between mb-3">
          <div>
            <h2 className="text-sm font-medium flex items-center gap-1.5">
              <TrendingUp className="w-4 h-4 text-primary" />
              AI 人力分析报告
            </h2>
            <p className="text-xs text-gray-500 mt-1">基于企业实际数据自动生成：人力概况、风险提示、成本分析、合规建议、改进方向</p>
          </div>
          <div className="flex items-center gap-2">
            {result && !loading && (
              <button
                onClick={handleExport}
                className="flex items-center gap-1 text-xs text-primary hover:text-primary/80 transition-colors"
              >
                <Download className="w-3.5 h-3.5" />
                导出 Word
              </button>
            )}
            <Button size="sm" onClick={handleGenerate} disabled={loading}>
              {loading ? (
                <><Loader2 className="w-4 h-4 mr-1 animate-spin" />生成中...</>
              ) : (
                <><Sparkles className="w-4 h-4 mr-1" />生成报告</>
              )}
            </Button>
          </div>
        </div>

        {!result && !loading && (
          <div className="text-center py-12 text-gray-400">
            <TrendingUp className="w-12 h-12 mx-auto mb-3 text-gray-300" />
            <p className="text-sm">点击"生成报告"，AI 将基于企业当前数据自动生成结构化人力分析报告</p>
          </div>
        )}

        {loading && !result && (
          <div className="text-center py-12">
            <Loader2 className="w-8 h-8 mx-auto mb-3 text-primary animate-spin" />
            <p className="text-sm text-gray-500">AI 正在分析企业数据并生成报告...</p>
          </div>
        )}

        {result && (
          <div className="prose prose-sm max-w-none
            prose-headings:text-gray-800 prose-headings:font-semibold
            prose-h1:text-lg prose-h1:border-b prose-h1:pb-2 prose-h1:border-gray-200
            prose-h2:text-base prose-h2:mt-4
            prose-h3:text-sm prose-h3:mt-3
            prose-p:text-gray-600 prose-p:leading-relaxed
            prose-li:text-gray-600 prose-li:leading-relaxed
            prose-strong:text-gray-800
            prose-code:text-pink-600 prose-code:bg-gray-100 prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:text-xs prose-code:before:content-none prose-code:after:content-none
            prose-pre:bg-gray-900 prose-pre:text-gray-100 prose-pre:rounded-lg prose-pre:p-3 prose-pre:my-3
            prose-blockquote:border-l-primary prose-blockquote:bg-primary/5 prose-blockquote:py-1 prose-blockquote:px-3 prose-blockquote:rounded-r prose-blockquote:not-italic
            prose-table:text-xs prose-table:border-collapse
            prose-th:bg-gray-50 prose-th:px-3 prose-th:py-1.5 prose-th:font-semibold prose-th:border prose-th:border-gray-200
            prose-td:px-3 prose-td:py-1.5 prose-td:border prose-td:border-gray-200
            prose-a:text-primary prose-a:no-underline hover:prose-a:underline
          ">
            <ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]}>
              {result}
            </ReactMarkdown>
          </div>
        )}
      </Card>
    </div>
  )
}
