<template>
  <view class="booking-page">
    <!-- ──────────── Status bar spacing ──────────── -->
    <view class="status-bar" :style="{ height: statusBarHeight }" />

    <!-- ──────────── Page title ──────────── -->
    <view class="page-header">
      <text class="page-title">课程预约</text>
    </view>

    <!-- ──────────── Date & period filters ──────────── -->
    <view class="filter-header">
      <DateSelector v-model="selectedDate" @select="onDateSelect" />
      <TimePeriodFilter v-model="selectedPeriod" @change="onPeriodChange" />
    </view>

    <!-- ──────────── Slot list ──────────── -->
    <scroll-view
      class="slot-scroll"
      scroll-y
      :style="{ height: scrollHeight }"
      refresher-enabled
      :refresher-triggered="refreshing"
      @refresherrefresh="onRefresh"
    >
      <!-- Loading skeleton -->
      <view v-if="bookingStore.loadingSlots && !refreshing" class="loading-wrap">
        <view v-for="i in 3" :key="i" class="skeleton-card">
          <view class="skeleton-time" />
          <view class="skeleton-body">
            <view class="skeleton-title" />
            <view class="skeleton-sub" />
          </view>
          <view class="skeleton-btn" />
        </view>
      </view>

      <!-- Empty state -->
      <view v-else-if="filteredSlots.length === 0" class="empty-wrap">
        <view class="empty-icon-circle">
          <text class="empty-icon-text">📅</text>
        </view>
        <text class="empty-text">当日暂无可约时段</text>
        <text class="empty-sub">请选择其他日期或时段查看</text>
      </view>

      <!-- Slot cards -->
      <view v-else class="slot-list">
        <!-- Date summary -->
        <view class="date-summary">
          <text class="date-summary-text">
            共 {{ filteredSlots.length }} 个可选时段
          </text>
        </view>

        <SlotCard
          v-for="item in filteredSlots"
          :key="item.id"
          :time-slot="item"
          @book="onBookTap"
          @cancel="onCancelTap"
        />
      </view>

      <!-- Bottom padding spacer -->
      <view class="scroll-bottom-spacer" />
    </scroll-view>

    <!-- ──────────── Confirm popup ──────────── -->
    <BookingConfirmPopup
      :visible="showConfirmPopup"
      :time-slot="pendingSlot"
      :memberships="userStore.activeMemberships as MembershipWithCardType[]"
      @confirm="onConfirmBooking"
      @cancel="showConfirmPopup = false"
    />
  </view>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app'
import type { TimeSlotWithBookingStatus, MembershipWithCardType } from '@mp-pilates/shared'
import { TIME_PERIODS } from '@mp-pilates/shared'
import { useBookingStore } from '../../stores/booking'
import { useUserStore } from '../../stores/user'
import { formatDate } from '../../utils/format'
import { getSystemLayout } from '../../utils/system'
import DateSelector from '../../components/DateSelector.vue'
import TimePeriodFilter from '../../components/TimePeriodFilter.vue'
import SlotCard from '../../components/SlotCard.vue'
import BookingConfirmPopup from '../../components/BookingConfirmPopup.vue'

type PeriodKey = keyof typeof TIME_PERIODS | null

// ─── Stores ───────────────────────────────────────────────
const bookingStore = useBookingStore()
const userStore = useUserStore()

// ─── State ────────────────────────────────────────────────
const selectedDate = ref<string>(formatDate(new Date()))
const selectedPeriod = ref<PeriodKey>(null)
const showConfirmPopup = ref(false)
const pendingSlot = ref<TimeSlotWithBookingStatus | null>(null)
const refreshing = ref(false)

// ─── 微信分享 ───────────────────────────────────────────────
onShareAppMessage(() => {
  return {
    title: '预约普拉提课程，开启健康新生活',
    path: '/pages/booking/index',
    imageUrl: '',
  }
})

onShareTimeline(() => {
  return {
    title: '预约普拉提课程，开启健康新生活',
    query: '',
  }
})

// ─── Layout ───────────────────────────────────────────────
const statusBarHeight = ref('20px')
const scrollHeight = ref('500px')
// Heights of static elements above scroll-view (in rpx, converted to px)
const PAGE_HEADER_RPX = 88   // title bar height
const FILTER_HEADER_RPX = 240 // DateSelector + TimePeriodFilter
const TABBAR_RPX = 100

function updateLayout() {
  const { statusBarHeight: statusBarPx, windowWidth } = getSystemLayout()
  const ratio = windowWidth / 750
  statusBarHeight.value = `${statusBarPx}px`

  const headerPx = Math.round(PAGE_HEADER_RPX * ratio)
  const filterPx = Math.round(FILTER_HEADER_RPX * ratio)
  const tabbarPx = Math.round(TABBAR_RPX * ratio)

  // scroll-view fills remaining space: window - statusBar - pageHeader - filters - tabbar
  const { windowHeight } = uni.getSystemInfoSync()
  const remaining = windowHeight - statusBarPx - headerPx - filterPx - tabbarPx
  scrollHeight.value = `${remaining}px`
}

updateLayout()

// ─── Filtered slots ───────────────────────────────────────
const filteredSlots = computed<TimeSlotWithBookingStatus[]>(() => {
  const slots = bookingStore.slots as TimeSlotWithBookingStatus[]
  if (!selectedPeriod.value) return [...slots]

  const period = TIME_PERIODS[selectedPeriod.value]
  return slots.filter((slot) => {
    const t = slot.startTime
    return t >= period.start && t < period.end
  })
})

// ─── Data loading ─────────────────────────────────────────
async function loadSlots(date: string) {
  await bookingStore.fetchSlots(date)
}

async function onRefresh() {
  refreshing.value = true
  await loadSlots(selectedDate.value)
  refreshing.value = false
}

// ─── Event handlers ───────────────────────────────────────
function onDateSelect(date: string) {
  selectedDate.value = date
  loadSlots(date)
}

function onPeriodChange(_period: PeriodKey) {
  // Filtering is done client-side via computed property
}

// ─── Book flow ────────────────────────────────────────────
async function onBookTap(slot: TimeSlotWithBookingStatus) {
  // 1. Ensure logged in
  if (!userStore.loggedIn) {
    uni.showModal({
      title: '提示',
      content: '请先登录后再预约课程',
      confirmText: '去登录',
      success: async (res) => {
        if (res.confirm) {
          try {
            await userStore.login()
            await userStore.fetchMemberships()
            // Retry booking flow after login
            onBookTap(slot)
          } catch {
            uni.showToast({ title: '登录失败', icon: 'none' })
          }
        }
      },
    })
    return
  }

  // 2. Ensure has valid membership
  if (!userStore.hasValidMembership) {
    uni.showModal({
      title: '暂无可用会员卡',
      content: '您当前没有有效的会员卡，购买后即可预约课程',
      confirmText: '去购买',
      cancelText: '取消',
      success: (res) => {
        if (res.confirm) {
          uni.navigateTo({ url: '/pages/store/index' })
        }
      },
    })
    return
  }

  // 3. Show confirm popup
  pendingSlot.value = slot
  showConfirmPopup.value = true
}

async function onConfirmBooking(payload: { timeSlotId: string; membershipId: string }) {
  showConfirmPopup.value = false

  uni.showLoading({ title: '预约中...' })
  try {
    await bookingStore.createBooking(payload)
    uni.hideLoading()
    uni.showToast({ title: '预约成功！', icon: 'success' })
    // Refresh slots to reflect new booking status
    await loadSlots(selectedDate.value)
  } catch (err: unknown) {
    uni.hideLoading()
    const message = err instanceof Error ? err.message : '预约失败，请重试'
    uni.showToast({ title: message, icon: 'none' })
  }
}

async function onCancelTap(slot: TimeSlotWithBookingStatus) {
  if (!slot.myBookingId) return

  uni.showModal({
    title: '取消预约',
    content: '确定要取消这个预约吗？',
    confirmText: '确定取消',
    confirmColor: '#ef4444',
    cancelText: '再想想',
    success: async (res) => {
      if (res.confirm) {
        uni.showLoading({ title: '取消中...' })
        try {
          await bookingStore.cancelBooking(slot.myBookingId!)
          uni.hideLoading()
          uni.showToast({ title: '已取消预约', icon: 'success' })
          await loadSlots(selectedDate.value)
        } catch (err: unknown) {
          uni.hideLoading()
          const message = err instanceof Error ? err.message : '取消失败，请重试'
          uni.showToast({ title: message, icon: 'none' })
        }
      }
    },
  })
}

// ─── Lifecycle ────────────────────────────────────────────
onMounted(async () => {
  // Load memberships if logged in but not yet fetched
  if (userStore.loggedIn && userStore.activeMemberships.length === 0) {
    await userStore.fetchMemberships()
  }
  // Load today's slots
  await loadSlots(selectedDate.value)
})
</script>

<style lang="scss" scoped>
.booking-page {
  height: 100vh;
  background: $primary-bg;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ── Status bar ───────────────────────────────────── */
.status-bar {
  flex-shrink: 0;
  background: #fff;
}

/* ── Page header ──────────────────────────────────── */
.page-header {
  flex-shrink: 0;
  height: 88rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fff;
}

.page-title {
  font-size: 34rpx;
  font-weight: 600;
  color: #1a1a2e;
}

/* ── Filter header ────────────────────────────────── */
.filter-header {
  flex-shrink: 0;
  background: #fff;
  box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.04);
}

/* ── Scroll container ──────────────────────────────── */
.slot-scroll {
  flex: 1;
  width: 100%;
  box-sizing: border-box;
}

/* ── Slot list ─────────────────────────────────────── */
.slot-list {
  display: flex;
  flex-direction: column;
  gap: 20rpx;
  padding: 24rpx 24rpx 0;
}

/* ── Date summary ──────────────────────────────────── */
.date-summary {
  padding: 0 8rpx 4rpx;
}

.date-summary-text {
  font-size: 24rpx;
  color: #999;
  font-weight: 400;
}

/* ── Loading skeleton ──────────────────────────────── */
.loading-wrap {
  display: flex;
  flex-direction: column;
  gap: 20rpx;
  padding: 28rpx 24rpx;
}

.skeleton-card {
  height: 140rpx;
  border-radius: 24rpx;
  background: #fff;
  display: flex;
  flex-direction: row;
  align-items: center;
  padding: 32rpx 28rpx 32rpx 36rpx;
  gap: 24rpx;
  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.03);
}

.skeleton-time {
  width: 80rpx;
  height: 72rpx;
  border-radius: 12rpx;
  background: linear-gradient(90deg, $primary-border 25%, $primary-light 50%, $primary-border 75%);
  background-size: 400% 100%;
  animation: shimmer 1.4s infinite;
  flex-shrink: 0;
}

.skeleton-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 12rpx;
}

.skeleton-title {
  width: 60%;
  height: 28rpx;
  border-radius: 8rpx;
  background: linear-gradient(90deg, $primary-border 25%, $primary-light 50%, $primary-border 75%);
  background-size: 400% 100%;
  animation: shimmer 1.4s infinite;
}

.skeleton-sub {
  width: 40%;
  height: 20rpx;
  border-radius: 6rpx;
  background: linear-gradient(90deg, $primary-border 25%, $primary-light 50%, $primary-border 75%);
  background-size: 400% 100%;
  animation: shimmer 1.4s infinite;
}

.skeleton-btn {
  width: 140rpx;
  height: 72rpx;
  border-radius: 36rpx;
  background: linear-gradient(90deg, $primary-border 25%, $primary-light 50%, $primary-border 75%);
  background-size: 400% 100%;
  animation: shimmer 1.4s infinite;
  flex-shrink: 0;
}

/* ── Empty state ───────────────────────────────────── */
.empty-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 140rpx 40rpx;
  gap: 16rpx;
}

.empty-icon-circle {
  width: 140rpx;
  height: 140rpx;
  border-radius: 50%;
  background: $primary-border;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 16rpx;
}

.empty-icon-text {
  font-size: 56rpx;
}

.empty-text {
  font-size: 30rpx;
  color: #666;
  font-weight: 600;
}

.empty-sub {
  font-size: 26rpx;
  color: #bbb;
}

/* ── Bottom spacer ─────────────────────────────────── */
.scroll-bottom-spacer {
  height: 48rpx;
}
</style>
