<template>
  <el-drawer
    :model-value="open"
    class="cfo-value-opportunity-drawer"
    size="min(96vw, 760px)"
    :with-header="false"
    @update:model-value="$emit('update:open', $event)"
  >
    <div class="value-drawer-shell">
      <header class="value-drawer-head">
        <div>
          <span class="value-drawer-eyebrow">节省机会证据链</span>
          <h2>{{ opportunity?.title || '节省机会详情' }}</h2>
        </div>
        <button type="button" class="value-icon-button" aria-label="关闭节省机会详情" @click="$emit('update:open', false)">
          <i class="mdi mdi-close" aria-hidden="true"></i>
        </button>
      </header>

      <div v-if="loading" class="value-drawer-state" role="status" aria-live="polite">
        <i class="mdi mdi-loading mdi-spin" aria-hidden="true"></i>
        <strong>正在加载基线、证据和事件记录</strong>
      </div>
      <div v-else-if="error" class="value-drawer-state error" role="alert">
        <i class="mdi mdi-alert-circle-outline" aria-hidden="true"></i>
        <strong>{{ error.message || '节省机会详情加载失败' }}</strong>
        <button type="button" class="btn" @click="$emit('retry')">重试</button>
      </div>
      <div v-else-if="detail" class="value-drawer-content">
        <section class="value-detail-hero" aria-labelledby="value-detail-summary-title">
          <div>
            <span :class="['value-status-pill', detail.statusMeta.tone]">{{ detail.statusMeta.label }}</span>
            <span class="value-version-pill">v{{ detail.version }}</span>
          </div>
          <h3 id="value-detail-summary-title">{{ detail.estimatedLabel }}</h3>
          <p>{{ detail.description || '暂无机会说明。' }}</p>
          <dl>
            <div><dt>单据</dt><dd>{{ detail.claimNoSnapshot || detail.claimId }}</dd></div>
            <div><dt>负责人</dt><dd>{{ detail.ownerLabel }}</dd></div>
            <div><dt>可信度</dt><dd>{{ detail.confidenceLabel }}</dd></div>
            <div><dt>目标日期</dt><dd>{{ detail.dueLabel }}</dd></div>
          </dl>
        </section>

        <section class="value-detail-section" aria-labelledby="value-source-links-title">
          <div class="value-section-head">
            <h3 id="value-source-links-title">查看来源</h3>
            <span>{{ sourceLinks.length }} 个入口</span>
          </div>
          <nav v-if="sourceLinks.length" class="value-source-link-list" aria-label="节省机会来源入口">
            <RouterLink
              v-for="link in sourceLinks"
              :key="link.key"
              :to="link.to"
              :class="['value-source-link', link.kind]"
            >
              <i :class="link.icon" aria-hidden="true"></i>
              <span>
                <strong>{{ link.label }}</strong>
                <small>{{ link.description }}</small>
              </span>
              <i class="mdi mdi-chevron-right" aria-hidden="true"></i>
            </RouterLink>
          </nav>
          <p v-else class="value-inline-empty">当前机会没有可验证的关联单据、预算维度或分析维度入口。</p>
        </section>

        <section class="value-detail-section" aria-labelledby="value-actions-title">
          <div class="value-section-head">
            <h3 id="value-actions-title">可执行动作</h3>
            <span v-if="detail.readOnlyReason">只读</span>
          </div>
          <div v-if="opportunityActions.length" class="value-action-list">
            <button
              v-for="action in opportunityActions"
              :key="action"
              type="button"
              class="btn"
              :class="resolveActionMeta(action).tone === 'danger' ? 'danger' : 'primary'"
              @click="$emit('action', { action, target: opportunity, opportunity })"
            >
              {{ resolveActionMeta(action).label }}
            </button>
          </div>
          <p v-else-if="!requiresExternalEvidence" class="value-inline-empty">
            {{ detail.readOnlyReason || '当前状态没有可执行动作。' }}
          </p>
          <p v-if="requiresExternalEvidence" class="value-inline-empty evidence-required" role="status">
            实际结果必须来自平台付款事件，或关联可追溯的支付、银行、ERP 凭证。当前页面不会提交空证据；
            外部凭证入口接入前，请先完成付款流程或等待连接器回执。
          </p>
        </section>

        <section class="value-detail-section" aria-labelledby="value-baseline-title">
          <div class="value-section-head">
            <h3 id="value-baseline-title">冻结基线</h3>
            <span v-if="opportunity.baseline">{{ opportunity.baseline.dataQualityStatus }}</span>
          </div>
          <dl v-if="opportunity.baseline" class="value-detail-grid">
            <div><dt>基线类型</dt><dd>{{ opportunity.baseline.baselineType }}</dd></div>
            <div><dt>基线值</dt><dd>{{ formatBaselineValue(opportunity.baseline) }}</dd></div>
            <div><dt>样本量</dt><dd>{{ opportunity.baseline.sampleCount }}</dd></div>
            <div><dt>质量评分</dt><dd>{{ opportunity.baseline.dataQualityScore }}</dd></div>
            <div><dt>算法版本</dt><dd>{{ opportunity.baseline.algorithmVersion }}</dd></div>
            <div><dt>政策版本</dt><dd>{{ opportunity.baseline.policyVersion || '未绑定' }}</dd></div>
          </dl>
          <p v-else class="value-inline-empty baseline-missing">基线详情不可用，当前机会不能作为已核验价值依据。</p>
        </section>

        <section class="value-detail-section" aria-labelledby="value-realizations-title">
          <div class="value-section-head">
            <h3 id="value-realizations-title">实际结果</h3>
            <span>{{ realizations.length }} 笔</span>
          </div>
          <div v-if="realizations.length" class="value-realization-list">
            <article v-for="realization in realizations" :key="realization.id" class="value-realization-card">
              <div class="value-realization-head">
                <div>
                  <strong>{{ formatMoney(realization.reportingAmount, realization.reportingCurrency) }}</strong>
                  <span>{{ realization.realizationType === 'reversal' ? '冲回记录' : '实际结果' }} · {{ realizationStatus(realization.status) }}</span>
                </div>
                <span>v{{ realization.version }}</span>
              </div>
              <dl>
                <div><dt>发生时间</dt><dd>{{ formatDateTime(realization.realizedAt) }}</dd></div>
                <div><dt>记录人</dt><dd>{{ realization.recordedByName || realization.recordedById }}</dd></div>
                <div><dt>去重状态</dt><dd>{{ realization.dedupeStatus }}</dd></div>
                <div><dt>汇率证据</dt><dd>{{ realization.fxSource }} / {{ realization.fxVersion }}</dd></div>
                <div><dt>财务确认</dt><dd>{{ financeConfirmationLabel(realization) }}</dd></div>
                <div><dt>确认时间</dt><dd>{{ formatDateTime(realization.confirmedAt) }}</dd></div>
              </dl>
              <p v-if="realization.confirmationNote" class="value-record-note">
                确认说明：{{ realization.confirmationNote }}
              </p>
              <p v-else-if="realization.rejectionReason" class="value-record-note">
                拒绝原因：{{ realization.rejectionReason }}
              </p>
              <p v-else-if="realization.reversalReason" class="value-record-note">
                冲回原因：{{ realization.reversalReason }}
              </p>
              <div v-if="realization.availableActions?.length" class="value-action-list compact">
                <button
                  v-for="action in realization.availableActions"
                  :key="action"
                  type="button"
                  class="btn"
                  :class="resolveActionMeta(action).tone === 'danger' ? 'danger' : ''"
                  @click="$emit('action', { action, target: realization, opportunity })"
                >
                  {{ resolveActionMeta(action).label }}
                </button>
              </div>
              <p v-else-if="realization.readOnlyReason" class="value-record-note">{{ realization.readOnlyReason }}</p>
            </article>
          </div>
          <p v-else class="value-inline-empty">尚未记录实际结果；预计金额不会进入 CFO 主指标。</p>
        </section>

        <section class="value-detail-section" aria-labelledby="value-evidence-title">
          <div class="value-section-head">
            <h3 id="value-evidence-title">证据索引</h3>
            <span>{{ evidence.length }} 条</span>
          </div>
          <ol v-if="evidence.length" class="value-evidence-list">
            <li v-for="item in evidence" :key="item.id || item.evidenceKey">
              <i class="mdi mdi-file-certificate-outline" aria-hidden="true"></i>
              <div>
                <strong>{{ item.evidenceRole || item.resourceType }}</strong>
                <span>{{ item.sourceSystem }} · {{ item.resourceId }}</span>
                <small>{{ item.verificationStatus }} · {{ formatDateTime(item.occurredAt) }}</small>
              </div>
            </li>
          </ol>
          <p v-else class="value-inline-empty">暂无独立证据索引，请补齐后再确认价值。</p>
        </section>

        <section class="value-detail-section" aria-labelledby="value-events-title">
          <div class="value-section-head">
            <h3 id="value-events-title">不可变事件记录</h3>
            <span>{{ events.length }} 条</span>
          </div>
          <ol v-if="events.length" class="value-event-list">
            <li v-for="event in events" :key="event.id">
              <i aria-hidden="true"></i>
              <div>
                <strong>{{ event.action }}</strong>
                <span>{{ event.actorName || event.actorId }} · v{{ event.expectedVersion }} → v{{ event.resultVersion }}</span>
                <small>{{ formatDateTime(event.occurredAt) }} · 请求 {{ event.requestId }}</small>
              </div>
            </li>
          </ol>
          <p v-else class="value-inline-empty">暂无事件记录。</p>
        </section>
      </div>
    </div>
  </el-drawer>
</template>

<script setup>
import { computed } from 'vue'
import { useRoute } from 'vue-router'

import {
  buildOpportunityRows,
  formatDateTime,
  formatMoney,
  resolveActionMeta
} from '../../views/scripts/cfoValueDashboardModel.js'
import { buildCfoOpportunitySourceLinks } from '../../views/scripts/cfoValueSourceLinks.js'

const props = defineProps({
  open: { type: Boolean, default: false },
  opportunity: { type: Object, default: () => null },
  loading: { type: Boolean, default: false },
  error: { type: Object, default: () => null }
})

defineEmits(['update:open', 'retry', 'action'])

const route = useRoute()
const detail = computed(() => (
  props.opportunity ? buildOpportunityRows({ items: [props.opportunity] })[0] : null
))
const sourceLinks = computed(() => buildCfoOpportunitySourceLinks(props.opportunity || {}, {
  dashboardQuery: route.query
}))
const realizations = computed(() => props.opportunity?.realizations || [])
const evidence = computed(() => props.opportunity?.evidence || [])
const events = computed(() => props.opportunity?.events || [])
const opportunityActions = computed(() => (
  detail.value?.availableActions?.filter((action) => action !== 'record_realization') || []
))
const requiresExternalEvidence = computed(() => (
  detail.value?.availableActions?.includes('record_realization') || false
))

function realizationStatus(status) {
  return {
    pending_confirmation: '待财务确认',
    finance_confirmed: '财务已确认',
    rejected: '已拒绝',
    reversed: '已冲回'
  }[status] || status || '未知'
}

function financeConfirmationLabel(realization = {}) {
  if (realization.status === 'finance_confirmed') {
    return realization.financeConfirmerName || realization.financeConfirmerId || '独立财务已确认'
  }
  if (realization.status === 'rejected') {
    return realization.rejectedByName || realization.rejectedById || '财务已拒绝'
  }
  if (realization.status === 'reversed') {
    return realization.reversedByName || realization.reversedById || '已追加冲回'
  }
  return '待独立财务确认'
}

function formatBaselineValue(baseline = {}) {
  if (baseline.originalCurrency) {
    return formatMoney(baseline.baselineValue, baseline.originalCurrency)
  }
  const unit = String(baseline.unit || '').trim()
  return `${Number(baseline.baselineValue || 0).toLocaleString('zh-CN', { maximumFractionDigits: 4 })}${unit ? ` ${unit}` : ''}`
}
</script>

<style scoped>
.value-drawer-shell { min-height: 100%; display: flex; flex-direction: column; background: var(--bg); }
.value-drawer-head { position: sticky; top: 0; z-index: 2; display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 20px 22px; border-bottom: 1px solid var(--line); background: rgba(255, 255, 255, .96); backdrop-filter: blur(12px); }
.value-drawer-eyebrow { display: block; color: var(--theme-primary-active); font-size: 12px; font-weight: 800; letter-spacing: .08em; }
.value-drawer-head h2 { margin: 5px 0 0; color: var(--ink); font-size: 20px; line-height: 1.35; }
.value-icon-button { width: 44px; height: 44px; display: grid; place-items: center; flex: 0 0 auto; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); color: var(--text); font-size: 20px; }
.value-drawer-state { min-height: 360px; display: grid; place-content: center; justify-items: center; gap: 14px; padding: 24px; color: var(--muted); text-align: center; }
.value-drawer-state > i { color: var(--theme-primary); font-size: 32px; }
.value-drawer-state.error > i { color: var(--danger); }
.value-drawer-state .btn { min-height: 44px; }
.value-drawer-content { display: grid; gap: 14px; padding: 16px 22px 32px; }
.value-detail-hero, .value-detail-section { padding: 18px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); box-shadow: 0 1px 2px rgba(15, 23, 42, .04); }
.value-detail-hero > div:first-child { display: flex; gap: 8px; }
.value-status-pill, .value-version-pill, .value-section-head > span { min-height: 24px; display: inline-flex; align-items: center; padding: 3px 8px; border-radius: 999px; background: var(--info-soft); color: var(--info); font-size: 12px; font-weight: 800; }
.value-status-pill.success { background: var(--success-soft); color: var(--success); }
.value-status-pill.warning { background: var(--warning-soft); color: var(--warning); }
.value-status-pill.danger { background: var(--danger-soft); color: var(--danger); }
.value-status-pill.primary { background: var(--theme-primary-soft); color: var(--theme-primary-active); }
.value-detail-hero h3 { margin: 16px 0 8px; color: var(--ink); font-size: 30px; font-variant-numeric: tabular-nums; }
.value-detail-hero > p { color: var(--muted); font-size: 13px; line-height: 1.65; }
.value-detail-hero dl, .value-detail-grid, .value-realization-card dl { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 18px 0 0; }
dl div { min-width: 0; }
dt { color: var(--muted); font-size: 12px; }
dd { margin: 4px 0 0; color: var(--ink); font-size: 13px; font-weight: 700; overflow-wrap: anywhere; }
.value-section-head, .value-realization-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.value-section-head { margin-bottom: 14px; }
.value-section-head h3 { margin: 0; color: var(--ink); font-size: 15px; }
.value-action-list { display: flex; flex-wrap: wrap; gap: 10px; }
.value-action-list .btn { min-height: 44px; }
.value-action-list.compact { margin-top: 14px; }
.value-action-list.compact .btn { min-height: 44px; font-size: 12px; }
.value-source-link-list { display: grid; gap: 10px; }
.value-source-link { min-height: 64px; display: grid; grid-template-columns: 36px minmax(0, 1fr) 18px; align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-soft); color: var(--text); text-decoration: none; transition: border-color 160ms ease, background 160ms ease; }
.value-source-link:hover, .value-source-link:focus-visible { border-color: var(--theme-primary); background: var(--theme-primary-soft); outline: none; }
.value-source-link > i:first-child { width: 36px; height: 36px; display: grid; place-items: center; border-radius: var(--radius); background: var(--surface); color: var(--theme-primary-active); font-size: 18px; }
.value-source-link > span { min-width: 0; }
.value-source-link strong, .value-source-link small { display: block; }
.value-source-link strong { color: var(--ink); font-size: 13px; }
.value-source-link small { margin-top: 4px; color: var(--muted); font-size: 12px; line-height: 1.5; }
.value-source-link > i:last-child { color: var(--muted); }
.value-source-link.budget small { color: var(--warning-active); }
.value-inline-empty, .value-record-note { padding: 12px; border-radius: var(--radius); background: var(--surface-soft); color: var(--muted); font-size: 12px; line-height: 1.55; }
.value-inline-empty.baseline-missing { border-left: 3px solid var(--warning); background: var(--warning-soft); color: var(--warning-active); }
.value-inline-empty.evidence-required { border-left: 3px solid var(--warning); background: var(--warning-soft); color: var(--warning-active); }
.value-realization-list { display: grid; gap: 12px; }
.value-realization-card { padding: 14px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-soft); }
.value-realization-head strong { display: block; color: var(--ink); font-size: 18px; font-variant-numeric: tabular-nums; }
.value-realization-head span { display: block; margin-top: 3px; color: var(--muted); font-size: 12px; }
.value-evidence-list, .value-event-list { display: grid; gap: 12px; margin: 0; padding: 0; list-style: none; }
.value-evidence-list li, .value-event-list li { display: flex; align-items: flex-start; gap: 12px; min-width: 0; }
.value-evidence-list > li > i { width: 34px; height: 34px; display: grid; place-items: center; flex: 0 0 auto; border-radius: var(--radius); background: var(--theme-primary-soft); color: var(--theme-primary-active); font-size: 17px; }
.value-evidence-list div, .value-event-list div { min-width: 0; }
.value-evidence-list strong, .value-event-list strong { display: block; color: var(--ink); font-size: 13px; }
.value-evidence-list span, .value-evidence-list small, .value-event-list span, .value-event-list small { display: block; margin-top: 3px; color: var(--muted); font-size: 12px; line-height: 1.5; overflow-wrap: anywhere; }
.value-event-list > li > i { width: 10px; height: 10px; margin: 5px 4px 0; flex: 0 0 auto; border: 3px solid var(--theme-primary-soft-strong); border-radius: 50%; background: var(--theme-primary); box-sizing: content-box; }
@media (max-width: 560px) {
  .value-drawer-head, .value-drawer-content { padding-left: 14px; padding-right: 14px; }
  .value-detail-hero h3 { font-size: 24px; }
  .value-detail-hero dl, .value-detail-grid, .value-realization-card dl { grid-template-columns: 1fr; }
  .value-action-list { display: grid; grid-template-columns: 1fr; }
  .value-action-list .btn { width: 100%; }
}
</style>
