<template>
  <div class="page-container">
    <h2 class="page-title">数据脱敏</h2>
    <el-tabs v-model="activeTab" type="border-card">
      <el-tab-pane label="脱敏策略" name="rules">
        <div class="section-header" style="margin-bottom: 12px;">
          <el-button type="primary" size="small" @click="handleAddRule">
            <el-icon><Plus /></el-icon>新增策略
          </el-button>
        </div>
        <el-table :data="ruleList" v-loading="ruleLoading" stripe size="default" border>
          <el-table-column prop="name" label="策略名称" min-width="140" />
          <el-table-column prop="algorithm" label="算法" width="100">
            <template #default="{ row }">
              <el-tag size="small" type="info">{{ algorithmText(row.algorithm) }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="level_name" label="关联分级" width="120" />
          <el-table-column prop="category_name" label="关联分类" width="120" />
          <el-table-column prop="description" label="描述" min-width="150" show-overflow-tooltip />
          <el-table-column label="操作" width="140" fixed="right">
            <template #default="{ row }">
              <el-button type="primary" link size="small" @click="handleEditRule(row)">编辑</el-button>
              <el-button type="danger" link size="small" @click="handleDeleteRule(row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-tab-pane>
      <el-tab-pane label="脱敏预览" name="preview">
        <div class="preview-form card-shadow" style="padding: 16px; margin-bottom: 16px;">
          <el-form :model="previewForm" inline>
            <el-form-item label="数据源">
              <el-select v-model="previewForm.source_id" placeholder="选择数据源" style="width: 180px" @change="onSourceChange">
                <el-option v-for="s in dataSources" :key="s.id" :label="s.name" :value="s.id" />
              </el-select>
            </el-form-item>
            <el-form-item label="数据表">
              <el-select v-model="previewForm.table_name" placeholder="选择表" style="width: 180px">
                <el-option v-for="t in tables" :key="t.name" :label="t.name" :value="t.name" />
              </el-select>
            </el-form-item>
            <el-form-item label="项目">
              <el-select v-model="previewForm.project_id" placeholder="选择项目（可选）" clearable style="width: 180px">
                <el-option v-for="p in projects" :key="p.id" :label="p.name" :value="p.id" />
              </el-select>
            </el-form-item>
            <el-form-item>
              <el-button type="primary" :loading="previewLoading" @click="handlePreview">预览脱敏</el-button>
            </el-form-item>
          </el-form>
        </div>
        <div v-if="previewResult.columns" class="preview-result card-shadow" style="padding: 16px;">
          <div style="font-weight: 600; margin-bottom: 12px;">脱敏预览（前 {{ previewResult.total_rows }} 行）</div>
          <el-table :data="previewResult.rows" stripe size="small" border>
            <el-table-column
              v-for="col in previewResult.columns"
              :key="col.name"
              :prop="col.name"
              :label="col.name + (col.has_rule ? ' LOCK' : '')"
              min-width="120"
            />
          </el-table>
        </div>
      </el-tab-pane>
    </el-tabs>
    <el-dialog v-model="ruleDialogVisible" :title="isEditRule ? '编辑策略' : '新增策略'" width="520px" destroy-on-close>
      <el-form ref="ruleFormRef" :model="ruleForm" :rules="ruleRules" label-width="100px">
        <el-form-item label="策略名称" prop="name">
          <el-input v-model="ruleForm.name" placeholder="策略名称" />
        </el-form-item>
        <el-form-item label="脱敏算法" prop="algorithm">
          <el-select v-model="ruleForm.algorithm" placeholder="选择算法" style="width: 100%">
            <el-option label="掩码 (mask)" value="mask" />
            <el-option label="截断 (truncate)" value="truncate" />
            <el-option label="哈希 (hash)" value="hash" />
            <el-option label="泛化 (generalize)" value="generalize" />
            <el-option label="替换 (replace)" value="replace" />
          </el-select>
        </el-form-item>
        <el-form-item label="关联分级">
          <el-select v-model="ruleForm.level_id" placeholder="选择分级（可选）" clearable style="width: 100%">
            <el-option v-for="l in levels" :key="l.id" :label="l.name" :value="l.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="关联分类">
          <el-cascader
            v-model="ruleForm.category_id"
            :options="categoryTree"
            :props="{ value: 'id', label: 'name', checkStrictly: true, emitPath: false }"
            clearable
            placeholder="选择分类（可选）"
            style="width: 100%"
          />
        </el-form-item>
        <el-form-item label="算法参数">
          <el-input v-model="ruleForm.paramsText" type="textarea" :rows="3" placeholder='JSON格式，如 {"keep_prefix":3, "keep_suffix":4}' />
        </el-form-item>
        <el-form-item label="描述">
          <el-input v-model="ruleForm.description" type="textarea" :rows="2" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="ruleDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="submitLoading" @click="handleSubmitRule">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import { getMaskingRules, createMaskingRule, updateMaskingRule, deleteMaskingRule, previewMasking } from '@/api/masking'
import { getDataSources } from '@/api/datasource'
import { getProjects } from '@/api/project'
import { getDataLevels, getCategoryTree } from '@/api/classification'
import { getMetadataTree } from '@/api/metadata'

const activeTab = ref('rules')
const ruleLoading = ref(false)
const ruleList = ref<any[]>([])
const ruleDialogVisible = ref(false)
const isEditRule = ref(false)
const ruleEditId = ref<number | null>(null)
const submitLoading = ref(false)
const ruleFormRef = ref()
const ruleForm = reactive({ name: '', algorithm: 'mask', level_id: undefined as number | undefined, category_id: undefined as number | undefined, paramsText: '', description: '' })
const ruleRules = { name: [{ required: true, message: '请输入策略名称', trigger: 'blur' }], algorithm: [{ required: true, message: '请选择算法', trigger: 'change' }] }
const levels = ref<any[]>([])
const categoryTree = ref<any[]>([])
const dataSources = ref<any[]>([])
const tables = ref<any[]>([])
const projects = ref<any[]>([])
const previewForm = reactive({ source_id: undefined as number | undefined, table_name: '', project_id: undefined as number | undefined })
const previewLoading = ref(false)
const previewResult = ref<any>({})

function algorithmText(v: string) {
  const map: Record<string, string> = { mask: '掩码', truncate: '截断', hash: '哈希', generalize: '泛化', replace: '替换' }
  return map[v] || v
}

async function fetchRules() {
  ruleLoading.value = true
  try {
    const res: any = await getMaskingRules()
    ruleList.value = res.data || []
  } catch (e: any) { ElMessage.error(e?.message || '加载失败') }
  finally { ruleLoading.value = false }
}

function handleAddRule() {
  isEditRule.value = false
  ruleEditId.value = null
  ruleForm.name = ''
  ruleForm.algorithm = 'mask'
  ruleForm.level_id = undefined
  ruleForm.category_id = undefined
  ruleForm.paramsText = ''
  ruleForm.description = ''
  ruleDialogVisible.value = true
}

function handleEditRule(row: any) {
  isEditRule.value = true
  ruleEditId.value = row.id
  ruleForm.name = row.name
  ruleForm.algorithm = row.algorithm
  ruleForm.level_id = row.level_id
  ruleForm.category_id = row.category_id
  ruleForm.paramsText = row.params ? JSON.stringify(row.params) : ''
  ruleForm.description = row.description || ''
  ruleDialogVisible.value = true
}

async function handleSubmitRule() {
  const valid = await ruleFormRef.value?.validate().catch(() => false)
  if (!valid) return
  submitLoading.value = true
  try {
    const payload: any = { name: ruleForm.name, algorithm: ruleForm.algorithm, level_id: ruleForm.level_id, category_id: ruleForm.category_id, description: ruleForm.description }
    if (ruleForm.paramsText) {
      try { payload.params = JSON.parse(ruleForm.paramsText) } catch { ElMessage.error('参数JSON格式错误'); return }
    }
    if (isEditRule.value && ruleEditId.value) {
      await updateMaskingRule(ruleEditId.value, payload)
    } else {
      await createMaskingRule(payload)
    }
    ElMessage.success('保存成功')
    ruleDialogVisible.value = false
    fetchRules()
  } catch (e: any) { ElMessage.error(e?.message || '保存失败') }
  finally { submitLoading.value = false }
}

async function handleDeleteRule(row: any) {
  try {
    await ElMessageBox.confirm('确认删除该策略？', '提示', { type: 'warning' })
    await deleteMaskingRule(row.id)
    ElMessage.success('删除成功')
    fetchRules()
  } catch (e: any) { if (e !== 'cancel') ElMessage.error(e?.message || '删除失败') }
}

async function onSourceChange(sourceId: number) {
  tables.value = []
  previewForm.table_name = ''
  try {
    const res: any = await getMetadataTree(sourceId)
    const sourceNode = (res.data || []).find((s: any) => s.id === sourceId)
    if (sourceNode) {
      const allTables: any[] = []
      sourceNode.children?.forEach((db: any) => {
        db.children?.forEach((t: any) => allTables.push(t))
      })
      tables.value = allTables
    }
  } catch (e) { /* ignore */ }
}

async function handlePreview() {
  if (!previewForm.source_id || !previewForm.table_name) {
    ElMessage.warning('请选择数据源和表')
    return
  }
  previewLoading.value = true
  try {
    const res: any = await previewMasking(previewForm.source_id, previewForm.table_name, previewForm.project_id, 20)
    previewResult.value = res.data || {}
  } catch (e: any) { ElMessage.error(e?.message || '预览失败') }
  finally { previewLoading.value = false }
}

async function fetchMeta() {
  try {
    const [sRes, pRes, lRes, cRes] = await Promise.all([
      getDataSources(), getProjects({ page: 1, page_size: 100 }),
      getDataLevels(), getCategoryTree()
    ])
    dataSources.value = (sRes as any)?.data || []
    projects.value = (pRes as any)?.data || []
    levels.value = (lRes as any)?.data || []
    categoryTree.value = (cRes as any)?.data || []
  } catch (e) { /* ignore */ }
}

onMounted(() => { fetchRules(); fetchMeta() })
</script>
