<template>
  <div class="ai-routing-page">
    <div class="page-header">
      <div class="header-left">
        <h2 class="page-title">AI 配置管理</h2>
        <p class="page-desc">统一管理服务商、接口工作流、业务场景绑定、流式测试和调用日志。</p>
      </div>
      <div class="header-actions">
        <el-button :icon="Refresh" :loading="loading" @click="loadAll">刷新数据</el-button>
      </div>
    </div>

    <el-row :gutter="16" class="stats-row">
      <el-col :span="6">
        <div class="stat-card stat-provider">
          <div class="stat-value">{{ providers.length }}</div>
          <div class="stat-label">服务商</div>
        </div>
      </el-col>
      <el-col :span="6">
        <div class="stat-card stat-endpoint">
          <div class="stat-value">{{ endpoints.length }}</div>
          <div class="stat-label">接口工作流</div>
        </div>
      </el-col>
      <el-col :span="6">
        <div class="stat-card stat-scene">
          <div class="stat-value">{{ enabledSceneCount }}</div>
          <div class="stat-label">已启用场景</div>
        </div>
      </el-col>
      <el-col :span="6">
        <div class="stat-card stat-log">
          <div class="stat-value">{{ logs.length }}</div>
          <div class="stat-label">最近调用日志</div>
        </div>
      </el-col>
    </el-row>

    <el-card class="table-card routing-card" shadow="never">
      <el-tabs v-model="activeTab" class="routing-tabs">
        <el-tab-pane label="服务商配置" name="providers">
          <div class="toolbar">
            <el-button type="primary" :icon="Plus" @click="openProvider()">新增服务商</el-button>
          </div>
          <el-table :data="providers" v-loading="loading" stripe empty-text="暂无服务商配置">
            <el-table-column prop="providerCode" label="服务商编码" width="170" show-overflow-tooltip />
            <el-table-column prop="providerName" label="服务商名称" min-width="160" show-overflow-tooltip />
            <el-table-column label="服务商类型" width="120">
              <template #default="{ row }">
                <el-tag type="primary" effect="plain">{{ providerTypeLabel(row.providerType) }}</el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="baseUrl" label="基础地址" min-width="280" show-overflow-tooltip />
            <el-table-column prop="timeoutMs" label="超时毫秒" width="110" align="center" />
            <el-table-column label="状态" width="100" align="center">
              <template #default="{ row }">
                <el-tag :type="row.isEnabled === 1 ? 'success' : 'danger'" effect="plain">
                  {{ row.isEnabled === 1 ? '启用' : '禁用' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="150" fixed="right" align="center">
              <template #default="{ row }">
                <el-button link type="primary" @click="openProvider(row)">编辑</el-button>
                <el-button link type="danger" @click="removeProvider(row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>

        <el-tab-pane label="接口工作流" name="endpoints">
          <div class="toolbar">
            <el-button type="primary" :icon="Plus" @click="openEndpoint()">新增接口</el-button>
          </div>
          <el-table :data="endpoints" v-loading="loading" stripe empty-text="暂无接口工作流配置">
            <el-table-column prop="endpointCode" label="接口编码" width="220" show-overflow-tooltip />
            <el-table-column prop="endpointName" label="接口名称" min-width="180" show-overflow-tooltip />
            <el-table-column label="服务商" min-width="170" show-overflow-tooltip>
              <template #default="{ row }">{{ providerName(row.providerId) }}</template>
            </el-table-column>
            <el-table-column label="接口类型" width="110" align="center">
              <template #default="{ row }">{{ endpointTypeLabel(row.endpointType) }}</template>
            </el-table-column>
            <el-table-column prop="apiPath" label="接口路径" min-width="210" show-overflow-tooltip />
            <el-table-column label="流式" width="90" align="center">
              <template #default="{ row }">
                <el-tag :type="row.supportStream === 1 ? 'success' : 'danger'" effect="plain">
                  {{ row.supportStream === 1 ? '支持' : '不支持' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="状态" width="100" align="center">
              <template #default="{ row }">
                <el-tag :type="row.isEnabled === 1 ? 'success' : 'danger'" effect="plain">
                  {{ row.isEnabled === 1 ? '启用' : '禁用' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="220" fixed="right" align="center">
              <template #default="{ row }">
                <el-button link type="primary" @click="openEndpoint(row)">编辑</el-button>
                <el-button link type="danger" @click="removeEndpoint(row)">删除</el-button>
                <el-button link type="success" :disabled="row.isEnabled !== 1" @click="openEndpointTest(row)">测试</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>

        <el-tab-pane label="场景绑定" name="scenes">
          <div class="toolbar">
            <el-button type="primary" :icon="Plus" @click="openScene()">新增场景</el-button>
            <el-button :icon="VideoPlay" @click="openRuntimeTest()">流式测试</el-button>
          </div>
          <el-table :data="scenes" v-loading="loading" stripe empty-text="暂无场景绑定">
            <el-table-column prop="sceneCode" label="场景编码" width="190" show-overflow-tooltip />
            <el-table-column prop="sceneName" label="场景名称" min-width="170" show-overflow-tooltip />
            <el-table-column label="绑定接口" min-width="260" show-overflow-tooltip>
              <template #default="{ row }">
                <span :class="{ muted: !row.endpointId }">{{ endpointName(row.endpointId) }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="priority" label="优先级" width="90" align="center" />
            <el-table-column label="强制流式" width="110" align="center">
              <template #default="{ row }">
                <el-tag :type="row.requiredStream === 1 ? 'success' : 'warning'" effect="plain">
                  {{ row.requiredStream === 1 ? '是' : '否' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="状态" width="100" align="center">
              <template #default="{ row }">
                <el-tag :type="row.isEnabled === 1 ? 'success' : 'danger'" effect="plain">
                  {{ row.isEnabled === 1 ? '启用' : '禁用' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="220" fixed="right" align="center">
              <template #default="{ row }">
                <el-button link type="primary" @click="openScene(row)">编辑</el-button>
                <el-button link type="danger" @click="removeScene(row)">删除</el-button>
                <el-button link type="success" @click="openSceneRuntimeTest(row)">测试</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>

        <el-tab-pane label="调用日志" name="logs">
          <el-table :data="logs" v-loading="loading" stripe empty-text="暂无调用日志">
            <el-table-column prop="createTime" label="调用时间" width="175" />
            <el-table-column prop="sceneCode" label="场景" width="160" show-overflow-tooltip />
            <el-table-column prop="providerCode" label="服务商" width="150" show-overflow-tooltip />
            <el-table-column prop="endpointCode" label="接口" min-width="210" show-overflow-tooltip />
            <el-table-column label="状态" width="100" align="center">
              <template #default="{ row }">
                <el-tag :type="row.status === 'success' ? 'success' : row.status === 'failed' ? 'danger' : 'warning'" effect="plain">
                  {{ statusLabel(row.status) }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="streamChunks" label="片段数" width="90" align="center" />
            <el-table-column prop="firstTokenMs" label="首字耗时" width="110" align="center" />
            <el-table-column prop="durationMs" label="总耗时" width="100" align="center" />
            <el-table-column prop="errorCode" label="错误码" min-width="180" show-overflow-tooltip />
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </el-card>

    <el-dialog v-model="providerDialog" :title="providerForm.id ? '编辑服务商' : '新增服务商'" width="680px">
      <el-form :model="providerForm" label-width="120px">
        <el-form-item label="服务商编码"><el-input v-model="providerForm.providerCode" placeholder="例如 coze_default" /></el-form-item>
        <el-form-item label="服务商名称"><el-input v-model="providerForm.providerName" placeholder="请输入服务商名称" /></el-form-item>
        <el-form-item label="服务商类型">
          <el-select v-model="providerForm.providerType" style="width: 100%">
            <el-option label="Dify" value="dify" />
            <el-option label="Coze" value="coze" />
            <el-option label="OpenAI" value="openai" disabled />
          </el-select>
        </el-form-item>
        <el-form-item label="基础地址"><el-input v-model="providerForm.baseUrl" placeholder="例如 https://api.coze.cn" /></el-form-item>
        <el-form-item label="接口密钥"><el-input v-model="providerForm.apiKey" type="password" show-password placeholder="编辑时为空表示不修改密钥" /></el-form-item>
        <el-form-item label="请求头配置"><el-input v-model="providerForm.defaultHeaders" type="textarea" :rows="3" placeholder="JSON 格式，可为空" /></el-form-item>
        <el-form-item label="启用状态"><el-switch v-model="providerEnabled" active-text="启用" inactive-text="禁用" /></el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="providerDialog = false">取消</el-button>
        <el-button type="primary" @click="submitProvider">保存</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="endpointDialog" :title="endpointForm.id ? '编辑接口工作流' : '新增接口工作流'" width="760px">
      <el-form :model="endpointForm" label-width="130px">
        <el-form-item label="接口编码"><el-input v-model="endpointForm.endpointCode" placeholder="例如 coze.script.generate" /></el-form-item>
        <el-form-item label="接口名称"><el-input v-model="endpointForm.endpointName" placeholder="请输入接口名称" /></el-form-item>
        <el-form-item label="所属服务商">
          <el-select v-model="endpointForm.providerId" filterable style="width: 100%">
            <el-option v-for="item in providers" :key="item.id" :label="`${item.providerName}（${item.providerCode}）`" :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="接口类型">
          <el-select v-model="endpointForm.endpointType" style="width: 100%">
            <el-option label="工作流" value="workflow" />
            <el-option label="对话" value="chat" />
          </el-select>
        </el-form-item>
        <el-form-item label="接口路径"><el-input v-model="endpointForm.apiPath" placeholder="/v1/workflow/stream_run 或 /chat-messages" /></el-form-item>
        <el-form-item label="工作流 ID"><el-input v-model="endpointForm.workflowId" /></el-form-item>
        <el-form-item label="机器人 ID"><el-input v-model="endpointForm.botId" /></el-form-item>
        <el-form-item label="请求模板"><el-input v-model="endpointForm.requestTemplate" type="textarea" :rows="4" placeholder="JSON 模板，可使用 {{prompt}} 等变量" /></el-form-item>
        <el-form-item label="默认入参"><el-input v-model="endpointForm.defaultInputs" type="textarea" :rows="3" placeholder="JSON 格式，会与用户端入参合并" /></el-form-item>
        <el-form-item label="参数定义">
          <div v-for="(param, index) in paramDefinitions" :key="index" class="param-row" style="display: flex; gap: 8px; margin-bottom: 8px; align-items: center">
            <el-input v-model="param.name" placeholder="参数名" style="width: 110px" />
            <el-input v-model="param.label" placeholder="显示标签" style="width: 120px" />
            <el-select v-model="param.type" style="width: 100px">
              <el-option label="文本" value="string" />
              <el-option label="多行" value="textarea" />
              <el-option label="数字" value="number" />
              <el-option label="开关" value="boolean" />
              <el-option label="JSON" value="json" />
            </el-select>
            <el-input v-model="param.defaultValue" placeholder="默认值" style="width: 100px" />
            <el-checkbox v-model="param.required">必填</el-checkbox>
            <el-button link type="danger" @click="removeParam(index)">删除</el-button>
          </div>
          <el-button link type="primary" @click="addParam">+ 添加参数</el-button>
        </el-form-item>
        <el-form-item label="支持流式"><el-switch v-model="endpointStream" active-text="支持" inactive-text="不支持" /></el-form-item>
        <el-form-item label="启用状态"><el-switch v-model="endpointEnabled" active-text="启用" inactive-text="禁用" /></el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="endpointDialog = false">取消</el-button>
        <el-button type="primary" @click="submitEndpoint">保存</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="sceneDialog" :title="sceneForm.id ? '编辑场景绑定' : '新增场景绑定'" width="720px">
      <el-form :model="sceneForm" label-width="120px">
        <el-form-item label="场景编码"><el-input v-model="sceneForm.sceneCode" placeholder="例如 script_generate" /></el-form-item>
        <el-form-item label="场景名称"><el-input v-model="sceneForm.sceneName" placeholder="请输入中文场景名称" /></el-form-item>
        <el-form-item label="绑定接口">
          <el-select v-model="sceneForm.endpointId" filterable style="width: 100%" placeholder="请选择接口工作流">
            <el-option v-for="item in endpoints" :key="item.id" :label="`${item.endpointName}（${item.endpointCode}）`" :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="入参说明"><el-input v-model="sceneForm.inputSchema" type="textarea" :rows="3" placeholder="JSON 格式，描述该场景允许的入参" /></el-form-item>
        <el-form-item label="优先级"><el-input-number v-model="sceneForm.priority" :min="0" :max="9999" /></el-form-item>
        <el-form-item label="强制流式"><el-switch v-model="sceneStream" active-text="是" inactive-text="否" /></el-form-item>
        <el-form-item label="启用状态"><el-switch v-model="sceneEnabled" active-text="启用" inactive-text="禁用" /></el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="sceneDialog = false">取消</el-button>
        <el-button type="primary" @click="submitScene">保存</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="testDialog" title="接口测试" width="760px">
      <el-form label-width="110px">
        <el-form-item label="业务场景">
          <el-select v-model="testForm.sceneCode" filterable style="width: 100%">
            <el-option v-for="item in scenes" :key="item.id" :label="`${item.sceneName}（${item.sceneCode}）`" :value="item.sceneCode" />
          </el-select>
        </el-form-item>
        <el-form-item label="入参 JSON">
          <el-input v-model="testInputsJson" type="textarea" :rows="6" placeholder="请输入 JSON 入参" />
        </el-form-item>
      </el-form>
      <el-alert
        v-if="nonStreamResult"
        :type="nonStreamResult.status === 'success' ? 'success' : 'error'"
        :title="nonStreamResult.status === 'success' ? '非流式测试成功' : '非流式测试失败'"
        show-icon
      />
      <pre v-if="nonStreamResult" class="test-output">{{ nonStreamResult.output || nonStreamResult.errorMessage || '暂无输出' }}</pre>
      <el-alert
        v-if="testResult"
        :type="testResult.status === 'success' ? 'success' : 'error'"
        :title="testResult.status === 'success' ? '流式测试成功' : '流式测试失败'"
        show-icon
      />
      <pre v-if="testResult" class="test-output">{{ testResult.output || testResult.errorMessage || '暂无输出' }}</pre>
      <template #footer>
        <el-button @click="testDialog = false">关闭</el-button>
        <el-button :loading="testing" @click="submitNonStreamTest">非流式测试</el-button>
        <el-button type="primary" :loading="testing" @click="submitRuntimeTest">流式测试</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="endpointTestDialog" title="接口工作流测试" width="760px">
      <div class="endpoint-info">
        <span class="endpoint-label">接口名称：</span>
        <span>{{ endpointTestRow?.endpointName }}（{{ endpointTestRow?.endpointCode }}）</span>
      </div>
      <el-form v-if="endpointParamFields.length > 0" label-width="120px" style="margin-top: 16px">
        <el-form-item v-for="field in endpointParamFields" :key="field.name" :label="field.label" :required="field.required"
          style="margin-bottom: 12px">
          <el-input v-if="field.type === 'string'" v-model="field.value" :placeholder="field.name" @input="syncEndpointJsonFromFields" />
          <el-input v-if="field.type === 'textarea'" v-model="field.value" type="textarea" :rows="3" :placeholder="field.name" @input="syncEndpointJsonFromFields" />
          <el-input-number v-if="field.type === 'number'" v-model="field.value" :placeholder="field.name" @change="syncEndpointJsonFromFields" style="width: 100%" />
          <el-switch v-if="field.type === 'boolean'" v-model="field.value" @change="syncEndpointJsonFromFields" />
          <el-input v-if="field.type === 'json'" v-model="field.value" type="textarea" :rows="4" :placeholder="field.placeholder || field.name" @input="syncEndpointJsonFromFields" />
        </el-form-item>
      </el-form>
      <el-collapse style="margin-top: 12px">
        <el-collapse-item title="高级编辑（JSON）">
          <el-input v-model="endpointInputsJson" type="textarea" :rows="6" placeholder="请输入 JSON 入参" @input="syncEndpointFieldsFromJson" />
        </el-collapse-item>
      </el-collapse>
      <el-alert
        v-if="endpointNonStreamResult"
        :type="endpointNonStreamResult.status === 'success' ? 'success' : 'error'"
        :title="endpointNonStreamResult.status === 'success' ? '非流式测试成功' : '非流式测试失败'"
        show-icon
      />
      <pre v-if="endpointNonStreamResult" class="test-output">{{ endpointNonStreamResult.output || endpointNonStreamResult.errorMessage || '暂无输出' }}</pre>
      <el-alert
        v-if="endpointTestResult"
        :type="endpointTestResult.status === 'success' ? 'success' : 'error'"
        :title="endpointTestResult.status === 'success' ? '流式测试成功' : '流式测试失败'"
        show-icon
      />
      <pre v-if="endpointTestResult" class="test-output">{{ endpointTestResult.output || endpointTestResult.errorMessage || '暂无输出' }}</pre>
      <template #footer>
        <el-button @click="endpointTestDialog = false">关闭</el-button>
        <el-button :loading="endpointTesting" @click="submitEndpointNonStreamTest">非流式测试</el-button>
        <el-button type="primary" :loading="endpointTesting" @click="submitEndpointStreamTest">流式测试</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Refresh, VideoPlay } from '@element-plus/icons-vue'
import {
  deleteAiEndpoint,
  deleteAiProvider,
  deleteAiScene,
  getEndpointTestTemplate,
  getSceneTestTemplate,
  listAiCallLogs,
  listAiEndpoints,
  listAiProviders,
  listAiScenes,
  saveAiEndpoint,
  saveAiProvider,
  saveAiScene,
  streamAiRuntime,
  streamEndpointRuntime,
  testAiRuntime,
  testEndpointRuntime
} from '@/api/aiconfig'
import type { AiCallLog, AiEndpointConfig, AiProvider, AiRuntimeTestResponse, AiSceneBinding, TestParamField, ParamDefinition, AiTestTemplateResponse } from '@/types/aiconfig'

const activeTab = ref('providers')
const loading = ref(false)
const providers = ref<AiProvider[]>([])
const endpoints = ref<AiEndpointConfig[]>([])
const scenes = ref<AiSceneBinding[]>([])
const logs = ref<AiCallLog[]>([])

const providerDialog = ref(false)
const endpointDialog = ref(false)
const sceneDialog = ref(false)
const testDialog = ref(false)
const testing = ref(false)
const testResult = ref<AiRuntimeTestResponse | null>(null)
const nonStreamResult = ref<AiRuntimeTestResponse | null>(null)
const testInputsJson = ref('{\n  "prompt": "请用一句中文回复测试成功。"\n}')

const endpointTestDialog = ref(false)
const endpointTesting = ref(false)
const endpointTestRow = ref<AiEndpointConfig | null>(null)
const endpointTestResult = ref<AiRuntimeTestResponse | null>(null)
const endpointNonStreamResult = ref<AiRuntimeTestResponse | null>(null)
const endpointInputsJson = ref('{}')
const endpointParamFields = ref<TestParamField[]>([])

const paramDefinitions = ref<ParamDefinition[]>([])

const providerForm = reactive<AiProvider>(newProvider())
const endpointForm = reactive<AiEndpointConfig>(newEndpoint())
const sceneForm = reactive<AiSceneBinding>(newScene())
const testForm = reactive({ sceneCode: '' })

const enabledSceneCount = computed(() => scenes.value.filter(item => item.isEnabled === 1).length)

const providerEnabled = computed({
  get: () => providerForm.isEnabled === 1,
  set: value => { providerForm.isEnabled = value ? 1 : 0 }
})
const endpointEnabled = computed({
  get: () => endpointForm.isEnabled === 1,
  set: value => { endpointForm.isEnabled = value ? 1 : 0 }
})
const endpointStream = computed({
  get: () => endpointForm.supportStream === 1,
  set: value => { endpointForm.supportStream = value ? 1 : 0 }
})
const sceneEnabled = computed({
  get: () => sceneForm.isEnabled === 1,
  set: value => { sceneForm.isEnabled = value ? 1 : 0 }
})
const sceneStream = computed({
  get: () => sceneForm.requiredStream === 1,
  set: value => { sceneForm.requiredStream = value ? 1 : 0 }
})

function newProvider(): AiProvider {
  return { providerCode: '', providerName: '', providerType: 'dify', baseUrl: '', authType: 'bearer', timeoutMs: 60000, isEnabled: 1 }
}

function newEndpoint(): AiEndpointConfig {
  return { endpointCode: '', endpointName: '', providerId: '', endpointType: 'workflow', responseMode: 'streaming', supportStream: 1, isEnabled: 1, timeoutMs: 60000 }
}

function newScene(): AiSceneBinding {
  return { sceneCode: '', sceneName: '', endpointId: '', requiredStream: 1, priority: 0, isEnabled: 1, version: 'v1' }
}

function assignForm<T extends object>(target: T, source: T) {
  Object.keys(target).forEach(key => delete (target as Record<string, unknown>)[key])
  Object.assign(target, source)
}

function providerName(id?: string) {
  return providers.value.find(item => item.id === id)?.providerName || id || '未配置'
}

function endpointName(id?: string) {
  return endpoints.value.find(item => item.id === id)?.endpointName || id || '未绑定接口'
}

function providerTypeLabel(type?: string) {
  const map: Record<string, string> = { dify: 'Dify', coze: 'Coze', openai: 'OpenAI', custom: '自定义' }
  return type ? map[type] || type : '-'
}

function endpointTypeLabel(type?: string) {
  const map: Record<string, string> = { workflow: '工作流', chat: '对话', completion: '补全', custom: '自定义' }
  return type ? map[type] || type : '-'
}

function statusLabel(status?: string) {
  const map: Record<string, string> = { running: '运行中', success: '成功', failed: '失败' }
  return status ? map[status] || status : '-'
}

async function loadAll() {
  loading.value = true
  try {
    const [providerRes, endpointRes, sceneRes, logRes] = await Promise.all([
      listAiProviders(),
      listAiEndpoints(),
      listAiScenes(),
      listAiCallLogs(80)
    ])
    providers.value = providerRes.data || []
    endpoints.value = endpointRes.data || []
    scenes.value = sceneRes.data || []
    logs.value = logRes.data || []
  } finally {
    loading.value = false
  }
}

function openProvider(row?: AiProvider) {
  assignForm(providerForm, row ? { ...row, apiKey: '' } : newProvider())
  providerDialog.value = true
}

function openEndpoint(row?: AiEndpointConfig) {
  assignForm(endpointForm, row ? { ...row } : newEndpoint())
  paramDefinitions.value = parseDefinitionsFromDefaultInputs(row?.defaultInputs)
  endpointDialog.value = true
}

function openScene(row?: AiSceneBinding) {
  assignForm(sceneForm, row ? { ...row } : newScene())
  sceneDialog.value = true
}

async function openRuntimeTest() {
  testForm.sceneCode = scenes.value.find(item => item.isEnabled === 1 && item.endpointId)?.sceneCode || scenes.value[0]?.sceneCode || ''
  testResult.value = null
  nonStreamResult.value = null
  await loadSceneTemplate(testForm.sceneCode)
  testDialog.value = true
}

async function openSceneRuntimeTest(row: AiSceneBinding) {
  testForm.sceneCode = row.sceneCode
  testResult.value = null
  nonStreamResult.value = null
  await loadSceneTemplate(row.sceneCode)
  testDialog.value = true
}

async function openEndpointTest(row: AiEndpointConfig) {
  if (!row.id) return
  endpointTestRow.value = row
  endpointParamFields.value = parseParamFields(row.defaultInputs)
  endpointInputsJson.value = buildInputsJson(endpointParamFields.value)
  endpointTestResult.value = null
  endpointNonStreamResult.value = null
  endpointTestDialog.value = true
  endpointTesting.value = true
  try {
    const res = await getEndpointTestTemplate(row.id!)
    applyEndpointTemplate(res.data as AiTestTemplateResponse)
  } catch (error: any) {
    ElMessage.warning(error?.message || '测试样例加载失败，已使用本地默认参数')
  } finally {
    endpointTesting.value = false
  }
}

async function loadSceneTemplate(sceneCode: string) {
  if (!sceneCode) {
    testInputsJson.value = '{\n  "prompt": "请用一句中文回复测试成功。"\n}'
    return
  }
  try {
    const res = await getSceneTestTemplate(sceneCode)
    const template = res.data as AiTestTemplateResponse
    testInputsJson.value = JSON.stringify(template.inputs || {}, null, 2)
  } catch (error: any) {
    testInputsJson.value = '{\n  "prompt": "请用一句中文回复测试成功。"\n}'
    ElMessage.warning(error?.message || '场景测试样例加载失败，已使用通用测试参数')
  }
}

function applyEndpointTemplate(template: AiTestTemplateResponse) {
  const inputs = template.inputs || {}
  endpointInputsJson.value = JSON.stringify(inputs, null, 2)
  endpointParamFields.value = (template.paramFields || []).map(field => ({
    ...field,
    value: field.type === 'json'
      ? JSON.stringify(field.value ?? {}, null, 2)
      : field.value,
    defaultValue: field.value,
    required: Boolean(field.required)
  }))
}

function parseParamFields(defaultInputs?: string): TestParamField[] {
  if (!defaultInputs) return []
  try {
    const parsed = JSON.parse(defaultInputs)
    if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) return []
    return Object.entries(parsed).map(([key, val]: [string, any]) => {
      // 新格式：{ _meta: {...}, value: ... }
      if (val && typeof val === 'object' && '_meta' in val) {
        return {
          name: key,
          label: val._meta.label || key,
          type: val._meta.type || 'string',
          value: val.value,
          defaultValue: val.value,
          required: val._meta.required || false
        } as TestParamField
      }
      // 旧格式：直接值
      return {
        name: key,
        label: key,
        type: inferParamType(val),
        value: val,
        defaultValue: val,
        required: false
      } as TestParamField
    })
  } catch {
    return []
  }
}

function inferParamType(val: any): 'string' | 'textarea' | 'number' | 'boolean' | 'json' {
  if (typeof val === 'number') return 'number'
  if (typeof val === 'boolean') return 'boolean'
  if (val && typeof val === 'object') return 'json'
  if (typeof val === 'string' && val.length > 80) return 'textarea'
  return 'string'
}

function buildInputsJson(fields: TestParamField[]): string {
  const obj: Record<string, any> = {}
  fields.forEach(f => {
    if (!f.name) return
    if (f.type === 'json') {
      try {
        obj[f.name] = typeof f.value === 'string' ? JSON.parse(f.value || '{}') : f.value
      } catch {
        obj[f.name] = f.value
      }
    } else {
      obj[f.name] = f.value
    }
  })
  return JSON.stringify(obj, null, 2)
}

function syncEndpointJsonFromFields() {
  endpointInputsJson.value = buildInputsJson(endpointParamFields.value)
}

function syncEndpointFieldsFromJson() {
  try {
    const parsed = JSON.parse(endpointInputsJson.value || '{}')
    endpointParamFields.value.forEach(field => {
      if (field.name in parsed) {
        field.value = field.type === 'json'
          ? JSON.stringify(parsed[field.name] ?? {}, null, 2)
          : parsed[field.name]
      }
    })
  } catch { /* ignore parse errors */ }
}

function addParam() {
  paramDefinitions.value.push({ name: '', label: '', type: 'string', defaultValue: '', required: false })
}

function removeParam(index: number) {
  paramDefinitions.value.splice(index, 1)
}

function buildDefaultInputsFromDefinitions(defs: ParamDefinition[]): string {
  const obj: Record<string, any> = {}
  defs.forEach(d => {
    if (d.name) {
      obj[d.name] = {
        _meta: { label: d.label || d.name, type: d.type, required: d.required },
        value: d.defaultValue
      }
    }
  })
  return JSON.stringify(obj)
}

function parseDefinitionsFromDefaultInputs(defaultInputs?: string): ParamDefinition[] {
  if (!defaultInputs) return []
  try {
    const parsed = JSON.parse(defaultInputs)
    if (typeof parsed !== 'object' || parsed === null) return []
    return Object.entries(parsed).map(([key, val]: [string, any]) => {
      if (val && typeof val === 'object' && '_meta' in val) {
        return {
          name: key,
          label: val._meta.label || key,
          type: val._meta.type || 'string',
          defaultValue: val.value,
          required: val._meta.required || false
        } as ParamDefinition
      }
      return { name: key, label: key, type: inferParamType(val), defaultValue: val, required: false } as ParamDefinition
    })
  } catch {
    return []
  }
}

async function submitProvider() {
  await saveAiProvider({ ...providerForm })
  providerDialog.value = false
  ElMessage.success('服务商已保存')
  await loadAll()
}

async function submitEndpoint() {
  const data = { ...endpointForm }
  // 如果有参数定义，合并到 defaultInputs
  if (paramDefinitions.value.length > 0) {
    data.defaultInputs = buildDefaultInputsFromDefinitions(paramDefinitions.value)
  }
  await saveAiEndpoint(data)
  endpointDialog.value = false
  ElMessage.success('接口工作流已保存')
  await loadAll()
}

async function submitScene() {
  await saveAiScene({ ...sceneForm })
  sceneDialog.value = false
  ElMessage.success('场景绑定已保存')
  await loadAll()
}

async function removeProvider(row: AiProvider) {
  if (!row.id) return
  await ElMessageBox.confirm('确认删除这个服务商配置吗？', '删除确认', { type: 'warning' })
  await deleteAiProvider(row.id)
  ElMessage.success('服务商已删除')
  await loadAll()
}

async function removeEndpoint(row: AiEndpointConfig) {
  if (!row.id) return
  await ElMessageBox.confirm('确认删除这个接口工作流吗？', '删除确认', { type: 'warning' })
  await deleteAiEndpoint(row.id)
  ElMessage.success('接口工作流已删除')
  await loadAll()
}

async function removeScene(row: AiSceneBinding) {
  if (!row.id) return
  await ElMessageBox.confirm('确认删除这个场景绑定吗？', '删除确认', { type: 'warning' })
  await deleteAiScene(row.id)
  ElMessage.success('场景绑定已删除')
  await loadAll()
}

async function submitNonStreamTest() {
  let inputs: Record<string, any>
  try {
    inputs = JSON.parse(testInputsJson.value || '{}')
  } catch (error) {
    ElMessage.error('入参 JSON 格式不正确')
    return
  }
  testing.value = true
  try {
    const res = await testAiRuntime({ sceneCode: testForm.sceneCode, inputs })
    nonStreamResult.value = res.data as AiRuntimeTestResponse
    if (nonStreamResult.value.status === 'success') {
      ElMessage.success('非流式测试成功')
    } else {
      ElMessage.error(`测试失败: ${nonStreamResult.value.errorMessage || nonStreamResult.value.errorCode}`)
    }
    await loadAll()
  } catch (error: any) {
    nonStreamResult.value = {
      sceneCode: testForm.sceneCode,
      status: 'failed',
      errorMessage: error?.message || '非流式测试失败'
    } as AiRuntimeTestResponse
    ElMessage.error(error?.message || '非流式测试失败')
  } finally {
    testing.value = false
  }
}

async function submitRuntimeTest() {
  let inputs: Record<string, any>
  try {
    inputs = JSON.parse(testInputsJson.value || '{}')
  } catch (error) {
    ElMessage.error('入参 JSON 格式不正确')
    return
  }
  testing.value = true
  testResult.value = { sceneCode: testForm.sceneCode, status: 'success', output: '', streamChunks: 0, durationMs: 0 }
  const startedAt = Date.now()
  try {
    await streamAiRuntime({ sceneCode: testForm.sceneCode, inputs }, (event, output) => {
      if (!testResult.value) return
      testResult.value.output = output
      if (event.type === 'delta') {
        testResult.value.streamChunks = (testResult.value.streamChunks || 0) + 1
      }
      if (event.type === 'done') {
        testResult.value.status = 'success'
      }
      if (event.type === 'error') {
        testResult.value.status = 'failed'
        testResult.value.errorCode = event.code
        testResult.value.errorMessage = event.message
      }
      testResult.value.durationMs = Date.now() - startedAt
    })
    await loadAll()
  } catch (error: any) {
    if (testResult.value) {
      testResult.value.status = 'failed'
      testResult.value.errorMessage = error?.message || '流式测试失败'
      testResult.value.durationMs = Date.now() - startedAt
    }
  } finally {
    testing.value = false
  }
}

async function submitEndpointNonStreamTest() {
  if (!endpointTestRow.value) return
  if (!validateEndpointFields()) return
  let inputs: Record<string, any>
  try {
    inputs = JSON.parse(endpointInputsJson.value || '{}')
  } catch {
    ElMessage.error('入参 JSON 格式不正确')
    return
  }
  endpointTesting.value = true
  try {
    const res = await testEndpointRuntime({ endpointId: endpointTestRow.value.id!, inputs })
    endpointNonStreamResult.value = res.data as AiRuntimeTestResponse
    if (endpointNonStreamResult.value.status === 'success') {
      ElMessage.success('非流式测试成功')
    } else {
      ElMessage.error(`测试失败: ${endpointNonStreamResult.value.errorMessage || endpointNonStreamResult.value.errorCode}`)
    }
    await loadAll()
  } catch (error: any) {
    endpointNonStreamResult.value = {
      sceneCode: '',
      status: 'failed',
      errorMessage: error?.message || '非流式测试失败'
    } as AiRuntimeTestResponse
    ElMessage.error(error?.message || '非流式测试失败')
  } finally {
    endpointTesting.value = false
  }
}

async function submitEndpointStreamTest() {
  if (!endpointTestRow.value) return
  if (!validateEndpointFields()) return
  let inputs: Record<string, any>
  try {
    inputs = JSON.parse(endpointInputsJson.value || '{}')
  } catch {
    ElMessage.error('入参 JSON 格式不正确')
    return
  }
  endpointTesting.value = true
  endpointTestResult.value = { sceneCode: '', status: 'success', output: '', streamChunks: 0, durationMs: 0 }
  const startedAt = Date.now()
  try {
    await streamEndpointRuntime({ endpointId: endpointTestRow.value.id!, inputs }, (event, output) => {
      if (!endpointTestResult.value) return
      endpointTestResult.value.output = output
      if (event.type === 'delta') {
        endpointTestResult.value.streamChunks = (endpointTestResult.value.streamChunks || 0) + 1
      }
      if (event.type === 'done') {
        endpointTestResult.value.status = 'success'
      }
      if (event.type === 'error') {
        endpointTestResult.value.status = 'failed'
        endpointTestResult.value.errorCode = event.code
        endpointTestResult.value.errorMessage = event.message
      }
      endpointTestResult.value.durationMs = Date.now() - startedAt
    })
    await loadAll()
  } catch (error: any) {
    if (endpointTestResult.value) {
      endpointTestResult.value.status = 'failed'
      endpointTestResult.value.errorMessage = error?.message || '流式测试失败'
      endpointTestResult.value.durationMs = Date.now() - startedAt
    }
  } finally {
    endpointTesting.value = false
  }
}

function validateEndpointFields() {
  for (const field of endpointParamFields.value) {
    if (!field.required) continue
    const value = field.value
    if (value === null || value === undefined || String(value).trim() === '') {
      ElMessage.error(`请填写必填参数：${field.label || field.name}`)
      return false
    }
  }
  for (const field of endpointParamFields.value.filter(item => item.type === 'json')) {
    try {
      JSON.parse(field.value || '{}')
    } catch {
      ElMessage.error(`参数 ${field.label || field.name} 不是有效 JSON`)
      return false
    }
  }
  return true
}

onMounted(loadAll)
</script>

<style scoped>
.ai-routing-page {
  padding: 24px;
}

.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 18px;
}

.page-title {
  margin: 0 0 8px;
  color: var(--ls-text);
  font-size: 24px;
  font-weight: 700;
}

.page-desc {
  margin: 0;
  color: var(--ls-text-muted);
  font-size: 14px;
}

.stats-row {
  margin-bottom: 16px;
}

.stat-card {
  min-height: 92px;
  padding: 18px 20px;
  border: 1px solid var(--ls-glass-border);
  border-radius: var(--ls-radius-lg);
  background: rgba(15, 17, 26, 0.38);
  box-shadow: var(--ls-shadow);
  backdrop-filter: blur(20px) saturate(160%);
}

.stat-value {
  color: var(--ls-text);
  font-size: 30px;
  font-weight: 700;
  line-height: 1;
}

.stat-label {
  margin-top: 10px;
  color: var(--ls-text-muted);
  font-size: 13px;
}

.stat-provider {
  border-color: rgba(255, 171, 145, 0.24);
}

.stat-endpoint {
  border-color: rgba(129, 212, 250, 0.22);
}

.stat-scene {
  border-color: rgba(103, 194, 58, 0.20);
}

.stat-log {
  border-color: rgba(230, 162, 60, 0.20);
}

.routing-card {
  padding: 4px 6px 14px;
}

.routing-tabs :deep(.el-tabs__header) {
  margin-bottom: 16px;
}

.toolbar {
  display: flex;
  gap: 10px;
  margin-bottom: 14px;
}

.muted {
  color: rgba(226, 232, 240, 0.45);
}

.test-output {
  min-height: 120px;
  max-height: 360px;
  overflow: auto;
  padding: 14px;
  margin-top: 12px;
  color: rgba(226, 232, 240, 0.92);
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--ls-radius-md);
  white-space: pre-wrap;
}

.endpoint-info {
  padding: 10px 14px;
  color: rgba(226, 232, 240, 0.85);
  background: rgba(0, 0, 0, 0.15);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--ls-radius-md);
  font-size: 14px;
}

.endpoint-label {
  color: var(--ls-text-muted);
  margin-right: 6px;
}
</style>
