<template>
  <ConfirmDialog
    :open="open"
    :badge="dialogBadge"
    badge-tone="warning"
    :title="title"
    :description="description"
    cancel-text="取消"
    confirm-text="确认退回"
    busy-text="退回中..."
    confirm-tone="primary"
    confirm-icon="mdi mdi-undo"
    :busy="busy"
    :close-on-mask="false"
    @close="handleClose"
    @confirm="handleConfirm"
  >
    <div class="return-reason-dialog">
      <small v-if="error" class="error" role="alert">{{ error }}</small>
      <div class="return-reason-section">
        <span>{{ optionsTitle }}</span>
        <div class="return-reason-options" role="group" :aria-label="optionsAriaLabel">
          <label
            v-for="option in options"
            :key="option.code"
            :class="['return-reason-option', { active: isOptionActive(option.code) }]"
          >
            <input
              :type="application ? 'radio' : 'checkbox'"
              :name="application ? 'application-return-reason' : undefined"
              :checked="isOptionActive(option.code)"
              :value="option.code"
              :disabled="busy"
              @change="handleOptionChange(option)"
            />
            <i :class="option.icon"></i>
            <strong>{{ option.label }}</strong>
          </label>
        </div>
        <small v-if="selectionError" class="error">{{ selectionError }}</small>
      </div>

      <label class="return-reason-section">
        <span>退单理由</span>
        <textarea
          v-model="reasonText"
          rows="4"
          :disabled="busy"
          :placeholder="reasonPlaceholder"
          @input="touched = true"
        ></textarea>
        <small :class="{ error: reasonError }">
          {{ validationMessage }}
        </small>
      </label>
    </div>
  </ConfirmDialog>
</template>

<script setup>
import { computed, ref, watch } from 'vue'

import ConfirmDialog from './ConfirmDialog.vue'

const CLAIM_RETURN_REASON_OPTIONS = [
  { code: 'missing_attachment', label: '附件缺失或不清晰', icon: 'mdi mdi-paperclip-alert' },
  { code: 'invoice_mismatch', label: '票据类型/金额与明细不一致', icon: 'mdi mdi-file-compare' },
  { code: 'over_policy', label: '超出制度标准或缺少超标说明', icon: 'mdi mdi-scale-unbalanced' },
  { code: 'business_explanation', label: '业务事由/地点/人员信息不完整', icon: 'mdi mdi-text-box-alert-outline' },
  { code: 'duplicate_or_abnormal', label: '疑似重复或异常票据', icon: 'mdi mdi-alert-octagon-outline' },
  { code: 'approval_question', label: '审批人需要补充说明', icon: 'mdi mdi-comment-question-outline' }
]

const APPLICATION_RETURN_REASON_OPTIONS = [
  {
    code: 'application_info_incomplete',
    label: '申请信息不完整',
    icon: 'mdi mdi-form-textbox',
    defaultReason: '请补充出差时间、地点、事由、天数或出行方式等关键信息后重新提交。'
  },
  {
    code: 'application_business_need_unclear',
    label: '业务必要性说明不足',
    icon: 'mdi mdi-briefcase-question-outline',
    defaultReason: '请说明本次申请对应的项目、客户或任务背景，以及必须现场处理的原因。'
  },
  {
    code: 'application_budget_basis_missing',
    label: '预算测算依据不足',
    icon: 'mdi mdi-calculator-variant-outline',
    defaultReason: '请补充预计住宿、交通、补贴等费用构成及测算依据，便于判断预算合理性。'
  },
  {
    code: 'application_policy_mismatch',
    label: '制度口径不匹配',
    icon: 'mdi mdi-scale-balance',
    defaultReason: '当前申请与差旅制度口径存在不一致，请核对职级、目的地、天数或费用标准后调整。'
  },
  {
    code: 'application_attachment_needed',
    label: '前置材料需补充',
    icon: 'mdi mdi-file-document-plus-outline',
    defaultReason: '请补充会议通知、客户邀约、项目安排或其他能支撑申请必要性的材料。'
  },
  {
    code: 'application_other',
    label: '其他',
    icon: 'mdi mdi-pencil-box-outline',
    defaultReason: ''
  }
]

const props = defineProps({
  open: { type: Boolean, default: false },
  busy: { type: Boolean, default: false },
  claimNo: { type: String, default: '' },
  application: { type: Boolean, default: false },
  error: { type: String, default: '' },
  title: { type: String, default: '确认退回该单据吗？' },
  description: {
    type: String,
    default: '退回后单据会回到待提交状态，申请人可按退回原因修改后重新提交。'
  }
})

const emit = defineEmits(['close', 'confirm'])

const selectedCodes = ref([])
const selectedApplicationCode = ref('')
const reasonText = ref('')
const touched = ref(false)
const selectionTouched = ref(false)
const lastAutoReason = ref('')

const options = computed(() => (props.application ? APPLICATION_RETURN_REASON_OPTIONS : CLAIM_RETURN_REASON_OPTIONS))
const selectedReasonCodes = computed(() => (
  props.application
    ? (selectedApplicationCode.value ? [selectedApplicationCode.value] : [])
    : selectedCodes.value
))
const dialogBadge = computed(() => (props.application ? '退回申请' : '退回单据'))
const optionsTitle = computed(() => (props.application ? '退单选项' : '默认风险点'))
const optionsAriaLabel = computed(() => (props.application ? '申请退单选项' : '默认退回风险点'))
const reasonPlaceholder = computed(() => (
  props.application
    ? '请选择退单选项，系统会自动带入默认理由。领导可按实际情况继续修改。'
    : '请写清楚需要申请人补充或修改的内容，例如：发票金额与明细金额不一致，请重新上传正确票据。'
))
const trimmedReason = computed(() => reasonText.value.trim())
const selectionError = computed(() => {
  if (!props.application || !selectionTouched.value || selectedReasonCodes.value.length > 0) {
    return ''
  }
  return '请选择一个退单选项，便于后续看板统计。'
})
const reasonError = computed(() => {
  if (!touched.value || trimmedReason.value.length >= 6) {
    return ''
  }
  return '请至少填写 6 个字的明确退单理由。'
})
const validationMessage = computed(() => (
  selectionError.value
  || reasonError.value
  || (
    props.application
      ? '退单选项会写入结构化埋点，理由会展示给申请人。'
      : '会同步记录到退单埋点，并展示给申请人。'
  )
))

watch(
  () => props.open,
  (open) => {
    if (open) {
      selectedCodes.value = []
      selectedApplicationCode.value = ''
      reasonText.value = ''
      touched.value = false
      selectionTouched.value = false
      lastAutoReason.value = ''
    }
  }
)

function syncApplicationDefaultReason(option) {
  const defaultReason = String(option?.defaultReason || '').trim()
  const canAutoFill = !touched.value || !reasonText.value.trim() || reasonText.value === lastAutoReason.value
  if (canAutoFill) {
    reasonText.value = defaultReason
  }
  lastAutoReason.value = defaultReason
}

function isOptionActive(code) {
  return props.application ? selectedApplicationCode.value === code : selectedCodes.value.includes(code)
}

function handleOptionChange(option) {
  selectionTouched.value = true

  if (props.application) {
    selectedApplicationCode.value = option.code
    syncApplicationDefaultReason(option)
    return
  }

  const selected = new Set(selectedCodes.value)
  if (selected.has(option.code)) {
    selected.delete(option.code)
  } else {
    selected.add(option.code)
  }
  selectedCodes.value = Array.from(selected)
}

function handleClose() {
  if (!props.busy) {
    emit('close')
  }
}

function handleConfirm() {
  touched.value = true
  selectionTouched.value = true
  if ((props.application && selectedReasonCodes.value.length === 0) || trimmedReason.value.length < 6 || props.busy) {
    return
  }

  emit('confirm', {
    reason: trimmedReason.value,
    reason_codes: [...selectedReasonCodes.value]
  })
}
</script>

<style scoped>
.return-reason-dialog {
  display: grid;
  gap: 14px;
}

.return-reason-dialog > small.error {
  padding: 9px 11px;
  border: 1px solid #fecaca;
  border-radius: 7px;
  background: #fef2f2;
  color: #b91c1c;
  font-size: 12px;
  line-height: 1.5;
}

.return-reason-section {
  display: grid;
  gap: 8px;
}

.return-reason-section > span {
  color: #334155;
  font-size: 12px;
  font-weight: 850;
}

.return-reason-options {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.return-reason-option {
  min-width: 0;
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr);
  align-items: center;
  gap: 8px;
  padding: 10px;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  background: #fff;
  color: #334155;
  cursor: pointer;
  transition: border-color 160ms ease, background 160ms ease, color 160ms ease;
}

.return-reason-option.active {
  border-color: rgba(234, 88, 12, .34);
  background: #fff7ed;
  color: #c2410c;
}

.return-reason-option input {
  width: 16px;
  height: 16px;
  accent-color: #ea580c;
}

.return-reason-option i {
  grid-column: 2;
  color: inherit;
}

.return-reason-option strong {
  min-width: 0;
  grid-column: 3;
  font-size: 12px;
  line-height: 1.35;
  overflow-wrap: anywhere;
}

.return-reason-section textarea {
  width: 100%;
  resize: vertical;
  min-height: 104px;
  padding: 12px;
  border: 1px solid #d7e0ea;
  border-radius: 8px;
  color: #0f172a;
  font-size: 13px;
  line-height: 1.6;
  outline: none;
}

.return-reason-section textarea:focus {
  border-color: rgba(234, 88, 12, .5);
  box-shadow: 0 0 0 3px rgba(234, 88, 12, .1);
}

.return-reason-section small {
  color: #64748b;
  font-size: 12px;
  line-height: 1.5;
}

.return-reason-section small.error {
  color: #dc2626;
}

@media (max-width: 640px) {
  .return-reason-options {
    grid-template-columns: minmax(0, 1fr);
  }
}
</style>
