import { useEffect, useRef, useState } from 'react'
import JSZip from 'jszip'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import { Zap } from 'lucide-react'
import { downloadSkillPackage, getAuthHeaders, API_BASE } from '../services/api.js'
import { runSkillRunStreamWithReconnect } from '../services/skillRunStream.js'
import { createRuntimeTimelineState, reduceRuntimeTimeline } from '../services/runtimeTimeline.js'
import { ToolCallLine, ToolResultLine, FilesDownloadBox } from './AgentEventLine.jsx'
import PreviewPanel from './PreviewPanel.jsx'
import { useChatOverlay } from '../contexts/ChatOverlayContext.jsx'
import RuntimeTimeline from './RuntimeTimeline.jsx'

// 从 zip 里提取主 .md
async function extractMdFromZip(blob) {
  let zip
  try {
    zip = await JSZip.loadAsync(blob)
  } catch {
    const text = await blob.text()
    return text.trim() ? { text, mainPath: 'SKILL.md' } : null
  }
  const entries = []
  zip.forEach((path, entry) => {
    if (entry.dir) return
    if (path.startsWith('__MACOSX/')) return
    if (/\.(md|markdown)$/i.test(path)) entries.push({ path, entry })
  })
  if (!entries.length) return null
  const score = (p) => {
    const base = p.split('/').pop().toLowerCase()
    if (base === 'skill.md') return 0
    if (base === 'skill.markdown') return 1
    if (base === 'readme.md') return 2
    if (/\.md$/i.test(base)) return 3
    return 4
  }
  entries.sort((a, b) => score(a.path) - score(b.path) || a.path.length - b.path.length)
  const main = entries[0]
  const text = await main.entry.async('string')
  return { text, mainPath: main.path }
}

export default function EvaluationPanel({ skill, onClose, onAdopted }) {
  const { openOverlay } = useChatOverlay()
  const [messages, setMessages] = useState([])
  const [input, setInput] = useState('')
  const [isLoading, setIsLoading] = useState(false)
  const [hasResult, setHasResult] = useState(false)
  const [isAdopting, setIsAdopting] = useState(false)
  const [skillContent, setSkillContent] = useState('')
  const [mdFilename, setMdFilename] = useState('SKILL.md')
  const [runtimeTimeline, setRuntimeTimeline] = useState(createRuntimeTimelineState)

  // Skill 执行引擎状态
  const [engineConfig, setEngineConfig] = useState(null)
  const [engineReady, setEngineReady] = useState(false)
  // 评测 system prompt 由后端「系统 Skill / Skill 评测器」统一提供。
  const sessionPromptRef = useRef('')
  const sessionReadyRef = useRef(false)
  // Agent 会话 ID（首条 SSE 事件返回，后续多轮对话续接）
  const agentSessionIdRef = useRef(null)

  const scrollRef = useRef(null)
  const loadedSkillIdRef = useRef(null)

  // 右侧预览面板
  const [previewUrl, setPreviewUrl] = useState(null)
  const [previewName, setPreviewName] = useState('')
  const handlePreview = (url, filename) => {
    setPreviewUrl(url)
    setPreviewName(filename || '')
  }
  const handleClosePreview = () => {
    setPreviewUrl(null)
    setPreviewName('')
  }

  // 滚到底
  useEffect(() => {
    const el = scrollRef.current
    if (el) el.scrollTop = el.scrollHeight
  }, [messages, runtimeTimeline])

  function addSystemMsg(text) {
    setMessages(prev => [...prev, { role: 'system', content: text }])
  }

  // 1. 检查 Skill 执行引擎配置
  useEffect(() => {
    const authHeaders = getAuthHeaders()
    fetch(`${API_BASE}/skill-run`, { headers: authHeaders })
      .then(r => r.json())
      .then(data => {
        setEngineConfig(data)
        setEngineReady(true)
      })
      .catch(() => {
        setEngineConfig(null)
        setEngineReady(true)
      })
  }, [])

  // 2. 等引擎就绪后，加载 Skill + 首次评测
  useEffect(() => {
    if (!engineReady) return
    if (loadedSkillIdRef.current === skill?.id) return
    loadedSkillIdRef.current = skill?.id || null
    sessionPromptRef.current = ''
    sessionReadyRef.current = false
    agentSessionIdRef.current = null
    setMessages([])
    setInput('')
    setIsLoading(false)
    setHasResult(false)
    setIsAdopting(false)
    setSkillContent('')
    setMdFilename('SKILL.md')
    setPreviewUrl(null)
    setPreviewName('')
    ;(async () => {
      addSystemMsg('正在加载 Skill 内容…')
      let content = ''
      let filename = `${(skill?.name || 'SKILL').replace(/[^\w\u4e00-\u9fa5-]+/g, '_')}.md`
      if (skill?.package_key) {
        try {
          const blob = await downloadSkillPackage(skill.package_key)
          const r = await extractMdFromZip(blob)
          if (r) {
            content = r.text
            filename = r.mainPath.split('/').pop() || filename
          }
        } catch {}
      }
      if (!content) {
        content = `# ${skill?.name || '未命名 Skill'}\n\n${skill?.desc || skill?.description || '（无描述）'}`
      }
      setSkillContent(content)
      setMdFilename(filename)

      if (!skill?.package_key) {
        addSystemMsg('⚠ 当前 Skill 没有可评测的上传包文件，无法进行真实包评测。请先上传标准 Skill 包。')
        return
      }

      if (!engineConfig?.hasEngine) {
        addSystemMsg('⚠ 平台未配置 Skill 执行引擎，请管理员到「智能体配置 / 运行时注册」选择并启用运行时')
        return
      }

      // 后端会读取「智能体配置 / 系统 Skill / Skill 评测器」作为唯一评测系统提示词。
      sessionPromptRef.current = ''
      sessionReadyRef.current = true

      addSystemMsg(`已加载 Skill 包：${skill.package_name || skill.package_key}。正在调用系统 Skill 评测器真实读取包文件…`)
      const initialUserText = [
        '请评测当前会话目录中已解压的 Skill 包。',
        `Skill 名称：${skill?.name || '未命名'}`,
        `Skill ID：${skill?.id || '未知'}`,
        `包文件：${skill?.package_name || skill?.package_key}`,
        '请先调用 list_files 查看完整包结构，再用 read_file 阅读 SKILL.md、examples.md、rubric.md 等关键文件，最后给出评测报告。',
      ].join('\n')
      doSendToAI(initialUserText, true)
    })()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [engineReady, skill?.id])

  async function doSendToAI(userText, isInitial = false) {
    if (!sessionReadyRef.current) {
      addSystemMsg('⚠ Skill 执行引擎未就绪，无法发送消息')
      return
    }

    setIsLoading(true)
    setRuntimeTimeline(createRuntimeTimelineState())

    // 收集历史消息作为上下文（只取真正的对话角色，过滤工具事件 / 仍在 streaming 的空助手）
    const historyForApi = messages
      .filter(m => (m.role === 'user' || m.role === 'assistant') && m.content && !m.isStreaming)
      .map(m => ({ role: m.role, content: m.content }))
    historyForApi.push({ role: 'user', content: userText })

    setMessages(prev => {
      const next = [...prev]
      next.push({ role: 'user', content: userText })
      next.push({ role: 'assistant', content: '', isStreaming: true })
      return next
    })

    // 累积当前 assistant bubble 的文本（每次工具调用后清空，开新 bubble）
    let currentAcc = ''
    let lastRenderTs = 0

    function flushDelta(force = false) {
      const now = Date.now()
      if (!force && now - lastRenderTs < 33) return
      lastRenderTs = now
      const snap = currentAcc
      setMessages(prev => {
        const next = prev.slice()
        for (let i = next.length - 1; i >= 0; i--) {
          if (next[i].role === 'assistant' && next[i].isStreaming) {
            next[i] = { ...next[i], content: snap }
            break
          }
        }
        return next
      })
    }

    function finalizeCurrentBubble() {
      flushDelta(true)
      setMessages(prev => {
        const next = prev.slice()
        for (let i = next.length - 1; i >= 0; i--) {
          if (next[i].role === 'assistant' && next[i].isStreaming) {
            next[i] = { ...next[i], isStreaming: false }
            break
          }
        }
        return next
      })
      currentAcc = ''
    }

    function startNewAssistantBubble() {
      currentAcc = ''
      lastRenderTs = 0
      setMessages(prev => [...prev, { role: 'assistant', content: '', isStreaming: true }])
    }

    try {
      const authHeaders = getAuthHeaders()
      const bodyObj = {
        mode: 'evaluate',
        messages: historyForApi,
        sessionId: agentSessionIdRef.current || undefined,
      }
      // 首次请求时传 packageKey，后端会解压到 session 目录，让 AI 能看到包内所有文件
      if (!agentSessionIdRef.current && skill?.package_key) {
        bodyObj.packageKey = skill.package_key
      }
      let streamErr = null

      await runSkillRunStreamWithReconnect({
        apiBase: API_BASE,
        authHeaders,
        body: bodyObj,
        handlers: {
        onEvent: event => setRuntimeTimeline(previous => reduceRuntimeTimeline(previous, event)),
        onSession: (sid) => {
          if (sid) agentSessionIdRef.current = sid
        },
        onDelta: (v) => {
          currentAcc += v
          flushDelta(false)
        },
        onToolCall: (name, args) => {
          finalizeCurrentBubble()
        },
        onToolResult: (name, result) => {
          startNewAssistantBubble()
        },
        onFiles: () => {},
        onError: (msg) => {
          streamErr = msg
        },
        },
      })

      if (streamErr) throw new Error(streamErr)

      finalizeCurrentBubble()
      setHasResult(true)

    } catch (err) {
      const msg = err?.message || String(err)
      setMessages(prev => {
        const next = prev.slice()
        for (let i = next.length - 1; i >= 0; i--) {
          if (next[i].role === 'assistant' && next[i].isStreaming) {
            next[i] = { role: 'assistant', content: `❌ 请求失败：${msg}`, isStreaming: false }
            break
          }
        }
        return next
      })
    } finally {
      setIsLoading(false)
    }
  }

  function handleSend() {
    const t = input.trim()
    if (!t || isLoading) return
    setInput('')
    doSendToAI(t, false)
  }

  function handleKeyDown(e) {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault()
      handleSend()
    }
  }

  async function handleAdopt() {
    if (!agentSessionIdRef.current) {
      addSystemMsg('⚠ 会话未初始化，无法采纳。请先完成一轮评测。')
      return
    }
    if (isLoading || isAdopting) return

    const ok = window.confirm(
      '点击确认后，AI 将根据评测意见直接修改包内文件（包括 .md、附件、目录等），然后生成新版本。\n\n原 Skill 不会被覆盖。是否继续？'
    )
    if (!ok) return

    setIsAdopting(true)
    try {
      addSystemMsg('🔧 AI 正在根据评测意见修改包内文件…')

      // 1. 发送指令让 AI 直接修改文件（doSendToAI 内部 await consumeSkillRunStream，
      //    会等整个 SSE 流结束后才 resolve）
      await doSendToAI(
        '请根据以上评测意见，直接使用 write_file 工具修改对应文件。需要删除文件用 delete_file，需要新增文件用 write_file（支持子路径）。修改范围不限于 .md，可以修改任何文件。所有修改完成后，请回复「✅ 所有修改已完成」。',
        false
      )

      // 2. 调用 repack 端点获取改进后的完整 Skill 包
      addSystemMsg('📦 正在打包改进后的 Skill…')
      const authHeaders = getAuthHeaders()
      const repackResp = await fetch(
        `${API_BASE}/skill-run/sessions/${encodeURIComponent(agentSessionIdRef.current)}/repack`,
        { headers: authHeaders }
      )
      if (!repackResp.ok) {
        const errText = await repackResp.text().catch(() => '')
        throw new Error(`打包失败：HTTP ${repackResp.status} ${errText.slice(0, 200)}`)
      }
      const blob = await repackResp.blob()
      if (!blob || blob.size < 32) {
        throw new Error('打包返回为空，可能 AI 未修改任何文件')
      }

      const baseName = (skill?.name || 'skill').replace(/[^\w\u4e00-\u9fa5-]+/g, '_')
      const zipName = `${baseName}-improved.zip`
      addSystemMsg(`✅ 文件修改完成，新版本 ZIP 已生成（${(blob.size / 1024).toFixed(1)} KB）`)
      onAdopted?.(blob, zipName)
    } catch (e) {
      addSystemMsg('❌ 采纳失败：' + (e?.message || String(e)))
    } finally {
      setIsAdopting(false)
    }
  }

  return (
    <div className="fixed inset-0 z-50 bg-white flex flex-col">
      {/* Header */}
      <div className="flex items-center gap-2 px-4 py-2.5 border-b border-gray-200 flex-shrink-0">
        <span className="text-brand-600 text-[14px]">✓</span>
        <span className="text-[14px] font-semibold text-gray-900">Skill 评测</span>
        <span className="text-gray-300">·</span>
        <span className="text-[13px] text-gray-600 truncate min-w-0 flex-1">{skill?.name}</span>
        {engineConfig?.hasEngine && (
          <span className="px-2 py-0.5 text-[11px] rounded-full bg-blue-50 text-blue-600 border border-blue-100 flex-shrink-0 inline-flex items-center gap-1">
            <Zap size={11} strokeWidth={2.4} />
            {engineConfig?.provider?.name || 'Skill 引擎'}
          </span>
        )}
        <button
          onClick={() => skill?.id && openOverlay('sandbox', { skillId: skill.id })}
          className="px-3 py-1 text-[12px] rounded-md text-gray-600 border border-gray-200 hover:bg-gray-50 flex-shrink-0"
          title="在沙箱中运行此 Skill"
        >
          ▶ 运行
        </button>
        <button
          onClick={onClose}
          className="w-7 h-7 grid place-items-center rounded-md text-gray-500 hover:bg-gray-100 flex-shrink-0"
          title="关闭"
        >
          ✕
        </button>
      </div>

      {/* Skill 执行引擎未配置警告 */}
      {engineReady && !engineConfig?.hasEngine && (
        <div className="px-4 py-2 bg-amber-50 border-b border-amber-200 text-[12px] text-amber-700">
          ⚠ 平台未配置 Skill 执行引擎，请管理员到「智能体配置 / 运行时注册」选择并启用运行时
        </div>
      )}

      {/* Messages */}
      <div ref={scrollRef} className="flex-1 min-h-0 overflow-y-auto px-4 py-4 space-y-2.5">
        {messages.map((m, idx) => {
          if (m.role === 'tool_call') return <ToolCallLine key={idx} name={m.name} args={m.args} />
          if (m.role === 'tool_result') return <ToolResultLine key={idx} name={m.name} result={m.result} sessionId={m.sessionId} onPreview={handlePreview} />
          if (m.role === 'files') return <FilesDownloadBox key={idx} sessionId={m.sessionId} files={m.files} onPreview={handlePreview} />
          return <MessageBubble key={idx} m={m} />
        })}
        <RuntimeTimeline timeline={runtimeTimeline} isRunning={isLoading} sessionId={agentSessionIdRef.current || ''} onPreview={handlePreview} />
        {messages.length === 0 && (
          <div className="text-center text-[12px] text-gray-400 py-8">准备中…</div>
        )}
      </div>

      {/* Action bar */}
      {hasResult && !isLoading && (
        <div className="px-4 py-2.5 border-t border-gray-100 bg-gray-50/60 flex items-center gap-2 flex-shrink-0">
          <button
            onClick={handleAdopt}
            disabled={isAdopting}
            className="px-4 py-1.5 text-[13px] rounded-md text-white bg-brand-600 hover:bg-brand-700 disabled:opacity-50"
          >
            {isAdopting ? '改进中…' : '采纳并改进包'}
          </button>
          <button
            onClick={() => {
              setMessages([])
              setHasResult(false)
              loadedSkillIdRef.current = null
              agentSessionIdRef.current = null
              sessionReadyRef.current = false
              // 切换 engineReady 触发重新初始化
              setEngineReady(false)
              setTimeout(() => setEngineReady(true), 0)
            }}
            className="px-4 py-1.5 text-[13px] rounded-md text-gray-600 border border-gray-200 hover:bg-gray-50"
          >
            重新评测
          </button>
          <button
            onClick={onClose}
            className="px-4 py-1.5 text-[13px] rounded-md text-gray-600 border border-gray-200 hover:bg-gray-50"
          >
            放弃评测
          </button>
          <span className="text-[11px] text-gray-400 ml-2">采纳后将跳转至上传页，完成重新发布</span>
        </div>
      )}

      {/* Input */}
      <div className="border-t border-gray-200 px-4 py-3 flex items-end gap-2 flex-shrink-0">
        <textarea
          rows={2}
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyDown={handleKeyDown}
          placeholder={isLoading ? '生成中…' : '输入反馈或指令…（Enter 发送，Shift+Enter 换行）'}
          disabled={isLoading || !sessionReadyRef.current}
          className="flex-1 px-3 py-2 text-[13px] border border-gray-200 rounded-md focus:outline-none focus:border-brand-400 resize-none disabled:bg-gray-50"
        />
        <button
          onClick={handleSend}
          disabled={isLoading || !input.trim() || !sessionReadyRef.current}
          className="px-4 py-2 text-[13px] rounded-md text-white bg-brand-600 hover:bg-brand-700 disabled:opacity-50 disabled:cursor-not-allowed flex-shrink-0"
        >
          发送
        </button>
      </div>

      {/* 右侧预览面板 */}
      <PreviewPanel
        url={previewUrl}
        filename={previewName}
        visible={!!previewUrl}
        onClose={handleClosePreview}
      />
    </div>
  )
}

function MessageBubble({ m }) {
  if (m.role === 'system') {
    return <div className="text-center text-[11px] text-gray-400 italic py-0.5">{m.content}</div>
  }
  if (m.role === 'user') {
    return (
      <div className="flex justify-end">
        <div className="bg-brand-600 text-white rounded-xl rounded-tr-sm px-4 py-2.5 max-w-[70%] text-[13px] whitespace-pre-wrap break-words">
          {m.content}
        </div>
      </div>
    )
  }
  // 流式中且尚无任何文本：不渲染空 bubble（避免每轮工具调用后多出一个空气泡）
  if (m.isStreaming && !m.content) return null
  return (
    <div className="flex justify-start">
      <div className="bg-gray-50 border border-gray-200 rounded-xl rounded-tl-sm px-4 py-3 max-w-[85%] min-w-[60px]">
        {m.content
          ? <SimpleMarkdown text={m.content} />
          : <span className="text-gray-400 text-[12px]">思考中…</span>}
        {m.isStreaming && <span className="inline-block w-1.5 h-3.5 bg-brand-500 ml-0.5 align-middle animate-pulse" />}
        {!m.isStreaming && m.content && <DownloadButtons text={m.content} />}
      </div>
    </div>
  )
}

// 基于 react-markdown + remark-gfm 的渲染（支持表格、代码块、列表、加粗等 GFM 特性）
// 使用内联 components 样式，不依赖 Tailwind typography 插件，确保表格、代码块等在任何环境都能渲染
const MD_COMPONENTS = {
  table: ({ node, ...props }) => (
    <div style={{ overflowX: 'auto', margin: '8px 0' }}>
      <table
        style={{
          borderCollapse: 'collapse',
          width: '100%',
          fontSize: '12px',
          lineHeight: 1.5,
        }}
        {...props}
      />
    </div>
  ),
  thead: ({ node, ...props }) => <thead {...props} />,
  tbody: ({ node, ...props }) => <tbody {...props} />,
  tr: ({ node, ...props }) => <tr {...props} />,
  th: ({ node, ...props }) => (
    <th
      style={{
        border: '1px solid #d1d5db',
        padding: '6px 10px',
        background: '#f3f4f6',
        textAlign: 'left',
        fontWeight: 600,
      }}
      {...props}
    />
  ),
  td: ({ node, ...props }) => (
    <td
      style={{
        border: '1px solid #d1d5db',
        padding: '6px 10px',
        verticalAlign: 'top',
      }}
      {...props}
    />
  ),
  h1: ({ node, ...props }) => <h1 style={{ fontSize: '18px', fontWeight: 700, margin: '12px 0 8px' }} {...props} />,
  h2: ({ node, ...props }) => <h2 style={{ fontSize: '16px', fontWeight: 700, margin: '12px 0 6px' }} {...props} />,
  h3: ({ node, ...props }) => <h3 style={{ fontSize: '14px', fontWeight: 700, margin: '10px 0 6px' }} {...props} />,
  h4: ({ node, ...props }) => <h4 style={{ fontSize: '13px', fontWeight: 700, margin: '8px 0 4px' }} {...props} />,
  p: ({ node, ...props }) => <p style={{ margin: '6px 0' }} {...props} />,
  ul: ({ node, ...props }) => <ul style={{ margin: '6px 0', paddingLeft: '20px', listStyle: 'disc' }} {...props} />,
  ol: ({ node, ...props }) => <ol style={{ margin: '6px 0', paddingLeft: '20px', listStyle: 'decimal' }} {...props} />,
  li: ({ node, ...props }) => <li style={{ margin: '2px 0' }} {...props} />,
  blockquote: ({ node, ...props }) => (
    <blockquote
      style={{
        borderLeft: '3px solid #d1d5db',
        paddingLeft: '10px',
        color: '#4b5563',
        margin: '8px 0',
      }}
      {...props}
    />
  ),
  hr: () => <hr style={{ border: 0, borderTop: '1px solid #e5e7eb', margin: '12px 0' }} />,
  a: ({ node, ...props }) => <a style={{ color: '#4F46E5', textDecoration: 'underline' }} target="_blank" rel="noreferrer" {...props} />,
  code: ({ node, inline, className, children, ...props }) => {
    if (inline) {
      return (
        <code
          style={{
            background: '#f3f4f6',
            padding: '1px 5px',
            borderRadius: '3px',
            fontSize: '12px',
            fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',
          }}
          {...props}
        >
          {children}
        </code>
      )
    }
    return (
      <code
        style={{
          display: 'block',
          fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',
          fontSize: '12px',
          lineHeight: 1.55,
        }}
        {...props}
      >
        {children}
      </code>
    )
  },
  pre: ({ node, ...props }) => (
    <pre
      style={{
        background: '#f3f4f6',
        color: '#1f2937',
        borderRadius: '6px',
        padding: '10px 12px',
        margin: '8px 0',
        overflowX: 'auto',
        fontSize: '12px',
        lineHeight: 1.55,
      }}
      {...props}
    />
  ),
  img: ({ node, ...props }) => <img style={{ maxWidth: '100%', borderRadius: '4px', margin: '6px 0' }} {...props} />,
}

export function SimpleMarkdown({ text }) {
  return (
    <div
      style={{
        fontSize: '13px',
        lineHeight: 1.6,
        color: '#1f2937',
        wordBreak: 'break-word',
      }}
    >
      <ReactMarkdown remarkPlugins={[remarkGfm]} components={MD_COMPONENTS}>
        {text || ''}
      </ReactMarkdown>
    </div>
  )
}

// 从消息内容中提取可下载代码块（HTML / Markdown）
export function extractDownloadables(text) {
  if (!text) return []
  const out = []
  const re = /```(html|markdown|md)\s*\n([\s\S]*?)```/gi
  let m
  while ((m = re.exec(text)) !== null) {
    const lang = m[1].toLowerCase()
    if (lang === 'html') {
      out.push({ kind: 'html', content: m[2], filename: 'skill-report.html', mime: 'text/html' })
    } else if (lang === 'markdown' || lang === 'md') {
      out.push({ kind: 'markdown', content: m[2], filename: 'skill-report.md', mime: 'text/markdown' })
    }
  }
  // 同类型只保留第一个，避免重复按钮
  const seen = new Set()
  return out.filter(it => { if (seen.has(it.kind)) return false; seen.add(it.kind); return true })
}

export function DownloadButtons({ text }) {
  const items = extractDownloadables(text)
  if (!items.length) return null
  function download(item) {
    const blob = new Blob([item.content], { type: item.mime })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = item.filename
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    setTimeout(() => URL.revokeObjectURL(url), 0)
  }
  return (
    <div className="mt-2 flex flex-wrap gap-2">
      {items.map((item, i) => (
        <button
          key={i}
          onClick={() => download(item)}
          className="px-3 py-1 text-[12px] rounded-md border border-brand-200 text-brand-700 bg-brand-50 hover:bg-brand-100"
        >
          ⬇️ 下载 {item.kind === 'html' ? 'HTML 报告' : 'Markdown'}
        </button>
      ))}
    </div>
  )
}

// Settings 弹窗
export function SettingsModal({ settings = {}, engineConfig, onClose, onSave, showSystemPrompt = false }) {
  const [systemPrompt, setSystemPrompt] = useState(settings.systemPrompt || '')
  const isAgentRun = engineConfig?.engineKind === 'agentrun' || !!engineConfig?.agentRun
  const engineName = isAgentRun
    ? (engineConfig?.agentRun?.name || 'AgentRun')
    : (engineConfig?.provider?.name || 'Skill 执行引擎')
  const engineDetail = isAgentRun
    ? `AgentRun · ${engineConfig?.agentRun?.runtimeName || 'Runtime'} · ${engineConfig?.agentRun?.endpointName || 'Endpoint'}`
    : 'AgentRun 未配置'

  function submit() {
    onSave({ systemPrompt })
  }

  return (
    <div className="fixed inset-0 z-[60] bg-black/30 flex items-center justify-center p-4" onClick={onClose}>
      <div
        className="bg-white rounded-xl shadow-xl w-full max-w-lg max-h-[90vh] overflow-y-auto"
        onClick={(e) => e.stopPropagation()}
      >
        <div className="px-5 py-3 border-b border-gray-100 flex items-center justify-between">
          <div className="text-[14px] font-semibold text-gray-900">设置</div>
          <button onClick={onClose} className="text-gray-400 hover:text-gray-600">✕</button>
        </div>
        <div className="p-5 space-y-4">
          {/* Skill 执行引擎状态信息 */}
          {engineConfig?.hasEngine ? (
            <div className="rounded-lg bg-blue-50 border border-blue-100 px-4 py-3 flex items-center gap-3">
              <span className="flex-shrink-0 grid place-items-center w-8 h-8 rounded-md bg-blue-100 text-blue-600"><Zap size={18} strokeWidth={2.4} /></span>
              <div className="flex-1 min-w-0">
                <div className="text-sm font-medium text-blue-900">{engineName}</div>
                <div className="text-[11px] text-blue-500 mt-0.5">{engineDetail}</div>
              </div>
              <span className="text-[11px] text-emerald-600 font-medium flex-shrink-0">✓ 已就绪</span>
            </div>
          ) : (
            <div className="rounded-lg bg-amber-50 border border-amber-100 px-4 py-3 text-[13px] text-amber-700">
              ⚠ 平台未配置 Skill 执行引擎，请管理员到「智能体配置 / 运行时注册」选择并启用运行时
            </div>
          )}

          {showSystemPrompt && (
            <div>
              <label className="block text-[12px] text-gray-600 mb-1">评测 Agent 提示词</label>
              <textarea
                rows={8}
                value={systemPrompt}
                onChange={(e) => setSystemPrompt(e.target.value)}
                className="w-full px-3 py-2 text-[12px] border border-gray-200 rounded-md focus:outline-none focus:border-brand-400 font-mono resize-y"
              />
              <button
                onClick={() => setSystemPrompt('')}
                className="text-[11px] text-brand-600 hover:underline mt-1"
              >
                清空提示词
              </button>
            </div>
          )}
        </div>
        <div className="px-5 py-3 border-t border-gray-100 flex items-center justify-end gap-2">
          <button onClick={onClose} className="px-3.5 py-1.5 text-[13px] rounded-md text-gray-600 border border-gray-200 hover:bg-gray-50">取消</button>
          <button onClick={submit} className="px-3.5 py-1.5 text-[13px] rounded-md text-white bg-brand-600 hover:bg-brand-700">保存</button>
        </div>
      </div>
    </div>
  )
}
