<template>
  <el-dialog
    :model-value="open"
    class="cfo-value-action-dialog"
    width="min(92vw, 560px)"
    :close-on-click-modal="false"
    :close-on-press-escape="!submitting"
    :show-close="!submitting"
    :title="actionMeta.label"
    @update:model-value="$emit('update:open', $event)"
  >
    <form class="value-action-form" @submit.prevent="submit">
      <div class="value-action-context">
        <span>{{ contextLabel }}</span>
        <strong>{{ targetTitle }}</strong>
        <small>当前版本 v{{ Number(target?.version || 0) }}</small>
      </div>

      <label v-if="action === 'reverse'" class="value-action-field">
        <span>冲回金额 <em aria-hidden="true">*</em></span>
        <input
          v-model="form.reversalAmount"
          type="number"
          min="0.01"
          step="0.01"
          inputmode="decimal"
          autocomplete="off"
        />
      </label>

      <label class="value-action-field">
        <span>操作说明 <em aria-hidden="true">*</em></span>
        <textarea
          v-model.trim="form.comment"
          rows="4"
          maxlength="1000"
          :placeholder="commentPlaceholder"
        ></textarea>
        <small>至少 2 个字符；说明将写入不可变事件记录。</small>
      </label>

      <p v-if="validationError || error" class="value-action-error" role="alert">
        <i class="mdi mdi-alert-circle-outline" aria-hidden="true"></i>
        {{ validationError || error?.message || '操作失败，请刷新后重试。' }}
      </p>
    </form>

    <template #footer>
      <div class="value-action-footer">
        <button type="button" class="btn ghost" :disabled="submitting" @click="$emit('update:open', false)">
          取消
        </button>
        <button
          type="button"
          class="btn"
          :class="actionMeta.tone === 'danger' ? 'danger' : 'primary'"
          :disabled="submitting"
          @click="submit"
        >
          <i v-if="submitting" class="mdi mdi-loading mdi-spin" aria-hidden="true"></i>
          {{ submitting ? '正在写入证据链' : actionMeta.label }}
        </button>
      </div>
    </template>
  </el-dialog>
</template>

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

import { createRequestId, resolveActionMeta } from '../../views/scripts/cfoValueDashboardModel.js'

const props = defineProps({
  open: { type: Boolean, default: false },
  action: { type: String, default: '' },
  target: { type: Object, default: () => null },
  opportunity: { type: Object, default: () => null },
  submitting: { type: Boolean, default: false },
  error: { type: Object, default: () => null }
})

const emit = defineEmits(['update:open', 'submit'])
const form = reactive(createForm())
const validationError = ref('')
const actionMeta = computed(() => {
  const meta = resolveActionMeta(props.action)
  if (props.target?.realizationType || props.target?.realizationKey) {
    return { ...meta, kind: 'realization' }
  }
  return meta
})
const targetTitle = computed(() => (
  props.opportunity?.title
  || props.target?.title
  || props.opportunity?.claimNoSnapshot
  || props.target?.id
  || '节省机会'
))
const contextLabel = computed(() => (
  actionMeta.value.kind === 'realization' ? '实际结果' : '节省机会'
))
const commentPlaceholder = computed(() => {
  if (props.action === 'confirm') return '请说明核验依据或外部凭证来源'
  if (props.action === 'reverse') return '请说明冲回原因及对应事实'
  if (props.action === 'reject') return '请说明拒绝原因'
  return '请说明本次操作依据'
})

watch(
  () => [props.open, props.action, props.target?.id],
  ([open]) => {
    if (!open) return
    Object.assign(form, createForm(props.target, props.opportunity))
    validationError.value = ''
  },
  { immediate: true }
)

function submit() {
  validationError.value = validate()
  if (validationError.value || props.submitting) return

  emit('submit', {
    kind: actionMeta.value.kind,
    action: props.action,
    requestId: form.requestId,
    opportunityId: props.opportunity?.id || props.target?.id,
    realizationId: actionMeta.value.kind === 'realization' ? props.target?.id : undefined,
    expectedVersion: Number(props.target?.version || 0),
    comment: form.comment,
    ...(props.action === 'reverse' ? { reversalAmount: form.reversalAmount } : {})
  })
}

function validate() {
  if (String(form.comment || '').trim().length < 2) return '请填写至少 2 个字符的操作说明。'
  if (Number(props.target?.version || 0) < 1) return '当前记录缺少有效版本，请刷新详情后重试。'
  if (props.action === 'reverse' && Number(form.reversalAmount) <= 0) return '冲回金额必须大于 0。'
  return ''
}

function createForm() {
  return {
    requestId: createRequestId('cfo-value-action'),
    comment: '',
    reversalAmount: ''
  }
}
</script>

<style scoped>
.value-action-form { display: grid; gap: 18px; }
.value-action-context { display: grid; gap: 4px; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-soft); }
.value-action-context span, .value-action-context small { color: var(--muted); font-size: 12px; }
.value-action-context strong { color: var(--ink); font-size: 14px; }
.value-action-field { display: grid; gap: 7px; color: var(--text); font-size: 13px; font-weight: 700; }
.value-action-field em { color: var(--danger); font-style: normal; }
.value-action-field input, .value-action-field textarea { width: 100%; min-height: 44px; padding: 10px 12px; border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--surface); color: var(--ink); }
.value-action-field textarea { resize: vertical; line-height: 1.55; }
.value-action-field small { color: var(--muted); font-size: 12px; font-weight: 500; line-height: 1.55; }
.value-action-error { display: flex; align-items: flex-start; gap: 8px; color: var(--danger-active); font-size: 13px; line-height: 1.5; }
.value-action-footer { display: flex; justify-content: flex-end; gap: 10px; }
.value-action-footer .btn { min-width: 112px; min-height: 44px; }
.btn:disabled { cursor: not-allowed; opacity: .48; transform: none; box-shadow: none; }
@media (max-width: 560px) {
  .value-action-footer { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .value-action-footer .btn { width: 100%; min-width: 0; }
}
</style>
