<template>
  <div>
    <h2 style="margin-bottom:12px">风控配置</h2>
    <p style="margin:0 0 24px;color:#606266">
      管理敏感词库与全局风控规则，保障平台安全运行。
    </p>

    <!-- 全局风控规则 -->
    <el-card style="margin-bottom: 16px">
      <template #header>
        <span>全局风控规则</span>
      </template>
      <el-form :model="ruleForm" label-width="160px" :label-position="isMobile ? 'top' : 'right'">
        <el-form-item label="IP限流阈值（次/分）">
          <el-input-number v-model="ruleForm.ipRateLimit" :min="10" :max="10000" />
        </el-form-item>
        <el-form-item label="登录失败次数阈值">
          <el-input-number v-model="ruleForm.loginFailThreshold" :min="3" :max="20" />
        </el-form-item>
        <el-form-item label="登录失败锁定时长（分）">
          <el-input-number v-model="ruleForm.loginLockMinutes" :min="5" :max="1440" />
        </el-form-item>
        <el-form-item label="账号异常检测">
          <el-switch v-model="ruleForm.abnormalDetection" active-text="开启" inactive-text="关闭" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="saveRules" :loading="ruleLoading">保存配置</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 敏感词库 -->
    <el-card>
      <template #header>
        <div class="card-header">
          <span>敏感词库</span>
          <el-button type="primary" @click="openDialog()">新增敏感词</el-button>
        </div>
      </template>

      <el-table :data="wordList" v-loading="tableLoading" border stripe>
        <el-table-column prop="word" label="敏感词" min-width="160" />
        <el-table-column prop="level" label="风险等级" width="120">
          <template #default="{ row }">
            <el-tag :type="levelTagType(row.level)">{{ row.level }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="category" label="分类" width="140" />
        <el-table-column prop="enabled" label="状态" width="100">
          <template #default="{ row }">
            <el-switch v-model="row.enabled" @change="toggleWord(row)" />
          </template>
        </el-table-column>
        <el-table-column prop="updatedAt" label="更新时间" width="180">
          <template #default="{ row }">{{ fmt(row.updatedAt) }}</template>
        </el-table-column>
        <el-table-column label="操作" width="140" fixed="right">
          <template #default="{ row }">
            <el-button link type="primary" @click="openDialog(row)">编辑</el-button>
            <el-button link type="danger" @click="deleteWord(row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <div class="pagination-wrap">
        <el-pagination
          v-model:current-page="page"
          v-model:page-size="size"
          :page-sizes="[10, 20, 50]"
          :total="total"
          layout="total, sizes, prev, pager, next"
          @size-change="loadWords"
          @current-change="loadWords"
        />
      </div>
    </el-card>

    <!-- 新增/编辑弹窗 -->
    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="520px" destroy-on-close>
      <el-form ref="formRef" :model="form" :rules="formRules" label-width="100px">
        <el-form-item label="敏感词" prop="word">
          <el-input v-model="form.word" placeholder="请输入敏感词" />
        </el-form-item>
        <el-form-item label="风险等级" prop="level">
          <el-select v-model="form.level" placeholder="请选择风险等级" style="width:100%">
            <el-option label="低" value="低" />
            <el-option label="中" value="中" />
            <el-option label="高" value="高" />
          </el-select>
        </el-form-item>
        <el-form-item label="分类" prop="category">
          <el-input v-model="form.category" placeholder="如：政治、色情、广告" />
        </el-form-item>
        <el-form-item label="启用状态">
          <el-switch v-model="form.enabled" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitForm" :loading="submitLoading">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import { opsApi, type RiskRuleForm, type SensitiveWord } from '@/api/ops'

const isMobile = ref(window.innerWidth < 768)
const updateViewport = () => { isMobile.value = window.innerWidth < 768 }
onMounted(() => { window.addEventListener('resize', updateViewport) })

/* ---------- 全局规则 ---------- */
const ruleForm = reactive<RiskRuleForm>({
  ipRateLimit: 300,
  loginFailThreshold: 5,
  loginLockMinutes: 30,
  abnormalDetection: true,
})
const ruleLoading = ref(false)

async function loadRules() {
  try {
    const res = await opsApi.getRiskRules()
    const cfg = res.data.data
    if (cfg) {
      ruleForm.ipRateLimit = cfg.ipRateLimit ?? 300
      ruleForm.loginFailThreshold = cfg.loginFailThreshold ?? 5
      ruleForm.loginLockMinutes = cfg.loginLockMinutes ?? 30
      ruleForm.abnormalDetection = cfg.abnormalDetection ?? true
    }
  } catch {
    // ignore
  }
}

async function saveRules() {
  ruleLoading.value = true
  try {
    await opsApi.saveRiskRules({ ...ruleForm })
    ElMessage.success('配置已保存')
  } catch {
    ElMessage.error('保存失败')
  } finally {
    ruleLoading.value = false
  }
}

/* ---------- 敏感词 ---------- */
const wordList = ref<SensitiveWord[]>([])
const tableLoading = ref(false)
const page = ref(1)
const size = ref(20)
const total = ref(0)

const dialogVisible = ref(false)
const dialogTitle = ref('新增敏感词')
const formRef = ref<FormInstance>()
const submitLoading = ref(false)
const isEdit = ref(false)

const form = reactive<Partial<SensitiveWord>>({
  word: '',
  level: '中',
  category: '',
  enabled: true,
})

const formRules: FormRules = {
  word: [{ required: true, message: '请输入敏感词', trigger: 'blur' }],
  level: [{ required: true, message: '请选择风险等级', trigger: 'change' }],
  category: [{ required: true, message: '请输入分类', trigger: 'blur' }],
}

function levelTagType(level: string) {
  if (level === '高') return 'danger'
  if (level === '中') return 'warning'
  return 'info'
}

async function loadWords() {
  tableLoading.value = true
  try {
    const res = await opsApi.listSensitiveWords(page.value - 1, size.value)
    const data = res.data.data
    wordList.value = data.content ?? []
    total.value = data.total ?? 0
  } catch {
    ElMessage.error('加载失败')
  } finally {
    tableLoading.value = false
  }
}

function openDialog(row?: SensitiveWord) {
  isEdit.value = !!row
  dialogTitle.value = row ? '编辑敏感词' : '新增敏感词'
  if (row) {
    Object.assign(form, { ...row })
  } else {
    Object.assign(form, { word: '', level: '中', category: '', enabled: true })
  }
  dialogVisible.value = true
}

async function submitForm() {
  const valid = await formRef.value?.validate().catch(() => false)
  if (!valid) return
  submitLoading.value = true
  try {
    if (isEdit.value && form.id) {
      await opsApi.updateSensitiveWord(form.id, form as SensitiveWord)
    } else {
      await opsApi.createSensitiveWord(form as SensitiveWord)
    }
    ElMessage.success(isEdit.value ? '编辑成功' : '新增成功')
    dialogVisible.value = false
    loadWords()
  } catch {
    ElMessage.error('操作失败')
  } finally {
    submitLoading.value = false
  }
}

async function toggleWord(row: SensitiveWord) {
  try {
    await opsApi.toggleSensitiveWord(row.id, row.enabled)
    ElMessage.success('状态已更新')
  } catch {
    row.enabled = !row.enabled
    ElMessage.error('更新失败')
  }
}

async function deleteWord(row: SensitiveWord) {
  try {
    await ElMessageBox.confirm(`确定删除敏感词「${row.word}」吗？`, '提示', { type: 'warning' })
    await opsApi.deleteSensitiveWord(row.id)
    ElMessage.success('删除成功')
    loadWords()
  } catch {
    // cancel
  }
}

function fmt(value: string) {
  return value ? new Date(value).toLocaleString('zh-CN') : '-'
}

onMounted(() => {
  loadRules()
  loadWords()
})
</script>

<style scoped>
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.pagination-wrap {
  margin-top: 16px;
  display: flex;
  justify-content: flex-end;
}
</style>
