<template>
  <ConfirmDialog
    :open="riskRuleCreateOpen"
    badge="自然语言规则"
    badge-tone="info"
    title="新建风险规则"
    description="默认创建费用类风险规则。选择业务环节和费用领域后填写规则标题与自然语言描述，系统会根据评分模型自动计算风险分数和等级。"
    cancel-text="取消"
    confirm-text="开始生成"
    busy-text="生成中..."
    confirm-tone="primary"
    confirm-icon="mdi mdi-auto-fix"
    :busy="riskRuleCreateBusy"
    :close-on-mask="!riskRuleCreateBusy"
    @close="emit('close-risk-rule-create')"
    @confirm="emit('submit-risk-rule-create')"
  >
    <div class="risk-rule-create-form">
      <label class="span-2">
        <span>常见规则模板</span>
        <EnterpriseSelect
          v-model="selectedRiskRuleTemplateId"
          :options="riskRuleTemplateOptions"
          :disabled="riskRuleCreateBusy || riskRuleTemplatesLoading"
          :placeholder="riskRuleTemplatesLoading ? '模板加载中...' : '可选：从常见规则预填'"
          clearable
          filterable
          @change="applyRiskRuleTemplate"
        />
      </label>
      <div v-if="selectedRiskRuleTemplate" class="risk-rule-template-preview span-2">
        <div class="risk-rule-template-preview__head">
          <strong>{{ selectedRiskRuleTemplate.title }}</strong>
          <span>{{ selectedRiskRuleTemplate.group_label }}</span>
        </div>
        <p>{{ selectedRiskRuleTemplate.description }}</p>
        <small>字段：{{ formatTemplateFields(selectedRiskRuleTemplate.fields) }}</small>
        <small>模板只预填规则文本，提交后仍走通用自然语言生成链路。</small>
      </div>
      <p v-else-if="riskRuleTemplateLoadFailed" class="risk-rule-template-note span-2">
        常见模板暂时加载失败，可以继续手动编写规则。
      </p>
      <label>
        <span>业务环节</span>
        <EnterpriseSelect
          v-model="riskRuleCreateForm.business_stage"
          :options="riskRuleBusinessStageOptions"
          :disabled="riskRuleCreateBusy"
        />
      </label>
      <label>
        <span>费用领域</span>
        <EnterpriseSelect
          v-model="riskRuleCreateForm.expense_category"
          :options="riskRuleExpenseCategoryOptions"
          :disabled="riskRuleCreateBusy"
        />
      </label>
      <label>
        <span>是否上传附件</span>
        <EnterpriseSelect
          v-model="riskRuleCreateForm.requires_attachment"
          :options="riskRuleAttachmentOptions"
          :disabled="riskRuleCreateBusy"
        />
      </label>
      <label class="span-2">
        <span>规则标题</span>
        <input
          v-model="riskRuleCreateForm.rule_title"
          :disabled="riskRuleCreateBusy"
          maxlength="80"
          placeholder="例如：差旅目的地与票据城市一致性校验"
        />
      </label>
      <label class="span-2">
        <span>自然语言规则</span>
        <textarea
          v-model="riskRuleCreateForm.natural_language"
          :disabled="riskRuleCreateBusy"
          placeholder="例如：住宿城市必须出现在本次差旅行程城市中，否则提示高风险并要求补充说明。"
        ></textarea>
      </label>
    </div>
  </ConfirmDialog>

  <RiskRuleTestDialog
    :open="riskRuleTestOpen"
    :rule="selectedSkill"
    @close="emit('close-risk-rule-test')"
    @report-saved="emit('report-saved', $event)"
  />

  <ConfirmDialog
    :open="riskRuleEditOpen"
    badge="规则维护"
    badge-tone="info"
    :title="riskRuleEditMode === 'revision' ? '创建修订版本' : '编辑风险规则'"
    :description="riskRuleEditMode === 'revision' ? '已上线规则不会被直接覆盖，系统会先创建一个新的修订草稿并重新生成执行模板。' : '未上线规则可以直接调整标题、费用领域、附件要求和自然语言描述，并同步重新生成执行模板。'"
    cancel-text="取消"
    :confirm-text="riskRuleEditMode === 'revision' ? '创建并生成' : '保存并生成'"
    busy-text="保存中..."
    confirm-tone="primary"
    confirm-icon="mdi mdi-content-save-outline"
    :busy="riskRuleEditBusy"
    :close-on-mask="!riskRuleEditBusy"
    @close="emit('close-risk-rule-edit')"
    @confirm="emit('submit-risk-rule-edit')"
  >
    <div class="risk-rule-create-form">
      <label>
        <span>费用领域</span>
        <EnterpriseSelect
          v-model="riskRuleEditForm.expense_category"
          :options="riskRuleExpenseCategoryOptions"
          :disabled="riskRuleEditBusy"
        />
      </label>
      <label>
        <span>是否上传附件</span>
        <EnterpriseSelect
          v-model="riskRuleEditForm.requires_attachment"
          :options="riskRuleAttachmentOptions"
          :disabled="riskRuleEditBusy"
        />
      </label>
      <label class="span-2">
        <span>规则标题</span>
        <input
          v-model="riskRuleEditForm.rule_title"
          :disabled="riskRuleEditBusy"
          maxlength="80"
          placeholder="例如：差旅目的地与票据城市一致性校验"
        />
      </label>
      <label class="span-2">
        <span>自然语言规则</span>
        <textarea
          v-model="riskRuleEditForm.natural_language"
          :disabled="riskRuleEditBusy"
          placeholder="请用自然语言描述风险判断流程、字段、例外条件和处理动作。"
        ></textarea>
      </label>
      <label v-if="riskRuleEditMode === 'revision'" class="span-2">
        <span>修订原因</span>
        <textarea
          v-model="riskRuleEditForm.change_reason"
          :disabled="riskRuleEditBusy"
          placeholder="请说明本次修订要解决的规则问题或业务变化。"
        ></textarea>
      </label>
    </div>
  </ConfirmDialog>

  <ConfirmDialog
    :open="riskRuleDeleteOpen"
    badge="删除规则"
    badge-tone="danger"
    title="删除未发布风险规则"
    description="该操作会删除规则草稿、版本记录和关联 JSON 文件。只有从未发布过的规则允许删除。"
    cancel-text="取消"
    confirm-text="确认删除"
    busy-text="删除中..."
    confirm-tone="danger"
    confirm-icon="mdi mdi-delete-outline"
    :busy="actionState === 'delete-risk-rule'"
    @close="emit('close-delete-risk-rule')"
    @confirm="emit('delete-selected-risk-rule')"
  >
    <div class="risk-rule-action-confirm">
      <span>规则名称</span>
      <strong>{{ selectedSkill?.name }}</strong>
    </div>
  </ConfirmDialog>

  <ConfirmDialog
    :open="riskRuleReturnOpen"
    badge="回退规则"
    badge-tone="warning"
    title="回退风险规则"
    description="回退后规则会回到草稿状态，编写人需要根据原因重新调整并测试。"
    cancel-text="取消"
    confirm-text="确认回退"
    busy-text="回退中..."
    confirm-tone="warning"
    confirm-icon="mdi mdi-keyboard-return"
    :busy="actionState === 'return-risk-rule'"
    @close="emit('close-return-risk-rule')"
    @confirm="emit('return-selected-risk-rule')"
  >
    <label class="risk-rule-action-note">
      <span>回退原因</span>
      <textarea
        v-model="returnNoteModel"
        rows="4"
        :disabled="actionState === 'return-risk-rule'"
        placeholder="请说明需要编写人调整的规则问题"
      ></textarea>
    </label>
  </ConfirmDialog>

  <ConfirmDialog
    :open="riskRulePublishOpen"
    badge="发布上线"
    badge-tone="info"
    title="发布风险规则"
    description="发布后该规则会进入真实业务风险扫描，只加载正式上线规则。"
    cancel-text="取消"
    confirm-text="确认发布"
    busy-text="发布中..."
    confirm-tone="primary"
    confirm-icon="mdi mdi-rocket-launch-outline"
    :busy="actionState === 'publish-risk-rule'"
    @close="emit('close-publish-risk-rule')"
    @confirm="emit('publish-selected-risk-rule')"
  >
    <div class="risk-rule-action-confirm">
      <span>测试状态</span>
      <strong>{{ riskRuleTestPassed ? '已确认通过' : '未确认通过' }}</strong>
    </div>
  </ConfirmDialog>

  <ConfirmDialog
    :open="Boolean(versionSwitchTarget)"
    badge="切换版本"
    badge-tone="info"
    title="切换规则版本"
    description="切换后编辑器只会替换当前展示内容，不会直接回滚后端当前版本。"
    cancel-text="取消"
    confirm-text="确认切换"
    busy-text="切换中..."
    confirm-tone="primary"
    confirm-icon="mdi mdi-swap-horizontal"
    @close="emit('cancel-version-switch')"
    @confirm="emit('confirm-version-switch')"
  >
    <div class="version-modal-summary">
      <div>
        <span>当前展示版本</span>
        <strong>{{ selectedSkill?.displayVersion }}</strong>
      </div>
      <i class="mdi mdi-arrow-right"></i>
      <div>
        <span>目标版本</span>
        <strong>{{ versionSwitchTarget?.version }}</strong>
      </div>
    </div>

    <div v-if="versionSwitchTarget" class="version-modal-note">
      <strong>{{ versionSwitchTarget.note }}</strong>
      <span>{{ versionSwitchTarget.time }}</span>
    </div>
  </ConfirmDialog>

  <ConfirmDialog
    :open="reviewSubmitOpen"
    badge="提交审核"
    badge-tone="info"
    title="提交规则版本审核"
    description="请先确认本次送审采用的版本号，并选择负责审核的高级管理员。若填写新的版本号，系统会将当前工作稿固化为该版本后再送审。"
    cancel-text="取消"
    confirm-text="确认提交"
    busy-text="提交中..."
    confirm-tone="primary"
    confirm-icon="mdi mdi-send-outline"
    :busy="actionState === 'review-pending'"
    @close="emit('close-submit-review')"
    @confirm="emit('submit-selected-rule-for-review')"
  >
    <div class="review-submit-form">
      <label>
        <span>送审版本号</span>
        <input
          v-model="reviewSubmitVersionModel"
          type="text"
          placeholder="例如：v1.1.0"
          :disabled="actionState === 'review-pending'"
        />
      </label>
      <label>
        <span>审核人</span>
        <EnterpriseSelect
          v-model="reviewSubmitReviewerModel"
          :options="reviewSubmitReviewerOptions"
          :placeholder="reviewSubmitReviewerLoading ? '加载审核人中...' : '请选择高级管理员'"
          :disabled="reviewSubmitReviewerLoading || actionState === 'review-pending'"
        />
      </label>
      <p
        v-if="!reviewSubmitReviewerLoading && !hasReviewSubmitReviewers"
        class="review-submit-hint"
      >
        当前没有可选的高级管理员，请先在员工管理中配置具备管理员角色的员工。
      </p>
      <div v-if="selectedSkillUsesJsonRisk" class="review-submit-test-state">
        <span>测试确认</span>
        <strong :class="{ passed: riskRuleTestPassed }">
          {{ riskRuleTestPassed ? '当前版本已通过测试确认' : '当前版本尚未确认测试通过' }}
        </strong>
        <p>只有保存测试报告的风险规则，才能提交给高级财务人员审核。</p>
      </div>
    </div>
  </ConfirmDialog>
</template>

<script setup>
import { computed, ref, watch } from 'vue'
import ConfirmDialog from '../shared/ConfirmDialog.vue'
import EnterpriseSelect from '../shared/EnterpriseSelect.vue'
import RiskRuleTestDialog from '../shared/RiskRuleTestDialog.vue'
import { fetchRiskRuleTemplates } from '../../services/agentAssets.js'

defineOptions({
  name: 'AuditRuleDialogs'
})

const props = defineProps({
  selectedSkill: { type: Object, default: null },
  versionSwitchTarget: { type: Object, default: null },
  actionState: { type: String, default: '' },
  riskRuleCreateOpen: { type: Boolean, default: false },
  riskRuleCreateBusy: { type: Boolean, default: false },
  riskRuleCreateForm: { type: Object, required: true },
  riskRuleBusinessStageOptions: { type: Array, default: () => [] },
  riskRuleExpenseCategoryOptions: { type: Array, default: () => [] },
  riskRuleAttachmentOptions: { type: Array, default: () => [] },
  riskRuleTestOpen: { type: Boolean, default: false },
  riskRuleEditOpen: { type: Boolean, default: false },
  riskRuleEditMode: { type: String, default: 'draft' },
  riskRuleEditForm: { type: Object, default: () => ({}) },
  riskRuleEditBusy: { type: Boolean, default: false },
  riskRuleDeleteOpen: { type: Boolean, default: false },
  riskRuleReturnOpen: { type: Boolean, default: false },
  riskRulePublishOpen: { type: Boolean, default: false },
  riskRuleReturnNote: { type: String, default: '' },
  riskRuleTestPassed: { type: Boolean, default: false },
  reviewSubmitOpen: { type: Boolean, default: false },
  reviewSubmitVersion: { type: String, default: '' },
  reviewSubmitReviewer: { type: String, default: '' },
  reviewSubmitReviewerLoading: { type: Boolean, default: false },
  reviewSubmitReviewerOptions: { type: Array, default: () => [] },
  hasReviewSubmitReviewers: { type: Boolean, default: false },
  selectedSkillUsesJsonRisk: { type: Boolean, default: false }
})

const emit = defineEmits([
  'update:riskRuleReturnNote',
  'update:reviewSubmitVersion',
  'update:reviewSubmitReviewer',
  'close-risk-rule-create',
  'submit-risk-rule-create',
  'close-risk-rule-test',
  'report-saved',
  'close-risk-rule-edit',
  'submit-risk-rule-edit',
  'close-delete-risk-rule',
  'delete-selected-risk-rule',
  'close-return-risk-rule',
  'return-selected-risk-rule',
  'close-publish-risk-rule',
  'publish-selected-risk-rule',
  'cancel-version-switch',
  'confirm-version-switch',
  'close-submit-review',
  'submit-selected-rule-for-review'
])

const returnNoteModel = computed({
  get: () => props.riskRuleReturnNote,
  set: (value) => emit('update:riskRuleReturnNote', value)
})

const reviewSubmitVersionModel = computed({
  get: () => props.reviewSubmitVersion,
  set: (value) => emit('update:reviewSubmitVersion', value)
})

const reviewSubmitReviewerModel = computed({
  get: () => props.reviewSubmitReviewer,
  set: (value) => emit('update:reviewSubmitReviewer', value)
})

const riskRuleTemplateGroups = ref([])
const riskRuleTemplatesLoading = ref(false)
const riskRuleTemplateLoadFailed = ref(false)
const selectedRiskRuleTemplateId = ref('')

const flatRiskRuleTemplates = computed(() =>
  riskRuleTemplateGroups.value.flatMap((group) => group.templates || [])
)
const riskRuleTemplateOptions = computed(() =>
  flatRiskRuleTemplates.value.map((template) => ({
    value: template.template_id,
    label: `${template.group_label} / ${template.title}`
  }))
)
const selectedRiskRuleTemplate = computed(() =>
  flatRiskRuleTemplates.value.find((template) => template.template_id === selectedRiskRuleTemplateId.value) || null
)

watch(
  () => props.riskRuleCreateOpen,
  (open) => {
    if (!open) {
      selectedRiskRuleTemplateId.value = ''
      return
    }
    loadRiskRuleTemplates()
  }
)

async function loadRiskRuleTemplates() {
  if (riskRuleTemplateGroups.value.length || riskRuleTemplatesLoading.value) {
    return
  }
  riskRuleTemplatesLoading.value = true
  riskRuleTemplateLoadFailed.value = false
  try {
    riskRuleTemplateGroups.value = await fetchRiskRuleTemplates()
  } catch {
    riskRuleTemplateLoadFailed.value = true
  } finally {
    riskRuleTemplatesLoading.value = false
  }
}

function applyRiskRuleTemplate(templateId) {
  const template = flatRiskRuleTemplates.value.find((item) => item.template_id === templateId)
  if (!template || !props.riskRuleCreateForm) {
    return
  }

  props.riskRuleCreateForm.business_domain = template.business_domain || 'expense'
  props.riskRuleCreateForm.business_stage = template.business_stage || 'reimbursement'
  props.riskRuleCreateForm.expense_category = template.expense_category || props.riskRuleCreateForm.expense_category
  props.riskRuleCreateForm.rule_title = template.title || ''
  props.riskRuleCreateForm.requires_attachment = Boolean(template.requires_attachment)
  props.riskRuleCreateForm.natural_language = template.natural_language || ''
}

function formatTemplateFields(fields = []) {
  const labels = fields.map((field) => field.display || field.label || field.key).filter(Boolean)
  if (!labels.length) {
    return '未配置字段'
  }
  if (labels.length <= 4) {
    return labels.join('、')
  }
  return `${labels.slice(0, 4).join('、')} 等 ${labels.length} 项`
}
</script>

<style scoped src="../../assets/styles/views/audit-view.css"></style>
<style scoped src="../../assets/styles/views/audit-view-part2.css"></style>
<style scoped>
.risk-rule-create-form > .span-2 {
  grid-column: 1 / -1;
}

.risk-rule-template-preview {
  display: grid;
  gap: 7px;
  padding: 12px;
  border: 1px solid #dbe5ef;
  border-radius: 6px;
  background: #f8fafc;
}

.risk-rule-template-preview__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.risk-rule-template-preview__head strong {
  min-width: 0;
  color: #0f172a;
  font-size: 13px;
  font-weight: 850;
}

.risk-rule-template-preview__head span,
.risk-rule-template-preview small,
.risk-rule-template-note {
  color: #64748b;
  font-size: 12px;
  line-height: 1.55;
}

.risk-rule-template-preview p {
  margin: 0;
  color: #334155;
  font-size: 12px;
  line-height: 1.6;
}

.risk-rule-template-note {
  margin: 0;
}
</style>
