<template>
  <div class="policy-page">
    <div class="policy-header">
      <div>
        <h2 class="ops-page-title">全局合规策略</h2>
        <div class="policy-header__meta">
          <span>修订 {{ policy?.revision ?? 0 }}</span>
          <span>更新 {{ policy?.updated_at ? formatDate(policy.updated_at) : '--' }}</span>
        </div>
      </div>
      <a-space>
        <a-button :loading="loading" @click="loadAll">
          <template #icon><ReloadOutlined /></template>
          刷新
        </a-button>
        <a-button type="primary" :loading="saving" @click="savePolicy">保存策略</a-button>
      </a-space>
    </div>

    <div class="policy-grid">
      <div class="ops-card policy-master-card">
        <div class="policy-master-card__main">
          <div>
            <span class="eyebrow">MASTER SWITCH</span>
            <h3>内容合规检测总开关</h3>
            <p>关闭后自动检测器短路，但人工审阅 pending / rejected 仍会继续生效。</p>
          </div>
          <a-popconfirm
            :title="form.master_enabled ? '确认关闭全站自动检测？' : '确认开启全站自动检测？'"
            :ok-button-props="{ danger: form.master_enabled, loading: masterSaving }"
            @confirm="toggleMasterSwitch"
          >
            <a-switch
              :checked="form.master_enabled"
              :loading="masterSaving"
              checked-children="开启"
              un-checked-children="关闭"
            />
          </a-popconfirm>
        </div>
        <a-alert
          v-if="!form.master_enabled"
          type="warning"
          show-icon
          message="全站自动检测已关闭，发布闸会跳过词库、正则与 LLM 检测。"
        />
      </div>

      <div class="ops-card">
        <h3 class="section-title">判定模式</h3>
        <a-radio-group v-model:value="form.enforcement_mode" class="mode-radio-group">
          <a-radio-button value="mandatory">强制阻断</a-radio-button>
          <a-radio-button value="advisory">仅提示确认</a-radio-button>
          <a-radio-button value="disabled">关闭检测</a-radio-button>
        </a-radio-group>
        <div class="mode-hint">
          <a-tag :color="modeColor(form.enforcement_mode)">
            {{ modeLabel(form.enforcement_mode) }}
          </a-tag>
          <span>{{ modeHint }}</span>
        </div>
      </div>
    </div>

    <div class="ops-card">
      <div class="section-header">
        <h3 class="section-title">启用词库</h3>
        <a-tag>{{ form.enabled_dictionaries.length }} / {{ dictionaries.length }}</a-tag>
      </div>
      <a-select
        v-model:value="form.enabled_dictionaries"
        mode="multiple"
        class="dictionary-select"
        :options="dictionaryOptions"
        :loading="loading"
        placeholder="选择参与自动检测的词库"
      />
      <div class="dictionary-preview">
        <a-tag
          v-for="dictionary in selectedDictionaries"
          :key="dictionary.id"
          :color="dictionary.enabled ? 'blue' : 'default'"
        >
          {{ dictionary.name }} · v{{ dictionary.version }}
        </a-tag>
      </div>
    </div>

    <div class="ops-card">
      <div class="section-header">
        <h3 class="section-title">LLM 复核</h3>
        <a-switch
          v-model:checked="form.llm_judge_enabled"
          checked-children="开启"
          un-checked-children="关闭"
        />
      </div>
      <a-alert
        type="info"
        show-icon
        message="发布硬闸不等待 LLM；开启后编辑器检测可同步等待，发布后会进入异步复核队列并计入 AI 点数。"
      />
      <a-select
        v-model:value="form.llm_categories"
        mode="tags"
        class="llm-category-select"
        placeholder="输入复核类别，如 medical、finance"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ReloadOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import dayjs from 'dayjs'
import { computed, onMounted, reactive, ref } from 'vue'

import { modeColor, modeLabel } from '@/lib/compliance-display'
import {
  complianceApi,
  type ComplianceMode,
  type CompliancePolicy,
  type OpsComplianceDictionary,
} from '@/lib/compliance'
import { OpsApiError } from '@/lib/http'

const policy = ref<CompliancePolicy | null>(null)
const dictionaries = ref<OpsComplianceDictionary[]>([])
const loading = ref(false)
const saving = ref(false)
const masterSaving = ref(false)

const form = reactive({
  master_enabled: true,
  enforcement_mode: 'advisory' as ComplianceMode,
  enabled_dictionaries: [] as number[],
  llm_judge_enabled: false,
  llm_categories: [] as string[],
})

const dictionaryOptions = computed(() =>
  dictionaries.value.map((item) => ({
    label: `${item.name} · ${item.code}`,
    value: item.id,
    disabled: !item.enabled,
  })),
)

const selectedDictionaries = computed(() => {
  const selected = new Set(form.enabled_dictionaries)
  return dictionaries.value.filter((item) => selected.has(item.id))
})

const modeHint = computed(() => {
  if (form.enforcement_mode === 'mandatory') return 'block 等级命中会直接阻断发布'
  if (form.enforcement_mode === 'advisory') return '命中后作者确认风险即可继续发布'
  return '自动检测短路，保留人工审阅裁决'
})

async function loadAll() {
  loading.value = true
  try {
    const [policyResult, dictionariesResult] = await Promise.all([
      complianceApi.globalPolicy(),
      complianceApi.dictionaries(),
    ])
    policy.value = policyResult
    dictionaries.value = dictionariesResult
    applyPolicy(policyResult)
  } catch (error) {
    showError(error)
  } finally {
    loading.value = false
  }
}

async function savePolicy() {
  saving.value = true
  try {
    policy.value = await complianceApi.updateGlobalPolicy({
      master_enabled: form.master_enabled,
      enforcement_mode: form.enforcement_mode,
      enabled_dictionaries: form.enabled_dictionaries,
      llm_judge_enabled: form.llm_judge_enabled,
      llm_categories: form.llm_categories,
    })
    applyPolicy(policy.value)
    message.success('全局策略已保存')
  } catch (error) {
    showError(error)
  } finally {
    saving.value = false
  }
}

async function toggleMasterSwitch() {
  masterSaving.value = true
  try {
    policy.value = await complianceApi.setMasterSwitch(!form.master_enabled)
    applyPolicy(policy.value)
    message.success(form.master_enabled ? '自动检测已开启' : '自动检测已关闭')
  } catch (error) {
    showError(error)
  } finally {
    masterSaving.value = false
  }
}

function applyPolicy(next: CompliancePolicy) {
  form.master_enabled = next.master_enabled ?? true
  form.enforcement_mode = next.enforcement_mode
  form.enabled_dictionaries = [...next.enabled_dictionaries]
  form.llm_judge_enabled = next.llm_judge_enabled
  form.llm_categories = [...next.llm_categories]
}

function formatDate(value: string): string {
  return dayjs(value).format('YYYY-MM-DD HH:mm')
}

function showError(error: unknown) {
  if (error instanceof OpsApiError) {
    message.error(error.detail || error.message)
  }
}

onMounted(() => {
  void loadAll()
})
</script>

<style scoped>
.policy-page {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.policy-header,
.section-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
}

.policy-header__meta {
  display: flex;
  gap: 14px;
  color: #64748b;
  font-size: 13px;
}

.policy-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(320px, 420px);
  gap: 18px;
}

.policy-master-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.policy-master-card__main {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
}

.eyebrow {
  color: #64748b;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0;
}

.policy-master-card h3,
.section-title {
  margin: 0;
  color: #0f172a;
  font-size: 16px;
  font-weight: 700;
}

.policy-master-card p {
  margin: 8px 0 0;
  color: #64748b;
}

.mode-radio-group {
  width: 100%;
}

.mode-hint {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  color: #64748b;
}

.dictionary-select,
.llm-category-select {
  width: 100%;
  margin-top: 14px;
}

.dictionary-preview {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 14px;
}

@media (max-width: 1040px) {
  .policy-grid {
    grid-template-columns: 1fr;
  }
}
</style>
