<template>
  <view class="card-shop">
    <!-- Section header -->
    <view class="section-header">
      <text class="section-title">会员卡</text>
      <text class="section-action" @tap="goToAllCards">全部</text>
    </view>

    <!-- Loading skeleton -->
    <view v-if="loading" class="card-list">
      <view
        v-for="i in 3"
        :key="i"
        class="card-row skeleton-row"
      >
        <view class="skeleton-card-cover" />
        <view class="skeleton-info">
          <view class="skeleton-line skeleton-line--title" />
          <view class="skeleton-line skeleton-line--sub" />
          <view class="skeleton-line skeleton-line--price" />
        </view>
      </view>
    </view>

    <!-- Card list -->
    <view v-else-if="cardTypes.length" class="card-list">
      <view
        v-for="card in cardTypes"
        :key="card.id"
        class="card-row"
        @tap="goToDetail(card.id)"
      >
        <!-- Card Cover — image if available, gradient fallback -->
        <view class="card-cover" :class="card.coverUrl ? '' : getCardCoverClass(card.type)">
          <image
            v-if="card.coverUrl"
            class="card-cover-img"
            :src="card.coverUrl"
            mode="aspectFill"
          />
          <template v-else>
            <view class="cover-deco cover-deco--1" />
            <view class="cover-deco cover-deco--2" />
          </template>
        </view>

        <!-- Card info — aligns with card-cover height -->
        <view class="card-info">
          <view class="info-top">
            <text class="card-name">{{ card.name }}</text>
            <text class="card-validity">有效期 {{ card.durationDays }} 天</text>
          </view>
          <view class="info-bottom">
            <view v-if="card.totalTimes" class="card-times">
              <text class="card-times-value">{{ card.totalTimes }}</text>
              <text class="card-times-unit">课时</text>
            </view>
            <view class="price-row">
              <text class="price-current">¥{{ formatPrice(card.price) }}</text>
              <text
                v-if="card.originalPrice && card.originalPrice > card.price"
                class="price-original"
              >
                ¥{{ formatPrice(card.originalPrice) }}
              </text>
            </view>
          </view>
        </view>

        <!-- Arrow -->
        <text class="card-arrow">›</text>
      </view>
    </view>

    <!-- Empty -->
    <view v-else class="empty-state">
      <text class="empty-text">暂无可购买的会员卡</text>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import type { CardType } from '@mp-pilates/shared'
import { get } from '../utils/request'
import { formatPrice, getCardCoverClass } from '../utils/format'

const cardTypes = ref<CardType[]>([])
const loading = ref(false)
const hasLoaded = ref(false)

async function fetchCardTypes() {
  // Stale-While-Revalidate: only show skeleton on first load
  // Subsequent refreshes silently update data in background
  if (!hasLoaded.value) {
    loading.value = true
  }
  try {
    const result = await get<CardType[]>('/membership/card-types')
    cardTypes.value = result
      .filter((c) => c.isActive)
      .sort((a, b) => a.sortOrder - b.sortOrder)
    hasLoaded.value = true
  } catch {
    // Only show error toast on first load; silent fail on background refresh
    if (!hasLoaded.value) {
      uni.showToast({ title: '加载会员卡失败', icon: 'none' })
    }
  } finally {
    loading.value = false
  }
}

onMounted(fetchCardTypes)

// Expose refresh method for parent page
defineExpose({ fetchCardTypes })

function goToDetail(id: string) {
  uni.navigateTo({ url: `/pages/card/detail?id=${id}` })
}

function goToAllCards() {
  uni.navigateTo({ url: '/pages/card/detail?showAll=1' })
}
</script>

<style lang="scss" scoped>
.card-shop {
  background: #ffffff;
  margin: 16rpx 24rpx 0;
  padding-bottom: 20rpx;
  border-radius: 20rpx;
  overflow: hidden;
  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
}

/* ── Section header ── */
.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 32rpx 32rpx 20rpx;
}

.section-title {
  font-size: 36rpx;
  font-weight: 700;
  color: #222;
}

.section-action {
  font-size: 26rpx;
  color: #999;
  padding: 8rpx 24rpx;
  border: 1rpx solid #ddd;
  border-radius: 24rpx;
}

/* ── Card list ── */
.card-list {
  padding: 0 32rpx;
}

.card-row {
  display: flex;
  align-items: center;
  gap: 20rpx;
  padding: 16rpx 0;
  border-bottom: 1rpx solid rgba($brand-color, 0.08);

  &:last-child {
    border-bottom: none;
  }
}

/* ══════════════════════════════════════════════════════════
   CARD COVER — Clean minimal design
   ══════════════════════════════════════════════════════════ */
.card-cover {
  width: 200rpx;
  height: 130rpx;
  border-radius: 16rpx;
  overflow: hidden;
  flex-shrink: 0;
  position: relative;
}

.card-cover-img {
  width: 100%;
  height: 100%;
}

/* Decorative circles */
.cover-deco {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;

  &--1 {
    width: 100rpx;
    height: 100rpx;
    top: -30rpx;
    right: -20rpx;
    background: rgba(255, 255, 255, 0.4);
  }

  &--2 {
    width: 70rpx;
    height: 70rpx;
    bottom: -20rpx;
    left: -10rpx;
    background: rgba(255, 255, 255, 0.25);
  }
}

/* Card cover backgrounds */
.cover--times {
  background: linear-gradient(135deg, #E8D5C4 0%, #D4BFA8 100%);
}

.cover--duration {
  background: linear-gradient(135deg, #D8C8DC 0%, #C4AECB 100%);
}

.cover--trial {
  background: linear-gradient(135deg, #C8D8D2 0%, #A9C4BC 100%);
}

/* ── Card info — matches card-cover height ── */
.card-info {
  flex: 1;
  min-width: 0;
  height: 130rpx;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.info-top {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4rpx;
}

.info-bottom {
  display: flex;
  align-items: baseline;
  gap: 16rpx;
}

.card-name {
  font-size: 30rpx;
  font-weight: 700;
  color: $text-primary;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  letter-spacing: 0.5rpx;
  line-height: 1.2;
}

.card-validity {
  font-size: 23rpx;
  color: $text-secondary;
  line-height: 1.2;
}

.card-times {
  display: flex;
  align-items: baseline;
  gap: 4rpx;
}

.card-times-value {
  font-size: 34rpx;
  font-weight: 800;
  color: $brand-color;
  line-height: 1;
}

.card-times-unit {
  font-size: 20rpx;
  color: $text-secondary;
  font-weight: 500;
}

.price-row {
  display: flex;
  align-items: baseline;
  gap: 6rpx;
}

.price-current {
  font-size: 32rpx;
  font-weight: 800;
  color: $brand-color;
  line-height: 1;
}

.price-original {
  font-size: 20rpx;
  color: $text-hint;
  text-decoration: line-through;
}

/* Arrow */
.card-arrow {
  font-size: 44rpx;
  color: $text-hint;
  flex-shrink: 0;
  transform: scaleX(0.5);
  transform-origin: center;
}

/* ── Skeleton ── */
.skeleton-row {
  display: flex;
  align-items: center;
  gap: 20rpx;
  padding: 20rpx 0;
  border-bottom: 1rpx solid rgba($brand-color, 0.08);
}

.skeleton-card-cover {
  width: 240rpx;
  height: 130rpx;
  border-radius: 16rpx;
  flex-shrink: 0;
  background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%);
  background-size: 400% 100%;
  animation: shimmer 1.4s infinite;
}

.skeleton-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 16rpx;
}

.skeleton-line {
  height: 24rpx;
  border-radius: 6rpx;
  background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%);
  background-size: 400% 100%;
  animation: shimmer 1.4s infinite;

  &--title {
    width: 60%;
    height: 30rpx;
  }

  &--sub {
    width: 40%;
  }

  &--price {
    width: 45%;
    height: 36rpx;
  }
}

/* ── Empty state ── */
.empty-state {
  padding: 80rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.empty-text {
  font-size: 28rpx;
  color: $text-hint;
}
</style>
