import { useEffect, useRef, useState } from 'react'
import { Navigate, useSearchParams } from 'react-router-dom'
import { CheckCircle2, Clock, FileArchive, Loader2, Rocket, Send, Sparkles } from 'lucide-react'
import { useAuth } from '../contexts/AuthContext.jsx'
import { useCategories } from '../contexts/CategoryContext.jsx'
import { useFiles } from '../contexts/FilesContext.jsx'
import { useChatOverlay } from '../contexts/ChatOverlayContext.jsx'
import { API_BASE, createSkillApi, getAuthHeaders, updateSkillApi, uploadPackage } from '../services/api.js'
import { runSkillRunStreamWithReconnect } from '../services/skillRunStream.js'
import { createRuntimeTimelineState, reduceRuntimeTimeline } from '../services/runtimeTimeline.js'
import { buildSkillPackageBlob, safeSkillPackageFilename } from '../services/skillPackage.js'
import { buildSkillUploadPlan, deriveSkillDescriptionFromEntries } from '../services/skillUploadPlan.js'
import { fetchGeneratedPackageEntries } from '../services/generatedPackageFiles.js'
import { SimpleMarkdown } from '../components/EvaluationPanel.jsx'
import { FilesDownloadBox, LimitReachedBox, ToolCallLine, ToolResultLine } from '../components/AgentEventLine.jsx'
import PreviewPanel from '../components/PreviewPanel.jsx'
import HistoryDrawer from '../components/HistoryDrawer.jsx'
import { useConversationHistory } from '../hooks/useConversationHistory.js'
import NodePickerModal, { getNodePath } from '../components/NodePickerModal.jsx'
import RuntimeTimeline from '../components/RuntimeTimeline.jsx'

const SUPER_ADMIN_EMAIL = '494161546@qq.com'
const SUPER_ADMIN_PHONE = '13136092523'

const WELCOME_MESSAGE = `你好！我是 AI Skill 创建助手。

把你想完成的任务直接发给我。我会把请求原样交给当前配置的模型或智能体运行时，由它直接执行并返回结果。

生成完成后，页面只会提供一次“一键创建并立即发布 Skill”确认。`

function buildSourceWelcome(file, nodePath) {
  if (!file) return WELCOME_MESSAGE
  return `我已拿到你选择的流程文件，会连同你的请求一起直接交给当前配置的智能体运行时。

**流程文件**：${file.name}
**所属架构**：${nodePath || '未绑定流程节点'}
**文件描述**：${file.description || file.summary || '暂无描述'}

请直接告诉我需要创建什么 Skill。`
}

export default function CreateSkillChat({ overlayMode = false, overlaySourceFileId = null }) {
  const { user } = useAuth()
  const [searchParams] = useSearchParams()
  const { closeOverlay } = useChatOverlay()
  const { findFile } = useFiles()
  const { flat } = useCategories()
  const isSuperAdmin = user?.email === SUPER_ADMIN_EMAIL || user?.phone === SUPER_ADMIN_PHONE
  const isAdmin = user?.role === 'admin' || isSuperAdmin

  const sourceFileId = overlaySourceFileId || searchParams.get('sourceFile')
  const sourceFile = sourceFileId ? findFile(sourceFileId) : null
  const sourceFilePath = sourceFile ? getNodePath(sourceFile.category_id, flat) : ''

  const [messages, setMessages] = useState([
    { role: 'assistant', content: buildSourceWelcome(sourceFile, sourceFilePath) },
  ])
  const [input, setInput] = useState('')
  const [isLoading, setIsLoading] = useState(false)
  const [streamTip, setStreamTip] = useState('')
  const [sessionId, setSessionId] = useState(null)
  const [previewUrl, setPreviewUrl] = useState(null)
  const [previewName, setPreviewName] = useState('')
  const [selectedNodeId, setSelectedNodeId] = useState(sourceFile?.category_id || null)
  const [showNodePicker, setShowNodePicker] = useState(false)
  const [pendingPublishCardId, setPendingPublishCardId] = useState(null)
  const [engineReady, setEngineReady] = useState(false)
  const [engineOk, setEngineOk] = useState(true)
  const [runtimeTimeline, setRuntimeTimeline] = useState(createRuntimeTimelineState)
  const [latestPublishResult, setLatestPublishResult] = useState(null)

  const history = useConversationHistory('create', user)
  const scrollRef = useRef(null)
  const sessionIdRef = useRef(null)
  const actionSeqRef = useRef(0)
  const prevLoadingRef = useRef(false)

  useEffect(() => {
    const authHeaders = getAuthHeaders()
    fetch(`${API_BASE}/skill-run`, { headers: authHeaders })
      .then(response => response.json())
      .then(data => setEngineOk(!!data?.hasEngine))
      .catch(() => setEngineOk(false))
      .finally(() => setEngineReady(true))
  }, [])

  useEffect(() => {
    if (sourceFile?.category_id) setSelectedNodeId(sourceFile.category_id)
  }, [sourceFile?.category_id])

  useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight
  }, [messages, runtimeTimeline])

  useEffect(() => {
    if (prevLoadingRef.current && !isLoading) {
      history.save(messages, {
        skillName: 'AI 创建',
        sessionId: sessionIdRef.current,
      })
    }
    prevLoadingRef.current = isLoading
  }, [isLoading, messages])

  if (!overlayMode && !isAdmin) return <Navigate to="/" replace />

  function creatorName() {
    return user?.name || user?.email || user?.phone || '用户'
  }

  function currentNodeId() {
    return sourceFile?.category_id || selectedNodeId || null
  }

  function updatePublishCard(cardId, patch) {
    setMessages(previous => previous.map(message => {
      if (message.role !== 'publish_card' || message.id !== cardId) return message
      return {
        ...message,
        ...patch,
        fields: patch.fields ? { ...(message.fields || {}), ...patch.fields } : message.fields,
      }
    }))
  }

  function appendPublishCard({ text, entries, requestText }) {
    const nodeId = currentNodeId()
    const nodePath = nodeId ? getNodePath(nodeId, flat) || sourceFilePath : ''
    const conversation = [
      ...messages.filter(message => (
        (message.role === 'user' || message.role === 'assistant') &&
        message.content &&
        !message.isStreaming
      )),
      { role: 'user', content: requestText },
      { role: 'assistant', content: text },
    ]
    const plan = buildSkillUploadPlan({
      messages: conversation,
      entries: entries.length > 0 ? entries : undefined,
      description: text,
      nodeId,
      nodePath,
      creatorName: creatorName(),
      sourceFile,
      sourceFilePath,
    })
    const card = {
      role: 'publish_card',
      id: `publish_${Date.now().toString(36)}_${++actionSeqRef.current}`,
      status: 'pending',
      fields: {
        name: plan.name || 'AI 创建 Skill',
        description: plan.description || text.slice(0, 180),
        runtimeText: text,
        entries: Array.isArray(entries) ? entries : [],
        nodeId,
        nodePath,
        creatorName: creatorName(),
        visibility: 'public',
      },
    }
    setMessages(previous => [
      ...previous.map(message => (
        message.role === 'publish_card' && message.status === 'pending'
          ? { ...message, status: 'superseded' }
          : message
      )),
      card,
    ])
    return card
  }

  async function publishSkillCard(card, explicitNodeId = null) {
    const fields = card.fields || {}
    const nodeId = explicitNodeId || fields.nodeId || currentNodeId()
    if (!nodeId) {
      setPendingPublishCardId(card.id)
      setShowNodePicker(true)
      return
    }

    const nodePath = getNodePath(nodeId, flat) || fields.nodePath || sourceFilePath
    const runtimeText = String(fields.runtimeText || '').trim()
    const entries = Array.isArray(fields.entries) ? fields.entries : []
    const name = String(fields.name || 'AI 创建 Skill').trim()
    const creator = String(fields.creatorName || creatorName()).trim()
    const description = entries.length
      ? deriveSkillDescriptionFromEntries(entries, fields.description || runtimeText)
      : runtimeText

    updatePublishCard(card.id, {
      status: 'running',
      message: '正在创建并发布 Skill…',
      fields: { nodeId, nodePath },
    })

    try {
      let packageMeta = {}
      if (entries.length > 0) {
        const blob = await buildSkillPackageBlob({ name, description: runtimeText, entries })
        const filename = safeSkillPackageFilename(name)
        const file = new File([blob], filename, { type: 'application/zip' })
        const uploaded = await uploadPackage(file)
        const result = uploaded?.data || uploaded
        if (!result?.r2_key) throw new Error('上传接口未返回 package_key')
        packageMeta = {
          package_key: result.r2_key,
          package_size: result.size ?? file.size,
          package_name: result.filename ?? filename,
        }
      }

      const saved = await createSkillApi({
        name,
        desc: description || runtimeText || name,
        node_id: nodeId,
        source: entries.length ? 'upload' : 'create',
        creator_name: creator,
        visibility: fields.visibility === 'private' ? 'private' : 'public',
        ...packageMeta,
      })
      if (!saved?.id) throw new Error('创建接口未返回 Skill ID')
      await updateSkillApi(saved.id, { status: 'published' })

      updatePublishCard(card.id, {
        status: 'done',
        message: `已创建并发布：${name}`,
        fields: { skillId: saved.id, nodeId, nodePath },
      })
    } catch (error) {
      updatePublishCard(card.id, {
        status: 'error',
        message: error?.friendlyMessage || error?.message || String(error),
      })
    }
  }

  async function doSendToAI(userText, options = {}) {
    setIsLoading(true)
    setStreamTip('')
    setRuntimeTimeline(createRuntimeTimelineState())
    setLatestPublishResult(null)

    const historyForApi = messages
      .filter(message => (
        (message.role === 'user' || message.role === 'assistant') &&
        message.content &&
        !message.isStreaming
      ))
      .map(message => ({ role: message.role, content: message.content }))
    historyForApi.push({ role: 'user', content: userText })

    setMessages(previous => [
      ...previous,
      { role: 'user', content: userText },
      { role: 'assistant', content: '', isStreaming: true },
    ])

    let currentBubble = ''
    let finalAssistantText = ''
    let lastRenderAt = 0
    let generatedFileSessionId = ''
    let generatedFiles = []

    function flushBubble(force = false) {
      const now = Date.now()
      if (!force && now - lastRenderAt < 33) return
      lastRenderAt = now
      const snapshot = currentBubble
      setMessages(previous => {
        const next = previous.slice()
        for (let index = next.length - 1; index >= 0; index -= 1) {
          if (next[index].role === 'assistant' && next[index].isStreaming) {
            next[index] = { ...next[index], content: snapshot }
            break
          }
        }
        return next
      })
    }

    function finishBubble() {
      flushBubble(true)
      setMessages(previous => {
        const next = previous.slice()
        for (let index = next.length - 1; index >= 0; index -= 1) {
          if (next[index].role === 'assistant' && next[index].isStreaming) {
            next[index] = { ...next[index], isStreaming: false }
            break
          }
        }
        return next
      })
    }

    function startBubble() {
      currentBubble = ''
      lastRenderAt = 0
      setMessages(previous => [...previous, { role: 'assistant', content: '', isStreaming: true }])
    }

    try {
      let streamError = ''
      await runSkillRunStreamWithReconnect({
        apiBase: API_BASE,
        authHeaders: getAuthHeaders(),
        body: {
          messages: historyForApi,
          sessionId: sessionIdRef.current || undefined,
          mode: options.mode || 'create',
          sourceFile: sourceFile ? {
            id: sourceFile.id,
            name: sourceFile.name,
            description: sourceFile.description || sourceFile.summary || '',
            content: sourceFile.content || '',
            node_id: sourceFile.category_id,
            node_path: sourceFilePath,
          } : undefined,
        },
        handlers: {
          onEvent: event => setRuntimeTimeline(previous => reduceRuntimeTimeline(previous, event)),
          onSession: sid => {
            if (!sid) return
            sessionIdRef.current = sid
            setSessionId(sid)
          },
          onResume: event => {
            if (event?.sessionId) {
              sessionIdRef.current = event.sessionId
              setSessionId(event.sessionId)
            }
            if (event?.replayed > 0) setStreamTip('连接已恢复，正在继续执行')
          },
          onReconnect: info => setStreamTip(`连接波动，正在第 ${info.attempt} 次重连`),
          onHeartbeat: () => {},
          onDelta: value => {
            finalAssistantText += value
            currentBubble += value
            flushBubble(false)
          },
          onToolCall: (name, args) => {
            finishBubble()
          },
          onToolResult: (name, result) => {
            startBubble()
          },
          onFiles: (sid, files) => {
            generatedFileSessionId = sid || sessionIdRef.current || ''
            generatedFiles = Array.isArray(files) ? files : []
          },
          onLimitReached: message => {
            finishBubble()
            setMessages(previous => [...previous, { role: 'limit_reached', content: message }])
          },
          onError: message => { streamError = message || 'AI 服务错误' },
        },
      })

      if (streamError) throw new Error(streamError)
      finishBubble()
      finalAssistantText = finalAssistantText.trim()
      const generatedEntries = generatedFiles.length > 0
        ? await fetchGeneratedPackageEntries({
          sessionId: generatedFileSessionId || sessionIdRef.current,
          files: generatedFiles,
        })
        : []

      setLatestPublishResult({
        text: finalAssistantText,
        entries: generatedEntries.length > 0 ? generatedEntries : [],
        requestText: userText,
      })
      setStreamTip('')
      return { ok: true, text: finalAssistantText, generatedEntries }
    } catch (error) {
      const message = error?.message || String(error)
      setStreamTip(`连接失败：${message}`)
      setMessages(previous => {
        const next = previous.slice()
        for (let index = next.length - 1; index >= 0; index -= 1) {
          if (next[index].role === 'assistant' && next[index].isStreaming) {
            next[index] = { role: 'assistant', content: `❌ 请求失败：${message}`, isStreaming: false }
            return next
          }
        }
        return [...next, { role: 'assistant', content: `❌ 请求失败：${message}` }]
      })
      return { ok: false, text: '', generatedEntries: [] }
    } finally {
      setIsLoading(false)
    }
  }

  async function handleSend() {
    const t = input.trim()
    if (!t || isLoading) return
    setInput('')
    await doSendToAI(t, { mode: 'create' })
  }

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

  function handleContinue() {
    if (!isLoading) doSendToAI('继续执行上面未完成的任务', { mode: 'create' })
  }

  function handlePublishLatestResult() {
    if (!latestPublishResult || isLoading) return
    const card = appendPublishCard(latestPublishResult)
    setLatestPublishResult(null)
    publishSkillCard(card)
  }

  return (
    <div className="flex-1 flex flex-col h-full overflow-hidden">
      <div className={['flex items-center gap-2 h-10 border-b border-gray-200 flex-shrink-0 bg-white', overlayMode ? 'pl-12 pr-5' : 'px-5'].join(' ')}>
        <div className="w-6 h-6 rounded-md bg-gradient-to-br from-violet-500 to-indigo-600 grid place-items-center">
          <Sparkles size={13} className="text-white" />
        </div>
        <div className="flex-1 min-w-0 flex items-center gap-2">
          <h1 className="text-[14px] font-semibold text-gray-900 truncate">AI 辅助创建 Skill</h1>
          <span className="hidden sm:inline text-[12px] text-gray-500 truncate">直连当前配置的模型与智能体运行时</span>
        </div>
        <button
          type="button"
          onClick={() => history.setShowHistory(true)}
          className="w-7 h-7 rounded-md border border-gray-200 bg-white text-gray-500 hover:text-brand-600 hover:border-brand-200 hover:bg-brand-50 grid place-items-center transition"
          title="历史会话"
        >
          <Clock size={14} />
        </button>
      </div>

      {engineReady && !engineOk && (
        <div className="px-6 py-2.5 bg-amber-50 border-b border-amber-200 text-[12px] text-amber-700">
          当前运行时状态检查未通过；你仍可直接发送请求，服务端会返回真实配置或连接错误。
        </div>
      )}

      {sourceFile && (
        <div className="border-b border-emerald-100 bg-emerald-50 px-6 py-2.5 text-[12px] text-emerald-800">
          当前携带流程文件：<span className="font-medium">{sourceFile.name}</span>
          {sourceFilePath && <span className="ml-2 text-emerald-700">{sourceFilePath}</span>}
        </div>
      )}

      {streamTip && (
        <div className="border-b border-sky-100 bg-sky-50 px-6 py-2 text-[12px] text-sky-700">{streamTip}</div>
      )}

      <div ref={scrollRef} className="flex-1 overflow-y-auto px-6 py-5 space-y-3">
        {messages.map((message, index) => {
          if (message.role === 'tool_call') return <ToolCallLine key={index} name={message.name} args={message.args} />
          if (message.role === 'tool_result') {
            return (
              <ToolResultLine
                key={index}
                name={message.name}
                result={message.result}
                sessionId={message.sessionId}
                onPreview={(url, filename) => {
                  setPreviewUrl(url)
                  setPreviewName(filename || '')
                }}
              />
            )
          }
          if (message.role === 'files') {
            return (
              <FilesDownloadBox
                key={index}
                sessionId={message.sessionId}
                files={message.files}
                onPreview={(url, filename) => {
                  setPreviewUrl(url)
                  setPreviewName(filename || '')
                }}
              />
            )
          }
          if (message.role === 'limit_reached') {
            return <LimitReachedBox key={index} message={message.content} onContinue={handleContinue} disabled={isLoading} />
          }
          if (message.role === 'publish_card') {
            return (
              <PublishSkillCard
                key={message.id}
                card={message}
                onChange={(field, value) => updatePublishCard(message.id, { fields: { [field]: value } })}
                onChooseNode={() => {
                  setPendingPublishCardId(message.id)
                  setShowNodePicker(true)
                }}
                onPublish={() => publishSkillCard(message)}
              />
            )
          }
          if (message.role === 'system') {
            return <div key={index} className="text-center text-[11px] text-gray-400 italic py-1">{message.content}</div>
          }
          if (message.role === 'user') {
            return (
              <div key={index} 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">
                  {message.content}
                </div>
              </div>
            )
          }
          if (message.isStreaming && !message.content) return null
          return (
            <div key={index} 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]">
                {message.content ? <SimpleMarkdown text={message.content} /> : <span className="text-gray-400 text-[12px]">思考中…</span>}
                {message.isStreaming && <span className="inline-block w-1.5 h-3.5 bg-brand-500 ml-0.5 align-middle animate-pulse" />}
              </div>
            </div>
          )
        })}
        <RuntimeTimeline
          timeline={runtimeTimeline}
          isRunning={isLoading}
          sessionId={sessionId || ''}
          onPreview={(url, filename) => {
            setPreviewUrl(url)
            setPreviewName(filename || '')
          }}
        />
      </div>

      {latestPublishResult && !isLoading && (
        <div className="border-t border-violet-100 bg-violet-50/60 px-6 py-2.5 flex items-center gap-3">
          <div className="min-w-0 flex-1">
            <div className="text-[12px] font-medium text-violet-900">结果已返回，可继续追问，也可直接发布</div>
            <div className="text-[11px] text-violet-600">发布只负责创建、归位和上架，不会重新生成或拦截结果。</div>
          </div>
          <button
            type="button"
            onClick={handlePublishLatestResult}
            className="inline-flex flex-shrink-0 items-center gap-1.5 rounded-lg bg-violet-600 px-3.5 py-2 text-[12px] font-medium text-white hover:bg-violet-700"
          >
            <Rocket size={14} /> 一键创建并立即发布 Skill
          </button>
        </div>
      )}

      <div className="border-t border-gray-200 px-6 py-3 flex items-end gap-3 flex-shrink-0 bg-white">
        <textarea
          rows={2}
          value={input}
          onChange={event => setInput(event.target.value)}
          onKeyDown={handleKeyDown}
          placeholder={isLoading ? '运行时执行中…' : '直接描述要交给模型或智能体完成的任务…'}
          disabled={isLoading}
          className="flex-1 px-3 py-2 text-[13px] border border-gray-200 rounded-lg focus:outline-none focus:border-brand-400 resize-none disabled:bg-gray-50"
        />
        <button
          type="button"
          onClick={handleSend}
          disabled={isLoading || !input.trim()}
          className="px-4 py-2 rounded-lg text-white bg-brand-600 hover:bg-brand-700 disabled:opacity-50 disabled:cursor-not-allowed flex-shrink-0 transition"
        >
          <Send size={16} />
        </button>
      </div>

      <HistoryDrawer
        open={history.showHistory}
        onClose={() => history.setShowHistory(false)}
        conversations={history.conversations}
        onSelect={conversation => {
          const loaded = history.load(conversation)
          setMessages(loaded.messages || [])
          if (loaded.sessionId) {
            sessionIdRef.current = loaded.sessionId
            setSessionId(loaded.sessionId)
          }
        }}
        onDelete={conversation => history.remove(conversation)}
      />

      <NodePickerModal
        open={showNodePicker}
        initialNodeId={selectedNodeId}
        onClose={() => {
          setShowNodePicker(false)
          setPendingPublishCardId(null)
        }}
        onConfirm={nodeId => {
          setSelectedNodeId(nodeId)
          setShowNodePicker(false)
          const card = messages.find(message => message.role === 'publish_card' && message.id === pendingPublishCardId)
          setPendingPublishCardId(null)
          if (card) publishSkillCard({ ...card, fields: { ...(card.fields || {}), nodeId } }, nodeId)
        }}
      />

      <PreviewPanel
        url={previewUrl}
        filename={previewName}
        visible={!!previewUrl}
        onClose={() => {
          setPreviewUrl(null)
          setPreviewName('')
        }}
      />
    </div>
  )
}

function PublishSkillCard({ card, onChange, onChooseNode, onPublish }) {
  const fields = card.fields || {}
  const isRunning = card.status === 'running'
  const isDone = card.status === 'done'
  const isSuperseded = card.status === 'superseded'
  const disabled = isRunning || isDone || isSuperseded

  return (
    <div className="flex justify-start">
      <div className="w-full max-w-[720px] rounded-xl border border-violet-200 bg-white shadow-sm overflow-hidden">
        <div className="px-4 py-3 border-b border-violet-100 bg-violet-50/70 flex items-center gap-3">
          <div className="w-8 h-8 rounded-lg bg-violet-100 text-violet-700 grid place-items-center">
            {isRunning ? <Loader2 size={17} className="animate-spin" /> : isDone ? <CheckCircle2 size={17} /> : <Rocket size={16} />}
          </div>
          <div className="min-w-0 flex-1">
            <div className="text-[13px] font-semibold text-gray-900">运行时已返回结果</div>
            <div className="text-[11px] text-gray-500">确认后平台只负责创建、归位并立即发布</div>
          </div>
          {fields.entries?.length > 0 && (
            <span className="inline-flex items-center gap-1 text-[11px] text-violet-700">
              <FileArchive size={13} /> {fields.entries.length} 个文件
            </span>
          )}
        </div>

        <div className="p-4 space-y-3">
          <label className="block">
            <span className="block text-[12px] text-gray-600 mb-1">Skill 名称</span>
            <input
              value={fields.name || ''}
              disabled={disabled}
              onChange={event => onChange('name', event.target.value)}
              className="w-full h-9 px-3 text-[13px] border border-gray-200 rounded-lg focus:outline-none focus:border-brand-400 disabled:bg-gray-50"
            />
          </label>

          <div className="grid grid-cols-[1fr_160px] gap-3">
            <div>
              <span className="block text-[12px] text-gray-600 mb-1">流程节点</span>
              <button
                type="button"
                disabled={disabled}
                onClick={onChooseNode}
                className="w-full h-9 px-3 text-left text-[13px] rounded-lg border border-gray-200 bg-white hover:bg-gray-50 disabled:bg-gray-50"
              >
                <span className="block truncate">{fields.nodePath || '点击选择发布节点'}</span>
              </button>
            </div>
            <label className="block">
              <span className="block text-[12px] text-gray-600 mb-1">可见性</span>
              <select
                value={fields.visibility || 'public'}
                disabled={disabled}
                onChange={event => onChange('visibility', event.target.value)}
                className="w-full h-9 px-3 text-[13px] border border-gray-200 rounded-lg bg-white focus:outline-none focus:border-brand-400 disabled:bg-gray-50"
              >
                <option value="public">公开发布</option>
                <option value="private">私密发布</option>
              </select>
            </label>
          </div>

          {card.message && (
            <div className={[
              'text-[12px] rounded-lg px-3 py-2 border',
              card.status === 'error'
                ? 'bg-rose-50 text-rose-700 border-rose-100'
                : 'bg-emerald-50 text-emerald-700 border-emerald-100',
            ].join(' ')}>
              {card.message}
            </div>
          )}
        </div>

        <div className="px-4 py-3 border-t border-gray-100 bg-gray-50/60 flex justify-end">
          <button
            type="button"
            onClick={onPublish}
            disabled={disabled || !String(fields.name || '').trim()}
            className="inline-flex items-center gap-1.5 px-4 py-2 text-[13px] rounded-lg bg-brand-600 text-white hover:bg-brand-700 disabled:bg-gray-200 disabled:text-gray-400 disabled:cursor-not-allowed"
          >
            {isRunning ? <Loader2 size={14} className="animate-spin" /> : isDone ? <CheckCircle2 size={14} /> : <Rocket size={14} />}
            {isRunning ? '正在创建并发布' : isDone ? '已创建并发布' : isSuperseded ? '已有更新结果' : '一键创建并立即发布 Skill'}
          </button>
        </div>
      </div>
    </div>
  )
}
