<script setup>
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import {
  NButton, NInput, NSelect, NIcon, NSpin, NEmpty, NTag,
  useMessage
} from 'naive-ui'
import { SparklesOutline, ArrowForwardOutline, CopyOutline, ColorWandOutline } from '@vicons/ionicons5'
import {
  listGeneratorSkills,
  startSkillGeneration,
  buildSkillGenerationStreamUrl,
  refineSkillRequirement
} from '../../api/skill'
import { getModelList } from '../../api/model'

const router = useRouter()
const message = useMessage()

// ==================== 表单数据 ====================
const generators = ref([])
const models = ref([])
const loadingGenerators = ref(true)

const form = ref({
  generatorSkillFolder: '',
  name: '',
  description: '',
  requirement: '',
  modelId: null,
  maxIterations: 100
})

const generatorOptions = computed(() =>
  generators.value.map(g => ({
    label: g.displayName || g.name || g.folderName,
    value: g.folderName,
    description: g.description
  }))
)

const modelOptions = computed(() => [
  { label: '使用默认模型', value: null },
  ...models.value.map(m => ({ label: m.name || m.modelName, value: m.id }))
])

// ==================== 运行状态 ====================
const runId = ref('')
const stage = ref('')                // 当前阶段（RUNNING/EXECUTING/EXTRACTING/...）
const stageMessage = ref('')
const thinking = ref('')             // 累积的思考过程
const toolEvents = ref([])           // 工具调用事件
const status = ref('')               // CREATED/RUNNING/SUCCESS/FAILED
const errorMessage = ref('')
const generatedFolderName = ref('')
const finalText = ref('')
const isGenerating = ref(false)
const isRefining = ref(false)

const eventSource = ref(null)
const logContainer = ref(null)

// ==================== 加载数据 ====================
async function loadGenerators() {
  loadingGenerators.value = true
  try {
    const res = await listGeneratorSkills()
    generators.value = res.data || []
  } catch (e) {
    message.error('加载可生成技能列表失败')
  } finally {
    loadingGenerators.value = false
  }
}

async function loadModels() {
  try {
    const res = await getModelList()
    models.value = res.data || []
  } catch (e) {
    // 模型加载失败静默
  }
}

// ==================== 智能润色 ====================
async function handleRefine() {
  if (isRefining.value) return
  if (!form.value.requirement.trim()) {
    message.warning('请先输入需求描述')
    return
  }
  isRefining.value = true
  message.info('正在调用智能体进行规格化，通常需要 30-90 秒，请稍候...')
  try {
    const res = await refineSkillRequirement(form.value.requirement)
    const data = res.data || {}
    const status = data.status || ''
    const msg = data.message || ''
    const prompt = data.prompt || ''

    if (prompt) {
      form.value.requirement = prompt
    }
    if (status === 'failed') {
      message.error(msg || '润色失败')
    } else if (status === 'warning') {
      message.warning(msg || '润色返回警告，请复核')
    } else if (status === 'success') {
      message.success(msg || '已润色')
    } else {
      message.info('润色已完成')
    }
  } catch (e) {
    message.error(e.response?.data?.message || e.message || '润色失败')
  } finally {
    isRefining.value = false
  }
}

// ==================== 启动生成 ====================
async function handleGenerate() {
  if (!form.value.generatorSkillFolder) {
    message.warning('请选择用于生成的源技能')
    return
  }
  if (!form.value.name.trim()) {
    message.warning('请输入新技能名称')
    return
  }
  if (!form.value.requirement.trim()) {
    message.warning('请输入技能需求')
    return
  }
  if (isGenerating.value) return

  // 重置
  resetRunState()
  isGenerating.value = true

  try {
    const payload = {
      generatorSkillFolder: form.value.generatorSkillFolder,
      name: form.value.name.trim(),
      description: form.value.description.trim(),
      requirement: form.value.requirement.trim(),
      modelId: form.value.modelId,
      maxIterations: Number(form.value.maxIterations) || 100
    }
    const res = await startSkillGeneration(payload)
    runId.value = res.data.runId
    status.value = 'CREATED'
    stageMessage.value = '已提交，等待执行...'
    subscribeStream(res.data.runId)
  } catch (e) {
    isGenerating.value = false
    message.error(e.message || '启动生成失败')
  }
}

// ==================== SSE 订阅 ====================
function subscribeStream(rid) {
  const url = buildSkillGenerationStreamUrl(rid)
  const es = new EventSource(url)
  eventSource.value = es

  es.addEventListener('status', (e) => {
    try {
      const data = JSON.parse(e.data)
      stage.value = data.stage || ''
      stageMessage.value = data.message || ''
    } catch (_) { /* ignore */ }
  })

  es.addEventListener('thinking', (e) => {
    try {
      const data = JSON.parse(e.data)
      thinking.value += data.content || ''
      scrollLogToBottom()
    } catch (_) { /* ignore */ }
  })

  es.addEventListener('tool_call', (e) => {
    try {
      const data = JSON.parse(e.data)
      toolEvents.value.push({
        kind: 'call',
        tool: data.toolName || '',
        content: data.content || '',
        time: new Date().toLocaleTimeString()
      })
      scrollLogToBottom()
    } catch (_) { /* ignore */ }
  })

  es.addEventListener('tool_result', (e) => {
    try {
      const data = JSON.parse(e.data)
      toolEvents.value.push({
        kind: 'result',
        tool: data.toolName || '',
        content: data.content || '',
        time: new Date().toLocaleTimeString()
      })
      scrollLogToBottom()
    } catch (_) { /* ignore */ }
  })

  es.addEventListener('workflow_complete', (e) => {
    try {
      const data = JSON.parse(e.data)
      status.value = 'SUCCESS'
      generatedFolderName.value = data.generatedFolderName || ''
      finalText.value = data.finalText || ''
      message.success(`生成成功：${generatedFolderName.value}`)
    } catch (_) { /* ignore */ }
    finishStream()
  })

  es.addEventListener('workflow_error', (e) => {
    try {
      const data = JSON.parse(e.data)
      errorMessage.value = data.message || '未知错误'
    } catch (_) {
      errorMessage.value = '未知错误'
    }
    status.value = 'FAILED'
    message.error('生成失败：' + errorMessage.value)
    finishStream()
  })

  es.onerror = () => {
    // 浏览器自动重连可能触发 onerror，仅在已结束时关闭
    if (status.value === 'SUCCESS' || status.value === 'FAILED') {
      finishStream()
    }
  }
}

function finishStream() {
  isGenerating.value = false
  if (eventSource.value) {
    eventSource.value.close()
    eventSource.value = null
  }
}

function resetRunState() {
  runId.value = ''
  stage.value = ''
  stageMessage.value = ''
  thinking.value = ''
  toolEvents.value = []
  status.value = ''
  errorMessage.value = ''
  generatedFolderName.value = ''
  finalText.value = ''
}

function scrollLogToBottom() {
  nextTick(() => {
    const el = logContainer.value
    if (el) el.scrollTop = el.scrollHeight
  })
}

// ==================== 跳转与复制 ====================
function goToGeneratedSkill() {
  if (!generatedFolderName.value) return
  router.push(`/skill/edit/${encodeURIComponent(generatedFolderName.value)}`)
}

function copyFinalText() {
  if (!finalText.value) return
  navigator.clipboard.writeText(finalText.value)
    .then(() => message.success('已复制'))
    .catch(() => message.error('复制失败'))
}

// ==================== 生命周期 ====================
onMounted(() => {
  loadGenerators()
  loadModels()
})

onUnmounted(() => {
  if (eventSource.value) {
    eventSource.value.close()
  }
})

// ==================== 派生展示 ====================
const statusType = computed(() => {
  switch (status.value) {
    case 'SUCCESS': return 'success'
    case 'FAILED': return 'error'
    case 'RUNNING':
    case 'EXECUTING':
    case 'EXTRACTING':
    case 'CREATED': return 'info'
    default: return 'default'
  }
})

const statusText = computed(() => {
  switch (status.value) {
    case 'CREATED': return '已创建'
    case 'RUNNING': return '运行中'
    case 'SUCCESS': return '成功'
    case 'FAILED': return '失败'
    default: return status.value || '等待中'
  }
})
</script>

<template>
  <div class="skill-gen-page">
    <!-- 头部 -->
    <div class="page-header">
      <div class="header-left">
        <n-icon size="22" class="header-icon"><SparklesOutline /></n-icon>
        <div>
          <h2 class="page-title">技能生成</h2>
          <p class="page-subtitle">选择具备生成能力的技能，输入需求，自动生成新技能</p>
        </div>
      </div>
    </div>

    <div class="page-body">
      <!-- 左侧表单 -->
      <div class="form-panel">
        <div class="form-group">
          <label class="form-label">源技能 *</label>
          <n-select
            v-model:value="form.generatorSkillFolder"
            :options="generatorOptions"
            :loading="loadingGenerators"
            placeholder="选择具备生成能力的技能"
            filterable
          />
          <div v-if="generators.length === 0 && !loadingGenerators" class="empty-hint">
            <n-empty description="暂无具备生成能力的技能。请先在技能编辑页勾选「允许此技能生成其他技能」" size="small" />
          </div>
        </div>

        <div class="form-group">
          <label class="form-label">新技能名称 *</label>
          <n-input v-model:value="form.name" placeholder="如：代码审查助手" :maxlength="100" />
        </div>

        <div class="form-group">
          <label class="form-label">新技能描述</label>
          <n-input
            v-model:value="form.description"
            type="textarea"
            placeholder="简要描述新技能的用途"
            :rows="2"
            :maxlength="500"
          />
        </div>

        <div class="form-group">
          <div class="form-label-row">
            <label class="form-label">需求描述 *</label>
            <n-button
              size="tiny"
              quaternary
              type="primary"
              :loading="isRefining"
              :disabled="!form.requirement.trim()"
              @click="handleRefine"
            >
              <template #icon>
                <n-icon><ColorWandOutline /></n-icon>
              </template>
              智能润色
            </n-button>
          </div>
          <n-input
            v-model:value="form.requirement"
            type="textarea"
            placeholder="详细描述新技能需要完成什么任务、应具备的能力、输入输出等"
            :rows="6"
          />
        </div>

        <div class="form-row">
          <div class="form-group" style="flex: 1;">
            <label class="form-label">使用模型</label>
            <n-select
              v-model:value="form.modelId"
              :options="modelOptions"
              placeholder="使用默认模型"
            />
          </div>
          <div class="form-group" style="width: 140px;">
            <label class="form-label">最大迭代数</label>
            <n-input
              v-model:value="form.maxIterations"
              type="number"
              placeholder="100"
            />
          </div>
        </div>

        <div class="form-actions">
          <n-button
            type="primary"
            size="large"
            :loading="isGenerating"
            :disabled="!form.generatorSkillFolder || !form.name.trim() || !form.requirement.trim()"
            @click="handleGenerate"
          >
            <template #icon><n-icon><SparklesOutline /></n-icon></template>
            {{ isGenerating ? '生成中...' : '开始生成' }}
          </n-button>
        </div>
      </div>

      <!-- 右侧运行结果 -->
      <div class="result-panel">
        <div v-if="!runId && !isGenerating" class="result-empty">
          <n-empty description="点击「开始生成」后，这里会实时展示生成过程" />
        </div>

        <div v-else class="result-content">
          <!-- 状态条 -->
          <div class="status-bar">
            <div class="status-info">
              <n-tag :type="statusType" size="small" round>{{ statusText }}</n-tag>
              <span v-if="stageMessage" class="stage-msg">{{ stageMessage }}</span>
            </div>
            <div v-if="isGenerating" class="status-loading">
              <n-spin size="small" />
            </div>
          </div>

          <!-- 思考过程 -->
          <div v-if="thinking" class="log-section">
            <div class="section-title">思考过程</div>
            <div ref="logContainer" class="thinking-view">
              <pre>{{ thinking }}</pre>
            </div>
          </div>

          <!-- 工具事件 -->
          <div v-if="toolEvents.length" class="log-section">
            <div class="section-title">工具调用 ({{ toolEvents.length }})</div>
            <div class="tool-list">
              <div
                v-for="(ev, i) in toolEvents"
                :key="i"
                class="tool-item"
                :class="'tool-' + ev.kind"
              >
                <div class="tool-head">
                  <span class="tool-kind">{{ ev.kind === 'call' ? '→ 调用' : '← 结果' }}</span>
                  <span class="tool-name">{{ ev.tool }}</span>
                  <span class="tool-time">{{ ev.time }}</span>
                </div>
                <pre v-if="ev.content" class="tool-content">{{ ev.content }}</pre>
              </div>
            </div>
          </div>

          <!-- 生成结果 -->
          <div v-if="status === 'SUCCESS'" class="result-success">
            <div class="section-title">生成完成</div>
            <div class="success-card">
              <div class="success-row">
                <span class="success-label">新技能目录：</span>
                <code>{{ generatedFolderName }}</code>
              </div>
              <div class="success-actions">
                <n-button type="primary" size="small" @click="goToGeneratedSkill">
                  <template #icon><n-icon><ArrowForwardOutline /></n-icon></template>
                  进入编辑
                </n-button>
                <n-button v-if="finalText" size="small" quaternary @click="copyFinalText">
                  <template #icon><n-icon><CopyOutline /></n-icon></template>
                  复制总结
                </n-button>
              </div>
            </div>
            <div v-if="finalText" class="final-text">
              <div class="section-title">生成器总结</div>
              <pre>{{ finalText }}</pre>
            </div>
          </div>

          <!-- 失败 -->
          <div v-if="status === 'FAILED'" class="result-error">
            <div class="section-title">生成失败</div>
            <div class="error-box">{{ errorMessage }}</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.skill-gen-page {
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.page-header {
  padding: 16px 24px;
  border-bottom: 1px solid var(--border-color);
  background: var(--bg-secondary);
  flex-shrink: 0;
}

.header-left {
  display: flex;
  align-items: center;
  gap: 12px;
}

.header-icon {
  color: var(--color-accent);
}

.page-title {
  font-size: 18px;
  font-weight: 600;
  margin: 0;
  color: var(--text-primary);
}

.page-subtitle {
  font-size: 12px;
  color: var(--text-tertiary);
  margin: 4px 0 0 0;
}

.page-body {
  flex: 1;
  display: flex;
  gap: 16px;
  padding: 16px 24px;
  overflow: hidden;
}

/* ==================== 表单面板 ==================== */
.form-panel {
  width: 480px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  overflow-y: auto;
  padding: 20px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: 8px;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.form-row {
  display: flex;
  gap: 12px;
}

.form-label {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
}

.form-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.form-actions {
  margin-top: 8px;
}

.empty-hint {
  margin-top: 8px;
}

/* ==================== 结果面板 ==================== */
.result-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: 8px;
}

.result-empty {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.result-content {
  flex: 1;
  overflow-y: auto;
  padding: 16px 20px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.status-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border-color);
}

.status-info {
  display: flex;
  align-items: center;
  gap: 12px;
}

.stage-msg {
  font-size: 13px;
  color: var(--text-secondary);
}

.log-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.section-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
}

.thinking-view {
  background: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: 6px;
  padding: 12px;
  max-height: 360px;
  overflow-y: auto;
}

.thinking-view pre,
.tool-content pre,
.final-text pre {
  margin: 0;
  font-family: 'Consolas', 'Monaco', monospace;
  font-size: 12px;
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-all;
  color: var(--text-secondary);
}

.tool-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.tool-item {
  background: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: 6px;
  padding: 8px 12px;
}

.tool-call {
  border-left: 3px solid #3b82f6;
}

.tool-result {
  border-left: 3px solid #22c55e;
}

.tool-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 4px;
}

.tool-kind {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-tertiary);
  min-width: 48px;
}

.tool-name {
  font-size: 12px;
  font-weight: 600;
  color: var(--color-accent);
  flex: 1;
}

.tool-time {
  font-size: 11px;
  color: var(--text-tertiary);
}

.tool-content {
  margin-top: 4px;
  padding: 6px 8px;
  background: rgba(0, 0, 0, 0.03);
  border-radius: 4px;
  max-height: 180px;
  overflow-y: auto;
}

/* ==================== 成功结果 ==================== */
.result-success {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.success-card {
  padding: 16px;
  background: rgba(34, 197, 94, 0.06);
  border: 1px solid rgba(34, 197, 94, 0.25);
  border-radius: 6px;
}

.success-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  font-size: 14px;
}

.success-row code {
  background: rgba(34, 197, 94, 0.15);
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 13px;
  color: #22c55e;
  font-weight: 600;
}

.success-actions {
  display: flex;
  gap: 8px;
}

.final-text {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.final-text pre {
  background: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: 6px;
  padding: 12px;
  max-height: 240px;
  overflow-y: auto;
}

/* ==================== 失败 ==================== */
.result-error {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.error-box {
  padding: 12px 16px;
  background: rgba(239, 68, 68, 0.08);
  border: 1px solid rgba(239, 68, 68, 0.3);
  border-radius: 6px;
  color: #ef4444;
  font-size: 13px;
  line-height: 1.6;
}
</style>
