<template>
  <div class="scene-slot-bundle-page">
    <div class="page-header">
      <div class="header-content">
        <div class="title-section">
          <h1 class="page-title">场景槽位包管理</h1>
          <p class="page-desc">配置场景与槽位的映射关系，定义每个场景需要采集的槽位集合。[AC-SCENE-SLOT-01]</p>
        </div>
        <div class="header-actions">
          <el-select v-model="filterStatus" placeholder="按状态筛选" clearable style="width: 140px;">
            <el-option
              v-for="opt in SCENE_SLOT_BUNDLE_STATUS_OPTIONS"
              :key="opt.value"
              :label="opt.label"
              :value="opt.value"
            />
          </el-select>
          <el-button type="primary" @click="handleCreate">
            <el-icon><Plus /></el-icon>
            新建场景槽位包
          </el-button>
        </div>
      </div>
    </div>

    <el-card shadow="hover" class="bundle-card" v-loading="loading">
      <el-table :data="bundles" stripe style="width: 100%">
        <el-table-column prop="scene_key" label="场景标识" min-width="140">
          <template #default="{ row }">
            <code class="scene-key">{{ row.scene_key }}</code>
          </template>
        </el-table-column>
        <el-table-column prop="scene_name" label="场景名称" min-width="120" />
        <el-table-column prop="status" label="状态" width="100">
          <template #default="{ row }">
            <el-tag :type="getStatusTagType(row.status)" size="small">
              {{ getStatusLabel(row.status) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="required_slots" label="必填槽位" min-width="160">
          <template #default="{ row }">
            <div class="slot-tags">
              <el-tag
                v-for="slotKey in row.required_slots.slice(0, 3)"
                :key="slotKey"
                size="small"
                type="danger"
                class="slot-tag"
              >
                {{ slotKey }}
              </el-tag>
              <el-tag v-if="row.required_slots.length > 3" size="small" type="info">
                +{{ row.required_slots.length - 3 }}
              </el-tag>
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="optional_slots" label="可选槽位" min-width="140">
          <template #default="{ row }">
            <div class="slot-tags" v-if="row.optional_slots.length > 0">
              <el-tag
                v-for="slotKey in row.optional_slots.slice(0, 3)"
                :key="slotKey"
                size="small"
                type="info"
                class="slot-tag"
              >
                {{ slotKey }}
              </el-tag>
              <el-tag v-if="row.optional_slots.length > 3" size="small" type="info">
                +{{ row.optional_slots.length - 3 }}
              </el-tag>
            </div>
            <span v-else class="no-value">-</span>
          </template>
        </el-table-column>
        <el-table-column prop="completion_threshold" label="完成阈值" width="100">
          <template #default="{ row }">
            <span>{{ (row.completion_threshold * 100).toFixed(0) }}%</span>
          </template>
        </el-table-column>
        <el-table-column prop="ask_back_order" label="追问策略" width="100">
          <template #default="{ row }">
            <span>{{ getAskBackOrderLabel(row.ask_back_order) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="150" fixed="right">
          <template #default="{ row }">
            <el-button type="primary" link size="small" @click="handleEdit(row)">
              <el-icon><Edit /></el-icon>
              编辑
            </el-button>
            <el-button type="danger" link size="small" @click="handleDelete(row)">
              <el-icon><Delete /></el-icon>
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-empty v-if="!loading && bundles.length === 0" description="暂无场景槽位包" />
    </el-card>

    <el-dialog
      v-model="dialogVisible"
      :title="isEdit ? '编辑场景槽位包' : '新建场景槽位包'"
      width="800px"
      :close-on-click-modal="false"
      destroy-on-close
    >
      <el-form :model="formData" :rules="formRules" ref="formRef" label-width="100px">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="场景标识" prop="scene_key">
              <el-input
                v-model="formData.scene_key"
                placeholder="如：open_consult, refund_apply"
                :disabled="isEdit"
              />
              <div class="field-hint">唯一标识，创建后不可修改</div>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="场景名称" prop="scene_name">
              <el-input v-model="formData.scene_name" placeholder="如：开放咨询、退款申请" />
            </el-form-item>
          </el-col>
        </el-row>
        
        <el-form-item label="场景描述" prop="description">
          <el-input
            v-model="formData.description"
            type="textarea"
            :rows="2"
            placeholder="描述该场景的业务背景和用途"
          />
        </el-form-item>

        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="状态" prop="status">
              <el-select v-model="formData.status" style="width: 100%;">
                <el-option
                  v-for="opt in SCENE_SLOT_BUNDLE_STATUS_OPTIONS"
                  :key="opt.value"
                  :label="opt.label"
                  :value="opt.value"
                >
                  <div class="status-option">
                    <span>{{ opt.label }}</span>
                    <span class="status-desc">{{ opt.description }}</span>
                  </div>
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="完成阈值" prop="completion_threshold">
              <el-slider
                v-model="formData.completion_threshold"
                :min="0"
                :max="1"
                :step="0.1"
                :format-tooltip="(val: number) => `${(val * 100).toFixed(0)}%`"
              />
              <div class="field-hint">必填槽位填充比例达到此值视为完成</div>
            </el-form-item>
          </el-col>
        </el-row>

        <el-form-item label="必填槽位" prop="required_slots">
          <el-select
            v-model="formData.required_slots"
            multiple
            filterable
            style="width: 100%;"
            placeholder="选择必填槽位"
          >
            <el-option
              v-for="slot in availableSlots"
              :key="slot.id"
              :label="`${slot.slot_key} (${slot.ask_back_prompt || '无追问提示'})`"
              :value="slot.slot_key"
              :disabled="formData.optional_slots.includes(slot.slot_key)"
            >
              <div class="slot-option">
                <span class="slot-key-label">{{ slot.slot_key }}</span>
                <el-tag size="small" type="info">{{ slot.type }}</el-tag>
              </div>
            </el-option>
          </el-select>
          <div class="field-hint">缺失必填槽位时会触发追问，不会直接进行 KB 检索</div>
        </el-form-item>

        <el-form-item label="可选槽位" prop="optional_slots">
          <el-select
            v-model="formData.optional_slots"
            multiple
            filterable
            style="width: 100%;"
            placeholder="选择可选槽位"
          >
            <el-option
              v-for="slot in availableSlots"
              :key="slot.id"
              :label="slot.slot_key"
              :value="slot.slot_key"
              :disabled="formData.required_slots.includes(slot.slot_key)"
            >
              <div class="slot-option">
                <span class="slot-key-label">{{ slot.slot_key }}</span>
                <el-tag size="small" type="info">{{ slot.type }}</el-tag>
              </div>
            </el-option>
          </el-select>
          <div class="field-hint">可选槽位用于增强检索效果，缺失时不阻塞流程</div>
        </el-form-item>

        <el-form-item label="槽位优先级" prop="slot_priority">
          <div class="priority-editor">
            <div class="priority-header">
              <span class="priority-hint">拖拽调整槽位采集和追问的优先级顺序</span>
              <el-button
                v-if="formData.slot_priority && formData.slot_priority.length > 0"
                type="danger"
                link
                size="small"
                @click="formData.slot_priority = null"
              >
                清空
              </el-button>
            </div>
            
            <div v-if="allSlotsForPriority.length > 0" class="priority-list-wrapper">
              <draggable
                v-model="allSlotsForPriority"
                item-key="slot_key"
                handle=".drag-handle"
                class="priority-list"
                ghost-class="ghost"
              >
                <template #item="{ element, index }">
                  <div class="priority-item" :class="{ 'in-priority': isInPriority(element.slot_key) }">
                    <el-icon class="drag-handle"><Rank /></el-icon>
                    <span class="priority-order">{{ index + 1 }}</span>
                    <el-tag
                      size="small"
                      :type="formData.required_slots.includes(element.slot_key) ? 'danger' : 'info'"
                    >
                      {{ element.slot_key }}
                    </el-tag>
                    <el-tag size="small" type="warning" v-if="formData.required_slots.includes(element.slot_key)">
                      必填
                    </el-tag>
                  </div>
                </template>
              </draggable>
            </div>
            <div v-else class="priority-empty">
              <el-text type="info">请先添加必填或可选槽位</el-text>
            </div>
          </div>
        </el-form-item>

        <el-form-item label="追问策略" prop="ask_back_order">
          <el-radio-group v-model="formData.ask_back_order">
            <el-radio-button
              v-for="opt in ASK_BACK_ORDER_OPTIONS"
              :key="opt.value"
              :value="opt.value"
            >
              {{ opt.label }}
            </el-radio-button>
          </el-radio-group>
          <div class="field-hint">
            {{ ASK_BACK_ORDER_OPTIONS.find(o => o.value === formData.ask_back_order)?.description }}
          </div>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="submitting" @click="handleSubmit">
          {{ isEdit ? '保存' : '创建' }}
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, watch, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Edit, Delete, Rank } from '@element-plus/icons-vue'
import type { FormInstance, FormRules } from 'element-plus'
import draggable from 'vuedraggable'
import { sceneSlotBundleApi } from '@/api/scene-slot-bundle'
import { slotDefinitionApi } from '@/api/slot-definition'
import {
  SCENE_SLOT_BUNDLE_STATUS_OPTIONS,
  ASK_BACK_ORDER_OPTIONS,
  type SceneSlotBundle,
  type SceneSlotBundleCreateRequest,
  type SceneSlotBundleUpdateRequest,
  type SceneSlotBundleStatus,
  type AskBackOrder,
  getStatusLabel,
  getAskBackOrderLabel,
} from '@/types/scene-slot-bundle'
import type { SlotDefinition } from '@/types/slot-definition'

const loading = ref(false)
const bundles = ref<SceneSlotBundle[]>([])
const availableSlots = ref<SlotDefinition[]>([])
const filterStatus = ref<SceneSlotBundleStatus | ''>('')
const dialogVisible = ref(false)
const isEdit = ref(false)
const submitting = ref(false)
const formRef = ref<FormInstance>()

const formData = reactive({
  id: '',
  scene_key: '',
  scene_name: '',
  description: '',
  required_slots: [] as string[],
  optional_slots: [] as string[],
  slot_priority: null as string[] | null,
  completion_threshold: 1.0,
  ask_back_order: 'priority' as AskBackOrder,
  status: 'draft' as SceneSlotBundleStatus,
})

const formRules: FormRules = {
  scene_key: [
    { required: true, message: '请输入场景标识', trigger: 'blur' },
    { pattern: /^[a-z][a-z0-9_]*$/, message: '以小写字母开头，仅允许小写字母、数字、下划线', trigger: 'blur' }
  ],
  scene_name: [{ required: true, message: '请输入场景名称', trigger: 'blur' }],
  status: [{ required: true, message: '请选择状态', trigger: 'change' }],
}

const getStatusTagType = (status: SceneSlotBundleStatus): 'success' | 'warning' | 'info' => {
  const typeMap: Record<SceneSlotBundleStatus, 'success' | 'warning' | 'info'> = {
    'active': 'success',
    'draft': 'warning',
    'deprecated': 'info',
  }
  return typeMap[status] || 'info'
}

const allSlotsForPriority = computed({
  get: () => {
    const allKeys = [...formData.required_slots, ...formData.optional_slots]
    const priority = formData.slot_priority || allKeys
    
    const orderedSlots = priority
      .filter(key => allKeys.includes(key))
      .map(key => availableSlots.value.find(s => s.slot_key === key) || { slot_key: key })
    
    const remainingKeys = allKeys.filter(key => !priority.includes(key))
    const remainingSlots = remainingKeys
      .map(key => availableSlots.value.find(s => s.slot_key === key) || { slot_key: key })
    
    return [...orderedSlots, ...remainingSlots]
  },
  set: (value: { slot_key: string }[]) => {
    formData.slot_priority = value.map(s => s.slot_key)
  }
})

const isInPriority = (slotKey: string): boolean => {
  if (!formData.slot_priority) return true
  return formData.slot_priority.includes(slotKey)
}

const fetchBundles = async () => {
  loading.value = true
  try {
    const res = await sceneSlotBundleApi.list(filterStatus.value || undefined)
    bundles.value = res || []
  } catch (error: any) {
    ElMessage.error(error.response?.data?.message || '获取场景槽位包列表失败')
  } finally {
    loading.value = false
  }
}

const fetchAvailableSlots = async () => {
  try {
    const res = await slotDefinitionApi.list()
    availableSlots.value = res || []
  } catch (error: any) {
    console.error('获取槽位定义失败', error)
  }
}

const handleCreate = () => {
  isEdit.value = false
  Object.assign(formData, {
    id: '',
    scene_key: '',
    scene_name: '',
    description: '',
    required_slots: [],
    optional_slots: [],
    slot_priority: null,
    completion_threshold: 1.0,
    ask_back_order: 'priority',
    status: 'draft',
  })
  dialogVisible.value = true
}

const handleEdit = (bundle: SceneSlotBundle) => {
  isEdit.value = true
  Object.assign(formData, {
    id: bundle.id,
    scene_key: bundle.scene_key,
    scene_name: bundle.scene_name,
    description: bundle.description || '',
    required_slots: [...bundle.required_slots],
    optional_slots: [...bundle.optional_slots],
    slot_priority: bundle.slot_priority ? [...bundle.slot_priority] : null,
    completion_threshold: bundle.completion_threshold,
    ask_back_order: bundle.ask_back_order,
    status: bundle.status,
  })
  dialogVisible.value = true
}

const handleDelete = async (bundle: SceneSlotBundle) => {
  try {
    await ElMessageBox.confirm(
      `确定要删除场景槽位包「${bundle.scene_name}」吗？`,
      '删除确认',
      { type: 'warning' }
    )
    await sceneSlotBundleApi.delete(bundle.id)
    ElMessage.success('删除成功')
    fetchBundles()
  } catch (error: any) {
    if (error !== 'cancel') {
      ElMessage.error(error.response?.data?.message || '删除失败')
    }
  }
}

const handleSubmit = async () => {
  if (!formRef.value) return

  await formRef.value.validate(async (valid) => {
    if (!valid) return

    submitting.value = true
    try {
      const data: SceneSlotBundleCreateRequest | SceneSlotBundleUpdateRequest = {
        scene_name: formData.scene_name,
        description: formData.description || undefined,
        required_slots: formData.required_slots.length > 0 ? formData.required_slots : undefined,
        optional_slots: formData.optional_slots.length > 0 ? formData.optional_slots : undefined,
        slot_priority: formData.slot_priority || undefined,
        completion_threshold: formData.completion_threshold,
        ask_back_order: formData.ask_back_order,
        status: formData.status,
      }

      if (isEdit.value) {
        await sceneSlotBundleApi.update(formData.id, data as SceneSlotBundleUpdateRequest)
        ElMessage.success('更新成功')
      } else {
        const createData = data as SceneSlotBundleCreateRequest
        createData.scene_key = formData.scene_key
        await sceneSlotBundleApi.create(createData)
        ElMessage.success('创建成功')
      }

      dialogVisible.value = false
      fetchBundles()
    } catch (error: any) {
      ElMessage.error(error.response?.data?.message || '操作失败')
    } finally {
      submitting.value = false
    }
  })
}

watch(filterStatus, () => {
  fetchBundles()
})

onMounted(() => {
  fetchBundles()
  fetchAvailableSlots()
})
</script>

<style scoped lang="scss">
.scene-slot-bundle-page {
  padding: 20px;
}

.page-header {
  margin-bottom: 24px;
}

.header-content {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}

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

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

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

.bundle-card {
  border-radius: 8px;
}

.scene-key {
  padding: 2px 6px;
  background-color: var(--el-fill-color-light);
  border-radius: 4px;
  font-family: monospace;
  font-size: 12px;
}

.slot-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.slot-tag {
  margin: 0;
}

.no-value {
  color: var(--el-text-color-placeholder);
}

.field-hint {
  margin-top: 4px;
  font-size: 12px;
  color: var(--el-text-color-secondary);
}

.status-option {
  display: flex;
  flex-direction: column;
  gap: 2px;

  .status-desc {
    font-size: 12px;
    color: var(--el-text-color-secondary);
  }
}

.slot-option {
  display: flex;
  align-items: center;
  gap: 8px;

  .slot-key-label {
    font-weight: 500;
    font-family: monospace;
  }
}

.priority-editor {
  border: 1px solid var(--el-border-color);
  border-radius: 4px;
  padding: 12px;
  background-color: var(--el-fill-color-light);
}

.priority-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.priority-hint {
  font-size: 12px;
  color: var(--el-text-color-secondary);
}

.priority-list-wrapper {
  max-height: 300px;
  overflow-y: auto;
}

.priority-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.priority-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background-color: var(--el-bg-color);
  border-radius: 4px;
  border: 1px solid var(--el-border-color-light);
  cursor: move;
  transition: all 0.2s;

  &:hover {
    border-color: var(--el-color-primary-light-5);
  }

  &.in-priority {
    background-color: var(--el-color-primary-light-9);
  }
}

.drag-handle {
  cursor: move;
  color: var(--el-text-color-secondary);
  font-size: 16px;
}

.priority-order {
  width: 20px;
  text-align: center;
  font-weight: 600;
  color: var(--el-text-color-secondary);
}

.priority-empty {
  text-align: center;
  padding: 20px;
  color: var(--el-text-color-secondary);
}

.ghost {
  opacity: 0.5;
  background: var(--el-color-primary-light-8);
}
</style>
