<script lang="ts" setup>
/**
 * 消息中心 · VIP 通知高级视图
 * 优先用 payload 徽标；缺失时按 level_id / duration_type 回补，避免演示/旧数据只显示「-」
 */
import { computed, onMounted, ref, watch } from 'vue';

import { Spin } from 'ant-design-vue';

import VipBadgeCombo from '#/components/vip/VipBadgeCombo.vue';
import { getVipDurationOption } from '#/views/system/vip/duration/api';
import { getVipLevelInfo, getVipLevelOption } from '#/views/system/vip/level/api';

const props = defineProps<{
  notice: Record<string, any>;
}>();

const loading = ref(false);
const card = ref<Record<string, any>>({});

function parsePayload(): Record<string, any> {
  const p = props.notice?.action_payload;
  if (p && typeof p === 'object') return { ...p };
  try {
    return JSON.parse(String(props.notice?.content || '')) || {};
  } catch {
    return {};
  }
}

const scene = computed(() => {
  const type = String(card.value?.type || '');
  if (type === 'vip_open_success') {
    return { label: '开通成功', tone: 'success' };
  }
  if (type === 'vip_expiring') {
    return { label: '即将到期', tone: 'warn' };
  }
  if (type === 'vip_expired') {
    return { label: '已到期', tone: 'danger' };
  }
  return { label: props.notice?.type_name || 'VIP 通知', tone: 'normal' };
});

const hasBadge = computed(
  () => !!(card.value?.badge_url || card.value?.duration_badge_url),
);

const monogram = computed(() => {
  const name = String(card.value?.level_name || card.value?.level_code || 'VIP');
  return name.slice(0, 2).toUpperCase();
});

const expireText = computed(() => {
  if (card.value?.is_lifetime || Number(card.value?.expire_at) === 0) {
    return card.value?.duration_label || '终身有效';
  }
  const at = Number(card.value?.expire_at || 0);
  if (!at) return card.value?.duration_label || '—';
  if (typeof card.value?.expire_at === 'string' && String(card.value.expire_at).includes('-')) {
    return String(card.value.expire_at);
  }
  const d = new Date(at < 1e12 ? at * 1000 : at);
  const pad = (n: number) => String(n).padStart(2, '0');
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
});

/**
 * 补齐等级徽标 / 期限丝带 URL（演示 SQL 常缺图）
 */
async function hydrateBadges(base: Record<string, any>) {
  const next = { ...base };
  try {
    if (!next.badge_url) {
      if (Number(next.level_id) > 0) {
        const level = await getVipLevelInfo(Number(next.level_id));
        next.badge_url = level?.badge_url || next.badge_url;
        next.level_name = next.level_name || level?.name;
        next.level_code = next.level_code || level?.code;
      } else if (next.level_code) {
        const opts = (await getVipLevelOption()) || [];
        const hit = (Array.isArray(opts) ? opts : []).find(
          (o: any) => String(o.code) === String(next.level_code),
        );
        if (hit) {
          next.badge_url = hit.badge_url || '';
          next.level_id = hit.id || next.level_id;
          next.level_name = next.level_name || hit.name;
        }
      }
    }
    if (!next.duration_badge_url) {
      const durations = (await getVipDurationOption()) || [];
      const list = Array.isArray(durations) ? durations : [];
      const hit =
        list.find((o: any) => String(o.code) === String(next.duration_type)) ||
        list.find((o: any) => String(o.name) === String(next.duration_label));
      if (hit) {
        next.duration_badge_url = hit.badge_url || '';
        next.duration_label = next.duration_label || hit.name;
      }
    }
  } catch {
    /* 徽标补齐失败仍展示文案卡 */
  }
  return next;
}

async function loadCard() {
  loading.value = true;
  try {
    card.value = await hydrateBadges(parsePayload());
  } finally {
    loading.value = false;
  }
}

watch(
  () => [props.notice?.id, props.notice?.action_payload],
  () => loadCard(),
  { deep: true },
);

onMounted(loadCard);
</script>

<template>
  <Spin :spinning="loading">
    <div class="vip-view">
      <div class="vip-card" :class="`tone-${scene.tone}`">
        <div class="vip-card__glow" aria-hidden="true"></div>
        <div class="vip-card__top">
          <span class="scene-pill">{{ scene.label }}</span>
          <span v-if="card.level_code" class="code-pill">{{ card.level_code }}</span>
        </div>
        <div class="vip-card__body">
          <div class="badge-wrap">
            <VipBadgeCombo
              v-if="hasBadge"
              size="xl"
              :badge-url="card.badge_url"
              :duration-badge-url="card.duration_badge_url"
              :level-name="card.level_name"
              :duration-label="card.duration_label"
            />
            <div v-else class="mono">{{ monogram }}</div>
          </div>
          <div class="info">
            <div class="level-name">{{ card.level_name || '会员' }}</div>
            <div class="duration">{{ card.duration_label || '会员权益' }}</div>
            <div class="store">{{ card.store_name || '门店' }}</div>
            <div class="expire">有效期至 {{ expireText }}</div>
          </div>
        </div>
      </div>

      <div class="price-row">
        <div class="price-item">
          <span class="label">原价</span>
          <span class="val">¥{{ card.original_price || '0.00' }}</span>
        </div>
        <div class="price-item accent">
          <span class="label">实付</span>
          <span class="val">¥{{ card.pay_amount || '0.00' }}</span>
        </div>
      </div>

      <p v-if="notice.detail" class="detail">{{ notice.detail }}</p>
      <div v-if="card.store_id || card.open_record_id" class="meta-line">
        <span v-if="card.store_id">门店 ID #{{ card.store_id }}</span>
        <span v-if="card.open_record_id">开通记录 #{{ card.open_record_id }}</span>
      </div>
    </div>
  </Spin>
</template>

<style scoped>
.vip-view {
  padding: 2px 0 6px;
}

.vip-card {
  position: relative;
  overflow: hidden;
  padding: 20px 22px 22px;
  border-radius: 18px;
  color: #fff;
  background:
    linear-gradient(135deg, #1f2a37 0%, #2d4a3e 48%, #3d9b88 100%);
  box-shadow:
    0 12px 32px hsl(160 40% 20% / 0.28),
    inset 0 1px 0 hsl(0 0% 100% / 0.12);
}

.vip-card.tone-warn {
  background: linear-gradient(135deg, #2a2418 0%, #5c4020 52%, #b8860b 100%);
}

.vip-card.tone-danger {
  background: linear-gradient(135deg, #2a181c 0%, #5a2430 52%, #a33b4a 100%);
}

.vip-card__glow {
  position: absolute;
  inset: -40% auto auto -20%;
  width: 70%;
  height: 90%;
  background: radial-gradient(circle, hsl(0 0% 100% / 0.18), transparent 68%);
  pointer-events: none;
}

.vip-card__top {
  position: relative;
  z-index: 1;
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 16px;
}

.scene-pill,
.code-pill {
  display: inline-flex;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  background: hsl(0 0% 100% / 0.16);
  backdrop-filter: blur(6px);
}

.vip-card__body {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 22px;
}

.badge-wrap {
  flex-shrink: 0;
  filter: drop-shadow(0 10px 18px hsl(0 0% 0% / 0.35));
}

.mono {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 36px;
  font-weight: 800;
  letter-spacing: 0.04em;
  color: #fff;
  background: hsl(0 0% 100% / 0.16);
  border: 1px solid hsl(0 0% 100% / 0.22);
}

.info {
  min-width: 0;
  flex: 1;
}

.level-name {
  font-size: 24px;
  font-weight: 780;
  letter-spacing: -0.03em;
  line-height: 1.2;
}

.duration {
  margin-top: 6px;
  font-size: 14px;
  opacity: 0.92;
}

.store {
  margin-top: 10px;
  font-size: 13px;
  opacity: 0.86;
}

.expire {
  margin-top: 4px;
  font-size: 12px;
  opacity: 0.72;
}

.price-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-top: 14px;
}

.price-item {
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid hsl(var(--border));
  background: hsl(var(--card, var(--background)));
}

.price-item.accent {
  border-color: hsl(var(--primary) / 0.35);
  background: hsl(var(--primary) / 0.08);
}

.price-item .label {
  display: block;
  font-size: 12px;
  color: hsl(var(--muted-foreground));
}

.price-item .val {
  display: block;
  margin-top: 4px;
  font-size: 20px;
  font-weight: 720;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: hsl(var(--foreground));
}

.detail {
  margin: 14px 0 0;
  font-size: 13px;
  line-height: 1.55;
  color: hsl(var(--muted-foreground));
}

.meta-line {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 10px;
  font-size: 12px;
  color: hsl(var(--muted-foreground));
}
</style>
