<template>
  <section class="page generate-page">
    <div class="panel" v-loading="loadingProject">
      <div class="panel-header">
        <div>
          <h1 class="panel-title">项目生成工作台</h1>
          <p class="muted">先生成应用蓝图，再生成数据库结构，保存修改后生成业务蓝图。</p>
        </div>
      </div>

      <div class="content">
        <el-form :model="projectForm" label-position="top" class="project-form">
          <el-row :gutter="16">
            <el-col :xs="24" :md="8">
              <el-form-item label="项目名称">
                <el-input v-model="projectForm.projectName" placeholder="例如 客户中心" />
              </el-form-item>
            </el-col>
            <el-col :xs="24" :md="16">
              <el-form-item label="需求关键词">
                <el-input
                  v-model="projectForm.keyword"
                  placeholder="描述业务对象、流程或功能范围"
                />
              </el-form-item>
            </el-col>
          </el-row>
          <el-form-item label="补充说明">
            <el-input
              v-model="projectForm.projectDesc"
              type="textarea"
              :rows="3"
              placeholder="例如字段偏好、模块边界、业务规则"
            />
          </el-form-item>
          <el-row :gutter="16">
            <el-col :xs="24" :md="8">
              <el-form-item label="项目形态">
                <el-switch
                  v-model="projectForm.frontendEnabled"
                  active-text="生成用户前台"
                  inactive-text="仅后台管理"
                />
              </el-form-item>
            </el-col>
            <el-col :xs="24" :md="16">
              <el-form-item label="后台功能模块">
                <el-select
                  v-model="projectForm.moduleIds"
                  multiple
                  clearable
                  filterable
                  collapse-tags
                  collapse-tags-tooltip
                  placeholder="选择后台维护的功能模块"
                  class="module-select"
                  :loading="loadingModules"
                >
                  <el-option
                    v-for="module in availableModules"
                    :key="module.moduleId"
                    :label="moduleLabel(module)"
                    :value="module.moduleId"
                  />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>

        <el-alert
          v-if="errorMessage"
          class="error-alert"
          type="warning"
          :title="errorMessage"
          show-icon
          :closable="false"
        />

        <div class="toolbar">
          <el-button type="primary" :loading="generatingAppBlueprint" @click="handleGenerateAppBlueprint">
            生成应用蓝图
          </el-button>
          <el-button type="primary" :icon="DataAnalysis" :disabled="!hasAppBlueprint" :loading="generating" @click="handleGenerateDatabase">
            生成数据库
          </el-button>
          <el-button :disabled="!projectId || !database.tables.length" :loading="saving" @click="handleSaveDatabase">
            保存表结构
          </el-button>
          <el-button
            type="primary"
            :disabled="!projectId || !database.tables.length"
            :loading="generatingBusinessBlueprint"
            @click="handleGenerateBusinessBlueprint"
          >
            生成业务蓝图
          </el-button>
          <el-button
            type="success"
            :icon="View"
            :disabled="!projectId || !database.tables.length"
            :loading="previewing"
            @click="handlePreview"
          >
            预览项目
          </el-button>
        </div>

        <div v-if="activeAiTask || aiQuota" class="ai-task-strip">
          <div v-if="activeAiTask" class="ai-task-card">
            <div class="ai-task-card-header">
              <strong>{{ taskTypeLabel(activeAiTask.generateType) }}</strong>
              <el-tag size="small" effect="plain">{{ taskStatusLabel(activeAiTask.status) }}</el-tag>
            </div>
            <el-progress :percentage="Number(activeAiTask.progress || 0)" :stroke-width="8" />
            <p class="muted">{{ activeAiTask.currentStep || '-' }}</p>
            <p v-if="activeAiTask.errorMessage" class="task-error">{{ activeAiTask.errorMessage }}</p>
            <el-button
              v-if="activeAiTask.status === 'FAILED' || activeAiTask.status === 'RETRY_WAITING'"
              size="small"
              type="primary"
              @click="handleRetryActiveTask"
            >
              重试
            </el-button>
          </div>
          <div v-if="aiQuota" class="ai-quota-card">
            <span>今日 {{ aiQuota.dailyTaskUsed || 0 }}/{{ aiQuota.dailyTaskLimit || 0 }}</span>
            <span>运行中 {{ aiQuota.runningCount || 0 }}/{{ aiQuota.runningLimit || 0 }}</span>
            <span>本月成本 {{ aiQuota.monthlyCostUsedCents || 0 }}/{{ aiQuota.monthlyCostLimitCents || 0 }}</span>
          </div>
        </div>
      </div>
    </div>

    <div v-if="hasAppBlueprint" class="panel app-blueprint-panel">
      <div class="panel-header database-header">
        <h2 class="panel-title">应用蓝图</h2>
        <div class="database-header-actions">
          <el-radio-group v-model="appBlueprintView" size="large">
            <el-radio-button label="summary">摘要</el-radio-button>
            <el-radio-button label="diagram">模块图</el-radio-button>
            <el-radio-button label="json">JSON</el-radio-button>
          </el-radio-group>
          <span class="muted">角色：{{ appBlueprint.roles.length }}</span>
          <span class="muted">前台菜单：{{ appBlueprint.frontendMenus.length }}</span>
          <span class="muted">后台菜单：{{ appBlueprint.adminMenus.length }}</span>
        </div>
      </div>
      <div class="app-blueprint-content">
        <div v-show="appBlueprintView === 'summary'" class="app-blueprint-grid">
          <section>
            <h3>角色</h3>
            <el-tag v-for="role in appBlueprint.roles" :key="role.code" effect="plain">
              {{ role.name || role.code }}
            </el-tag>
          </section>
          <section>
            <h3>前台菜单</h3>
            <el-tag v-for="menu in appBlueprint.frontendMenus" :key="menu.code" type="success" effect="plain">
              {{ menu.name || menu.code }}
            </el-tag>
          </section>
          <section>
            <h3>后台菜单</h3>
            <el-tag v-for="menu in appBlueprint.adminMenus" :key="menu.code" type="warning" effect="plain">
              {{ menu.name || menu.code }}
            </el-tag>
          </section>
        </div>
        <AppModuleDiagramView v-show="appBlueprintView === 'diagram'" :blueprint="appBlueprint" />
        <template v-if="appBlueprintView === 'json'">
          <el-input v-model="appBlueprintJson" type="textarea" :rows="12" spellcheck="false" />
          <div class="toolbar compact-toolbar">
            <el-button @click="applyAppBlueprintJson">应用调整</el-button>
          </div>
        </template>
      </div>
    </div>

    <div class="panel designer-panel">
      <div class="panel-header database-header">
        <h2 class="panel-title">数据库设计</h2>
        <div class="database-header-actions">
          <el-radio-group v-model="databaseView" size="large">
            <el-radio-button label="editor">表结构编辑</el-radio-button>
            <el-radio-button label="er">ER 图</el-radio-button>
          </el-radio-group>
          <span class="muted">表数量：{{ database.tables.length }}</span>
        </div>
      </div>
      <template v-if="database.tables.length">
        <DatabaseDesigner v-show="databaseView === 'editor'" v-model="database" />
        <ErDiagramView v-show="databaseView === 'er'" :tables="database.tables" v-model:draft="database.erDiagram" />
      </template>
      <el-empty v-else description="点击生成数据库后，这里会展示可编辑表结构" />
    </div>

    <div class="panel blueprint-panel">
      <div class="panel-header database-header">
        <h2 class="panel-title">业务蓝图草稿</h2>
        <span class="muted">动作数量：{{ database.businessActions.length }}</span>
      </div>
      <div v-if="database.businessActions.length" class="blueprint-list">
        <article
          v-for="action in database.businessActions"
          :key="action.code || action.path"
          class="blueprint-action"
        >
          <div class="blueprint-action-header">
            <div>
              <h3>{{ action.name || action.code }}</h3>
              <p class="muted">{{ action.ownerTable || '未指定主表' }}</p>
            </div>
            <el-tag size="small" effect="plain">{{ action.method || 'POST' }}</el-tag>
          </div>
          <div class="blueprint-path">{{ action.path || '-' }}</div>
          <div class="blueprint-meta">
            <span v-if="action.transaction !== false">事务</span>
            <span v-if="Array.isArray(action.requestFields) && action.requestFields.length">
              入参：{{ action.requestFields.join('、') }}
            </span>
          </div>
          <div v-if="actionRuleItems(action).length" class="blueprint-section">
            <strong>规则</strong>
            <ul>
              <li v-for="(rule, ruleIndex) in actionRuleItems(action)" :key="`rule-${ruleIndex}-${rule}`">
                {{ rule }}
              </li>
            </ul>
          </div>
          <div v-if="Array.isArray(action.effects) && action.effects.length" class="blueprint-section">
            <strong>影响</strong>
            <ul>
              <li v-for="(effect, effectIndex) in action.effects" :key="blueprintEffectKey(effect, effectIndex)">
                {{ formatEffect(effect) }}
              </li>
            </ul>
          </div>
        </article>
      </div>
      <el-empty v-else description="保存表结构后点击生成业务蓝图，这里会展示非 CRUD 业务动作" />
    </div>
  </section>
</template>

<script setup>
import { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { DataAnalysis, View } from '@element-plus/icons-vue'
import AppModuleDiagramView from '@/components/AppModuleDiagramView.vue'
import DatabaseDesigner from '@/components/DatabaseDesigner.vue'
import ErDiagramView from '@/components/ErDiagramView.vue'
import { createAiTask, createProject, generateProject, getAiQuota, getAiTask, getDatabase, getProject, listAvailableModules, retryAiTask, saveDatabase, updateProject } from '@/api/project'

const route = useRoute()
const router = useRouter()

const generating = ref(false)
const generatingAppBlueprint = ref(false)
const generatingBusinessBlueprint = ref(false)
const saving = ref(false)
const previewing = ref(false)
const loadingProject = ref(false)
const loadingModules = ref(false)
const databaseView = ref('editor')
const appBlueprintView = ref('summary')
const projectId = ref(normalizeProjectId(route.query.projectId))
const errorMessage = ref('')
const appBlueprint = ref(emptyAppBlueprint())
const appBlueprintJson = ref(formatJson(emptyAppBlueprint()))
const database = ref({ tables: [], sql: '', erDiagram: emptyErDiagram(), businessActions: [] })
const availableModules = ref([])
const activeAiTask = ref(null)
const aiQuota = ref(null)
let stopAiPolling = false
const projectForm = reactive({
  projectName: '',
  keyword: String(route.query.keyword || ''),
  projectDesc: '',
  industryTemplate: '',
  frontendEnabled: true,
  moduleIds: []
})

const LAST_PROJECT_KEY = 'easycode_last_project_id'
const hasAppBlueprint = computed(() => {
  return appBlueprint.value.roles.length > 0 || appBlueprint.value.frontendMenus.length > 0 || appBlueprint.value.adminMenus.length > 0
})

function unwrap(result) {
  return result?.data || result || {}
}

function emptyErDiagram() {
  return {
    positions: {},
    relations: [],
    deletedEdgeIds: []
  }
}

function emptyAppBlueprint() {
  return {
    roles: [],
    frontendMenus: [],
    adminMenus: []
  }
}

function formatJson(value) {
  return JSON.stringify(value || {}, null, 2)
}

function parseMaybeJson(value) {
  if (!value) return {}
  if (typeof value === 'object') return value
  try {
    return JSON.parse(value)
  } catch (error) {
    return {}
  }
}

function normalizeAppBlueprint(payload) {
  const data = parseMaybeJson(unwrap(payload))
  return {
    roles: Array.isArray(data.roles) ? data.roles : [],
    frontendMenus: Array.isArray(data.frontendMenus) ? data.frontendMenus : [],
    adminMenus: Array.isArray(data.adminMenus) ? data.adminMenus : []
  }
}

function syncAppBlueprintJson() {
  appBlueprintJson.value = formatJson(appBlueprint.value)
}

function normalizeErDiagram(value) {
  const source = value && typeof value === 'object' ? value : {}
  return {
    positions: source.positions && typeof source.positions === 'object' ? source.positions : {},
    relations: Array.isArray(source.relations) ? source.relations : [],
    deletedEdgeIds: Array.isArray(source.deletedEdgeIds) ? source.deletedEdgeIds : []
  }
}

function normalizeDatabase(payload) {
  const data = unwrap(payload)
  return {
    tables: Array.isArray(data.tables) ? data.tables : [],
    sql: data.sql || '',
    erDiagram: normalizeErDiagram(data.erDiagram),
    businessActions: Array.isArray(data.businessActions) ? data.businessActions : []
  }
}

function normalizeBusinessActions(payload) {
  const data = unwrap(payload)
  return Array.isArray(data) ? data : []
}

function parseTaskResult(task) {
  if (!task?.resultPayload) return null
  try {
    return JSON.parse(task.resultPayload)
  } catch (error) {
    return task.resultPayload
  }
}

function taskTypeLabel(type) {
  const labels = {
    app_blueprint: '应用蓝图',
    database: '数据库',
    business_blueprint: '业务蓝图'
  }
  return labels[type] || type || 'AI 生成'
}

function taskStatusLabel(status) {
  const labels = {
    QUEUED: '排队中',
    RUNNING: '生成中',
    RETRY_WAITING: '等待重试',
    SUCCEEDED: '已完成',
    FAILED: '失败',
    CANCELED: '已取消'
  }
  return labels[status] || status || '-'
}

function delay(ms) {
  return new Promise((resolve) => window.setTimeout(resolve, ms))
}

function aiTaskPayload(generateType) {
  return {
    generateType,
    projectName: projectForm.projectName,
    projectDesc: projectForm.projectDesc,
    industryTemplate: projectForm.industryTemplate,
    extraRequirements: projectForm.keyword,
    appBlueprint: appBlueprintJson.value
  }
}

function normalizeProjectId(value) {
  const raw = Array.isArray(value) ? value[0] : value
  const id = Number(raw)
  return Number.isFinite(id) && id > 0 ? String(id) : ''
}

function normalizeModuleIds(value) {
  return (Array.isArray(value) ? value : [])
    .map((item) => Number(item))
    .filter((item) => Number.isFinite(item) && item > 0)
}

function moduleLabel(module) {
  const alias = module.moduleAlias ? ` / ${module.moduleAlias}` : ''
  return `${module.moduleName || module.moduleId}${alias}`
}

const ruleTypeLabels = {
  EXISTS: '必须存在',
  NOT_EXISTS: '必须不存在',
  FIELD_EQUALS: '字段等于',
  FIELD_NOT_EQUALS: '字段不等于',
  FIELD_IN: '字段属于',
  NUMBER_GTE: '数值不小于'
}

const effectTypeLabels = {
  UPDATE_FIELD: '更新字段',
  INSERT_ROW: '新增记录',
  UPDATE_FIELDS: '更新多字段',
  SET_STATUS: '设置状态',
  INCREASE_NUMBER: '数值增加',
  DECREASE_NUMBER: '数值减少'
}

function actionRuleItems(action) {
  const rules = []
  if (Array.isArray(action?.rules)) {
    rules.push(...action.rules.map(formatRule).filter(Boolean))
  }
  if (Array.isArray(action?.ruleChecks)) {
    rules.push(...action.ruleChecks.map(formatRule).filter(Boolean))
  }
  return rules
}

function formatRule(rule) {
  if (!rule) return ''
  if (typeof rule === 'string') return rule

  const parts = [ruleTypeLabels[rule.type] || rule.type || '规则']
  const target = formatTarget(rule.targetTable, rule.targetField)
  if (target) parts.push(target)
  if (Array.isArray(rule.conditionFields) && rule.conditionFields.length) {
    parts.push(`条件 ${formatFieldList(rule.conditionFields)}`)
  }
  if (rule.expectedValue) parts.push(`期望 ${rule.expectedValue}`)
  if (Array.isArray(rule.expectedValues) && rule.expectedValues.length) {
    parts.push(`可选 ${formatFieldList(rule.expectedValues)}`)
  }
  if (rule.compareValue) parts.push(`比较 ${rule.compareValue}`)
  if (rule.message) parts.push(`提示 ${rule.message}`)
  return parts.join(' / ')
}

function formatEffect(effect) {
  if (!effect) return ''
  if (typeof effect === 'string') return effect

  const parts = [effect.description || effectTypeLabels[effect.type] || effect.type || '影响']
  const target = formatTarget(effect.targetTable, effect.targetField)
  const values = formatValueMap(effect.values)
  if (target) parts.push(target)
  if (values) parts.push(values)
  if (effect.value) parts.push(`值 ${effect.value}`)
  if (effect.amount) parts.push(`数量 ${effect.amount}`)
  if (effect.minValue) parts.push(`下限 ${effect.minValue}`)
  if (Array.isArray(effect.conditionFields) && effect.conditionFields.length) {
    parts.push(`条件 ${formatFieldList(effect.conditionFields)}`)
  }
  if (effect.message) parts.push(`提示 ${effect.message}`)
  return parts.join(' / ')
}

function blueprintEffectKey(effect, index) {
  if (!effect || typeof effect === 'string') return `effect-${index}-${effect || ''}`
  return `effect-${index}-${effect.type || ''}-${effect.targetTable || ''}-${effect.targetField || ''}`
}

function formatTarget(table, field) {
  if (table && field) return `${table}.${field}`
  return table || field || ''
}

function formatValueMap(values) {
  if (!values || typeof values !== 'object' || Array.isArray(values)) return ''
  return Object.entries(values)
    .map(([key, value]) => `${key}=${value}`)
    .join('，')
}

function formatFieldList(values) {
  return values.filter(Boolean).join('、')
}

function projectPayload() {
  return {
    projectName: projectForm.projectName,
    projectDesc: projectForm.projectDesc,
    requirementKeyword: projectForm.keyword,
    industryTemplate: projectForm.industryTemplate,
    frontendEnabled: projectForm.frontendEnabled,
    moduleIds: normalizeModuleIds(projectForm.moduleIds)
  }
}

function rememberProject(id) {
  if (id) {
    localStorage.setItem(LAST_PROJECT_KEY, String(id))
  }
}

async function loadProjectDraft(value) {
  const id = normalizeProjectId(value)
  if (!id) return

  loadingProject.value = true
  errorMessage.value = ''
  try {
    const [projectResult, databaseResult] = await Promise.all([getProject(id), getDatabase(id)])
    const project = unwrap(projectResult)
    projectId.value = id
    projectForm.projectName = project.projectName || ''
    projectForm.projectDesc = project.projectDesc || ''
    projectForm.keyword = project.requirementKeyword || projectForm.keyword || ''
    projectForm.industryTemplate = project.industryTemplate || ''
    projectForm.frontendEnabled = project.frontendEnabled !== '0'
    projectForm.moduleIds = normalizeModuleIds(project.moduleIds)
    appBlueprint.value = normalizeAppBlueprint(project.appBlueprint)
    syncAppBlueprintJson()
    database.value = normalizeDatabase(databaseResult)
    rememberProject(id)
  } catch (error) {
    errorMessage.value = error.message || '加载项目草稿失败，请从我的项目重新打开'
  } finally {
    loadingProject.value = false
  }
}

async function ensureProject() {
  if (projectId.value) {
    await updateProject(projectId.value, projectPayload())
    return projectId.value
  }

  const result = await createProject(projectPayload())
  const data = unwrap(result)
  projectId.value = data.projectId || data.id

  if (!projectId.value) {
    throw new Error('创建项目成功但未返回项目 ID')
  }

  rememberProject(projectId.value)
  router.replace({
    path: '/generate',
    query: {
      ...route.query,
      projectId: projectId.value
    }
  })

  return projectId.value
}

async function loadModuleOptions() {
  loadingModules.value = true
  try {
    const result = await listAvailableModules()
    availableModules.value = Array.isArray(result) ? result : []
  } catch (error) {
    ElMessage.warning(error.message || '后台功能模块加载失败')
  } finally {
    loadingModules.value = false
  }
}

function validateRequirementInput() {
  if (!projectForm.projectName.trim()) {
    ElMessage.warning('请输入项目名称')
    return false
  }

  if (!projectForm.keyword.trim() && !projectForm.projectDesc.trim()) {
    ElMessage.warning('请输入需求关键词或补充说明')
    return false
  }

  return true
}

async function refreshAiQuota() {
  try {
    aiQuota.value = await getAiQuota()
  } catch (error) {
    aiQuota.value = null
  }
}

function applyAiTaskResult(task) {
  const payload = parseTaskResult(task)
  if (task.generateType === 'app_blueprint') {
    appBlueprint.value = normalizeAppBlueprint(payload)
    syncAppBlueprintJson()
    return
  }
  if (task.generateType === 'database') {
    database.value = normalizeDatabase(payload)
    return
  }
  if (task.generateType === 'business_blueprint') {
    database.value = {
      ...database.value,
      businessActions: normalizeBusinessActions(payload)
    }
  }
}

async function waitForAiTask(id, initialTask) {
  let task = initialTask
  activeAiTask.value = task
  while (!stopAiPolling && task && !['SUCCEEDED', 'FAILED', 'CANCELED'].includes(task.status)) {
    await delay(2000)
    task = await getAiTask(id, task.taskId)
    activeAiTask.value = task
  }

  if (task?.status === 'SUCCEEDED') {
    applyAiTaskResult(task)
    await refreshAiQuota()
    return task
  }

  throw new Error(task?.errorMessage || 'AI 生成任务未完成')
}

async function startAiTask(generateType) {
  const id = await ensureProject()
  const task = await createAiTask(id, aiTaskPayload(generateType))
  return waitForAiTask(id, task)
}

async function handleGenerateAppBlueprint() {
  if (!validateRequirementInput()) {
    return
  }

  generatingAppBlueprint.value = true
  errorMessage.value = ''
  try {
    await startAiTask('app_blueprint')
    ElMessage.success('应用蓝图已生成')
  } catch (error) {
    errorMessage.value = error.message || '生成应用蓝图失败，请稍后重试。'
  } finally {
    generatingAppBlueprint.value = false
  }
}

function applyAppBlueprintJson() {
  try {
    appBlueprint.value = normalizeAppBlueprint(JSON.parse(appBlueprintJson.value || '{}'))
    syncAppBlueprintJson()
    ElMessage.success('应用蓝图已应用')
  } catch (error) {
    ElMessage.warning('应用蓝图 JSON 格式不正确')
  }
}

async function handleGenerateDatabase() {
  if (!validateRequirementInput()) {
    return
  }

  if (!hasAppBlueprint.value) {
    ElMessage.warning('请先生成并确认应用蓝图')
    return
  }

  generating.value = true
  errorMessage.value = ''
  try {
    await startAiTask('database')

    if (!database.value.tables.length) {
      errorMessage.value = '后端暂未返回表结构，请稍后重试或手动添加表。'
    }

    ElMessage.success('数据库结构生成完成')
  } catch (error) {
    errorMessage.value = error.message || '生成数据库失败，请确认后端服务已启动。'
  } finally {
    generating.value = false
  }
}

async function handleGenerateBusinessBlueprint() {
  if (!validateRequirementInput()) {
    return
  }

  if (!database.value.tables.length) {
    ElMessage.warning('请先生成并确认数据库设计')
    return
  }

  generatingBusinessBlueprint.value = true
  errorMessage.value = ''
  try {
    const id = await ensureProject()
    await saveDatabase(id, database.value)
    await waitForAiTask(id, await createAiTask(id, aiTaskPayload('business_blueprint')))
    ElMessage.success('业务蓝图已生成')
  } catch (error) {
    errorMessage.value = error.message || '生成业务蓝图失败，请确认表结构已保存后重试。'
  } finally {
    generatingBusinessBlueprint.value = false
  }
}

async function handleRetryActiveTask() {
  if (!projectId.value || !activeAiTask.value?.taskId) return

  errorMessage.value = ''
  const type = activeAiTask.value.generateType
  if (type === 'app_blueprint') generatingAppBlueprint.value = true
  if (type === 'database') generating.value = true
  if (type === 'business_blueprint') generatingBusinessBlueprint.value = true
  try {
    const task = await retryAiTask(projectId.value, activeAiTask.value.taskId)
    await waitForAiTask(projectId.value, task)
    ElMessage.success(`${taskTypeLabel(type)}已生成`)
  } catch (error) {
    errorMessage.value = error.message || 'AI 生成任务重试失败'
  } finally {
    if (type === 'app_blueprint') generatingAppBlueprint.value = false
    if (type === 'database') generating.value = false
    if (type === 'business_blueprint') generatingBusinessBlueprint.value = false
  }
}

async function handleSaveDatabase() {
  if (!projectId.value) return

  saving.value = true
  try {
    await saveDatabase(projectId.value, database.value)
    ElMessage.success('表结构已保存')
  } finally {
    saving.value = false
  }
}

async function handlePreview() {
  if (!projectId.value) return

  previewing.value = true
  try {
    await saveDatabase(projectId.value, database.value)
    await generateProject(projectId.value)
    router.push(`/project/${projectId.value}/preview`)
  } catch (error) {
    errorMessage.value = error.message || '生成项目预览失败，请稍后重试。'
  } finally {
    previewing.value = false
  }
}

watch(
  () => route.query.projectId,
  (value) => {
    const id = normalizeProjectId(value)
    if (id && id !== projectId.value) {
      loadProjectDraft(id)
    }
  }
)

onMounted(() => {
  refreshAiQuota()
  loadModuleOptions()
  if (projectId.value) {
    loadProjectDraft(projectId.value)
  }
})

onBeforeUnmount(() => {
  stopAiPolling = true
})
</script>

<style scoped lang="scss">
.generate-page {
  display: grid;
  gap: 18px;
}

.content {
  display: grid;
  gap: 16px;
  padding: 20px;
}

.project-form {
  max-width: 980px;
}

.module-select {
  width: 100%;
}

.error-alert {
  max-width: 980px;
}

.designer-panel {
  overflow: hidden;
}

.app-blueprint-content {
  display: grid;
  gap: 16px;
  padding: 20px;
}

.app-blueprint-grid {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.app-blueprint-grid section {
  align-content: start;
  border: 1px solid var(--border-color);
  border-radius: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  min-height: 96px;
  padding: 14px;
}

.app-blueprint-grid h3 {
  flex-basis: 100%;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.4;
  margin: 0;
}

.compact-toolbar {
  justify-content: flex-end;
}

.blueprint-list {
  display: grid;
  gap: 14px;
  padding: 20px;
}

.blueprint-action {
  border: 1px solid var(--border-color);
  border-radius: 8px;
  display: grid;
  gap: 10px;
  padding: 16px;
}

.blueprint-action-header {
  align-items: flex-start;
  display: flex;
  gap: 12px;
  justify-content: space-between;
}

.blueprint-action h3 {
  font-size: 16px;
  font-weight: 700;
  line-height: 1.3;
  margin: 0 0 4px;
}

.blueprint-path {
  background: #f6f8fb;
  border-radius: 6px;
  color: #2c3e50;
  font-family: Consolas, Monaco, monospace;
  font-size: 13px;
  padding: 8px 10px;
  word-break: break-all;
}

.blueprint-meta {
  color: #64748b;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 14px;
  font-size: 13px;
}

.blueprint-section {
  display: grid;
  gap: 6px;
}

.blueprint-section strong {
  color: #1f2d3d;
  font-size: 13px;
}

.blueprint-section ul {
  color: #475569;
  display: grid;
  gap: 4px;
  margin: 0;
  padding-left: 18px;
}

.database-header {
  gap: 16px;
}

.database-header-actions {
  display: flex;
  align-items: center;
  gap: 18px;
}

.ai-task-strip {
  display: grid;
  gap: 12px;
  max-width: 980px;
}

.ai-task-card {
  border: 1px solid var(--border-color);
  border-radius: 8px;
  display: grid;
  gap: 8px;
  padding: 12px;
}

.ai-task-card-header,
.ai-quota-card {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.task-error {
  color: #c2410c;
  font-size: 13px;
  margin: 0;
}

@media (max-width: 860px) {
  .panel-header {
    align-items: stretch;
    flex-direction: column;
  }

  .database-header-actions {
    align-items: flex-start;
    flex-direction: column;
  }

  .app-blueprint-grid {
    grid-template-columns: 1fr;
  }
}
</style>
