<script setup lang="ts">
// 1. 导入 Vue3 核心 API 和 uni-app 生命周期
import { computed, nextTick, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'

// 2. 导入原组件和模拟数据
import { getArrayFieldMax, isWithin45Minutes } from '../utils'
import canvasSeatmap from './components/pages/CanvasSeatmap.vue'
import { StaticUrl } from '@/config'
import router from '@/router'

definePage({
  name: 'film-choose-seat',
  islogin: true,
  style: {
    navigationBarTitleText: '座次选择',
    backgroundColorBottom: '#fff',
  },
})

// ************************ 核心：定义所有缺失的接口（解决类型报错的关键） ************************
// /**
//  * 影院信息接口
//  */
// interface CinemaInfo {
//   cinema_name: string
//   [key: string]: any // 兼容其他未知属性，避免后续扩展报错
// }

/**
 * 区域列表项接口
 */
interface AreaItem {
  area: string | number
  areaId: string | number
  market_price: number | string
  strokeStyle: string
  [key: string]: any // 兼容组件所需的其他未知属性
}

// /**
//  * 场次信息接口
//  */
// interface ScheduleInfo {
//   schedule_id: string | number
//   hall_name: string
//   cinema: CinemaInfo | null
//   schedule_area: AreaItem[]
//   [key: string]: any // 兼容其他未知属性
// }

/**
 * 座位信息接口
 */
interface SeatInfo {
  seatName: string
  marketPrice: number | string
  [key: string]: any // 兼容组件所需的其他未知属性
}

/**
 * 座位图配置项接口
 */
interface SeatmapOptions {
  title: string
  hallName: string
  areaList: AreaItem[]
  footerHeight: number
  maxSelectNum?: number // 可选属性，对应注释的配置
  isolateSeats?: boolean // 可选属性，对应注释的配置
  [key: string]: any // 兼容组件所需的其他未知配置
}

/**
 * 座位点击回调事件接口
 */
interface SeatTapEvent {
  chooseSeatList: SeatInfo[]
}

/**
 * 座位图组件实例接口（定义组件的公开方法，解决 ref 调用方法的类型报错）
 */
interface CanvasSeatmapInstance {
  init: (params: { seatList: SeatInfo[], options: SeatmapOptions }) => void
  validateIsolates: () => boolean
  cancelSeat: (seat: SeatInfo) => void
}

const isLoging = ref(false)
const loading = ref<boolean>(false)
const seatInfo = ref<Api.filmMovieSeat>({})
const areaList = ref<AreaItem[]>([])
const seatList = ref<SeatInfo[]>([])
const chooseSeatList = ref<SeatInfo[]>([])
const options = ref<SeatmapOptions>({
  title: '',
  hallName: '',
  areaList: [],
  footerHeight: 0,
})
const areaArr = ref(['贵宾区', '普通区', '特价区1', '特价区2', '特价区3', '特价区4', '特价区5', '特价区6'])
const { userInfo } = storeToRefs(useUserStore())
const phone = ref('')
const query = ref({
  memberId: unref(userInfo).id,
  channelId: unref(userInfo).channelId,
  shopId: '1',
  channelName: unref(userInfo).channelName,
  cinemaName: '',
  cinemaCode: '',
  movieCode: '',
  hallName: '',
  orderPayMode: '1',
  originPrice: 0,
  seatNames: '',
  sessionBeginTime: '',
  switchSeat: false,
  movieName: '',
  postImageUrl: '',
  planType: '',

})
const active = ref('')
const showTime = ref(false)
const screenList = ref()
// ************************ 非响应式常量（类型自动推断，无需额外注解） ************************
const colorList = [
  '#449DFE', // 浅黄色
  '#FFB639', // 浅蓝色
  '#FF4D3A', // 干枯玫瑰
  '#b6e67f', // 浅绿色
  '#ffb0bc', // 浅粉色
] as const // as const 锁定数组元素，禁止修改，类型更严格

const totalPrice = computed(() => {
  let total = 0
  const scale = 10000
  if (!seatInfo.value.showTime)
    return 0
  const key = isWithin45Minutes(new Date(), seatInfo.value.showTime) ? 'fastPrice' : 'ticketPrice'
  const price = getArrayFieldMax(chooseSeatList.value, key) || 0
  total = (price * scale) * chooseSeatList.value.length / scale
  return total
})

// ************************ 组件 ref（添加明确实例类型，解决调用方法的类型报错） ************************
const seatmapRef = ref<CanvasSeatmapInstance | null>(null)

// ************************ 所有方法（添加参数/返回值类型注解，消除隐式 any） ************************
// /**
//  * 金额转换（分转元，保留 2 位小数）
//  * @param total 分单位金额
//  * @returns 元单位金额（字符串，保留 2 位小数）
//  */
// function priceConversion(total: number | string): string {
//   const numTotal = Number(total)
//   // 处理 NaN 情况，避免返回 NaN.toFixed(2) 报错
//   if (Number.isNaN(numTotal))
//     return '0.00'
//   return (numTotal / 100).toFixed(2)
// }

async function getScreenList(cinemaId: string, movieId: string) {
  const res = await Apis.film.getFilmMovieList({ data: { cinemaId, movieId } })
  res.data.data.movieShows?.forEach((i: any) => {
    if (i.shows.length) {
      i.shows.forEach((it: any, idx: number) => {
        if (active.value.includes(it.showDate)) {
          screenList.value = i.shows[idx].sessions
        }
      })
    }
  })
  console.log(2222222, screenList.value)
}

/**
 * 获取座位详情
 */
async function getData(sessionId: string, movieId: string, cinemaId: string): Promise<void> {
  uni.showLoading({ title: '加载中...' })
  const res = await Apis.film.getFilmMovieSeat({ data: { sessionId, movieId, cinemaId } })
  uni.hideLoading()
  getScreenList(res.data.cinemaId, res.data.movieId)
  active.value = res.data.showTime
  seatInfo.value = res.data
  // seatInfo.value.seatSection = []
  query.value.hallName = res.data.hall
  query.value.cinemaCode = res.data.cinemaCode
  query.value.movieCode = res.data.movieCode
  query.value.sessionBeginTime = res.data.showTime
  query.value.cinemaName = res.data.cinemaName
  query.value.movieName = res.data.movieName
  query.value.postImageUrl = res.data.postImageUrl
  areaList.value = res.data.areaPriceList
  areaList.value.sort((a, b) => Number(b.originPrice) - Number(a.originPrice))
  areaList.value.forEach((item: AreaItem, index: number) => {
    item.strokeStyle = colorList[index % colorList.length] || '#ccc'
    item.areaName = areaArr.value[index]
  })
  for (let index = 0; index < res.data.seatSection.seatRows.length; index++) {
    const item = res.data.seatSection.seatRows[index]
    for (let i = 0; i < item.columns.length; i++) {
      const seat = item.columns[i]
      let price = 0
      let marketPrice = 0
      let fastPrice = 0
      for (let d = 0; d < res.data.areaPriceList.length; d++) {
        const el = res.data.areaPriceList[d]
        if (el.areaId === seat.areaId) {
          // 价格
          price = el.price
          marketPrice = el.originPrice
          fastPrice = el.fastPrice
        }
      }
      // 桌椅状态

      let status = 0
      if (seat.state === 0 || seat.state === 4) {
        status = -2
      }
      else if (seat.state === 1) {
        status = 1
      }
      else if (seat.state === 2) {
        status = 0
      }
      else if (seat.state === 3) {
        status = 10
      }
      else if (seat.state === 10) {
        status = 1
      }
      else if (seat.state === 11) {
        status = 1
      }
      // 座位类型
      let seatType = 0
      if (seat.seatType === 2) {
        seatType = 1
      }
      else if (seat.seatType === 3) {
        seatType = 3
      }

      seatList.value.push({
        status,
        seatType,
        seatName: seat.seatName,
        seatId: seat.originSeatID,
        columnId: seat.colNum,
        rowId: item.rowsNum,
        // columnId: i,
        // rowId: index,

        areaId: seat.areaId,
        marketPrice,
        ticketPrice: price,
        fastPrice,
        serviceFee: 0,
      })
    }
  }

  console.log(2222, areaList.value)
  // 赋值座位图配置项（严格符合 SeatmapOptions 接口）
  options.value = {
    title: '',
    hallName: seatInfo.value.hall as string,
    areaList: areaList.value,
    footerHeight: 470,
    // maxSelectNum: 4,   // 可选属性，开启后无类型报错
    // isolateSeats: true, // 可选属性，开启后无类型报错
  }

  // 可选链访问，避免 cinema 为 null 时报错
  // const cinemaName = schedule.value.cinema?.cinema_name || '默认影院'
  // uni.setNavigationBarTitle({ title: cinemaName })
}

/**
 * 选定并购买座位
 */
async function buySeat() {
  if (loading.value)
    return false
  if (chooseSeatList.value.length === 0) {
    return uni.showToast({
      title: '请选择座位',
      icon: 'none',
      duration: 2000,
    })
  }

  // 可选链调用，避免组件实例为 null 时报错
  if (seatmapRef.value?.validateIsolates()) {
    uni.showToast({
      title: '左右座位请不要留空！',
      icon: 'none',
      duration: 2000,
    })
    return false
  }

  query.value.seatNames = chooseSeatList.value.map(item => item.seatName).join(',')
  query.value.planType = seatInfo.value?.language as string + seatInfo.value?.planType
  uni.showToast({
    title: '开始锁座',
    icon: 'none',
    duration: 2000,
  })
  uni.setStorageSync('film-info', { showTime: active.value, endTime: seatInfo.value.endTime, cinemaName: seatInfo.value.cinemaName, chooseSeatList: chooseSeatList.value, language: seatInfo.value.language, planType: seatInfo.value.planType, totalPrice: totalPrice.value, phone: phone.value })
  router.push({ name: 'film-submit-order', params: { query: JSON.stringify(query.value) } })
  console.log(query.value)
}

/**
 * 取消选定座位
 * @param seat 要取消的座位信息
 */
function cancelSeat(seat: SeatInfo): void {
  seatmapRef.value?.cancelSeat(seat)
}

/**
 * 座位图错误回调
 * @param e 错误事件对象
 */
function onError(e: { message: string }): void {
  uni.showToast({
    title: e.message || '座位图加载失败',
    icon: 'none',
    duration: 2000,
  })
}

/**
 * 座位点击回调
 * @param event 座位点击事件对象
 */
function onSeatTap(event: SeatTapEvent): void {
  chooseSeatList.value = event.chooseSeatList
  console.log('chooseSeatList', event)
  console.log('zuoshsjd', chooseSeatList.value)
  // 遍历已选座位列表，累加价格（严格类型访问）
  let price = 0
  for (const item of chooseSeatList.value) {
    if (item.marketPrice as number > price) {
      price = item.marketPrice as number
    }
  }
  query.value.originPrice = price
}

// ************************ 页面生命周期（严格类型，无报错） ************************
onLoad(async (opt): Promise<void> => {
  phone.value = opt?.phone
  await getData(opt?.sessionId, opt?.movieId, opt?.cinemaId)

  // 等待 DOM 渲染完成后初始化座位图
  await nextTick()

  // 可选链 + 类型守卫，确保调用安全无报错
  if (seatmapRef.value) {
    seatmapRef.value.init({
      seatList: seatList.value,
      options: options.value,
    })
  }
})

function handleTime(time: string, sessionId: string) {
  if (time === active.value) {
    return
  }
  active.value = time
  router.push({ name: 'film-choose-seat', params: { sessionId, movieId: seatInfo.value.movieId as string, cinemaId: seatInfo.value.cinemaId } })
}
function handleSwitch() {
  console.log(11111)

  showTime.value = !showTime.value
}

// 获取时间
function judgeNearDaysSimple(time: any) {
  const today = new Date(new Date().setHours(0, 0, 0, 0)).getTime()
  const target = new Date(new Date(time).setHours(0, 0, 0, 0)).getTime()
  const dayDiff = Math.floor((target - today) / 86400000)

  return { 0: '今天', 1: '明天', 2: '后天' }[dayDiff] || ''
}
</script>

<template>
  <view class="view-page">
    <!-- 顶部价格区域 -->
    <view v-if="seatInfo.cinemaId" class="areaList">
      <view class="area-item">
        <view class="area" style="background-color:#AAAAAA" />
        <view class="area-price">
          已售
        </view>
      </view>
      <view v-for="(item, index) in areaList" :key="index" class="area-item">
        <view class="area" :style="`border:1px solid ${item.strokeStyle}`" />
        <view class="area-price">
          {{ `${item.areaName} ${isWithin45Minutes(new Date(), seatInfo.showTime) ? item.fastPrice : item.price}` }}
        </view>
      </view>
    </view>
    <canvasSeatmap ref="seatmapRef" @error="onError" @on-seat-tap="onSeatTap" />

    <!-- 底部信息 -->
    <view v-if="seatInfo.cinemaId" class="footer">
      <view class="schedule bg-white">
        <view class="name-box">
          <view class="film-name">
            {{ seatInfo.movieName }}
          </view>
          <view class="change-box" @click="handleSwitch">
            <view>切换场次</view>
            <image class="arrow" :src="`${StaticUrl}/film-black-arrow.png`" mode="scaleToFill" />
          </view>
        </view>
        <view class="film-info">
          <text style="color:red">
            {{ judgeNearDaysSimple(seatInfo.showTime) || seatInfo.showTime?.split('T')[0] }}
          </text>
          {{ seatInfo.showTime?.split('T')[1] }} -
          {{ seatInfo.endTime?.split('T')[1] }}
          {{ seatInfo.planType }} {{ seatInfo.language }}
        </view>
        <!-- 切换场次 -->
        <view v-if="showTime" class="time-list">
          <view
            v-for="(item, index) in screenList" :key="index" class="time-item"
            :class="[active == item.showTime ? 'active' : '']" @click="handleTime(item.showTime, item.sessionId)"
          >
            <view class="time">
              {{ item.showTime.split('T')[1] }}
            </view>
            <view class="type">
              {{ item.language }} {{ item.planType }}
            </view>
            <view class="price">
              ￥{{ item.sellPrice }}起
            </view>
          </view>
        </view>
        <view v-if="chooseSeatList.length" class="seat-list">
          <view v-for="(seat, optindex) in chooseSeatList" :key="optindex" class="seat-item">
            <view class="seat">
              <view class="seat-name">
                {{ seat.seatName }}
              </view>
              <view class="seat-price">
                <!-- ￥{{ priceConversion(seat.marketPrice) }} -->
                ￥{{ isWithin45Minutes(new Date(), seatInfo.showTime) ? seat.fastPrice : seat.ticketPrice }}
              </view>
            </view>
            <view class="delete-seat" @click="cancelSeat(seat)">
              ×
            </view>
          </view>
        </view>
      </view>
      <view class="notice bg-white">
        请尽快选座，座位可能被抢！
      </view>

      <wd-button
        custom-class="confirm" block :loading="isLoging" :class="{ unbtn: !chooseSeatList.length || loading }"
        @click="buySeat"
      >
        {{ chooseSeatList.length ? (`￥${totalPrice} 确认座位`) : '请选座位' }}
      </wd-button>
    </view>
  </view>
</template>

<style lang="scss" scoped>
.view-page {
  background-color: #f7f9fc;
}

.bg-white {
  background-color: #fff;
}

/* 核心样式 */
.areaList {
  display: flex;
  align-items: center;
  /* 上下居中 */
  /* 左右居中（可选） */
  height: 40px;
  white-space: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  /* Firefox */
  -ms-overflow-style: none;
  /* IE/Edge */
}

.areaList::-webkit-scrollbar {
  display: none;
  /* Chrome、Safari、微信小程序-web-view */
}

.area-item {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  margin: 0 8px;
}

.area {
  width: 20px;
  height: 20px;
  border-radius: 4px;
}

.area-price {
  margin-left: 10rpx;
  font-size: 20rpx;
  line-height: 20px;
}

.footer {
  position: fixed;
  left: 0;
  bottom: var(--window-bottom);
  padding: 0 15px 15px 15px;
  width: 100vw;
  box-sizing: border-box;
  border-radius: 5px 5px 0% 0%;
  z-index: 999999999;
  background: #FFFFFF;
  border-radius: 16rpx 16rpx 0rpx 0rpx;
  padding: 28rpx 24rpx;
  box-sizing: border-box;
  .notice{
    font-size: 24rpx;
    color: #FF4A39;
    margin-top: 24rpx;
    margin-bottom: 24rpx;
  }

  .schedule {

    .name-box {
      display: flex;
      justify-content: space-between;
      .film-name {
        font-weight: bold;
        font-size: 32rpx;
        color: #222222;
      }
      .change-box {
        display: flex;
        align-items: center;
        font-size: 24rpx;
        color: #222222;
        .arrow{
          width: 32rpx;
          height: 32rpx;
          transform: rotate(90deg);
        }
      }
    }

      .film-info {
        font-size: 24rpx;
        color: #AAAAAA;
        margin-top: 20rpx;
      }

  }
}
.time-list{
  display: flex;
  flex-wrap: nowrap;
  scrollbar-width: none;
  margin-top: 24rpx;
  overflow-x: auto;
  white-space: nowrap;
    /* Firefox */
  -ms-overflow-style: none;
  /* IE/Edge */
  .time-item{
    flex-shrink: 0;
    width: 160rpx;
    height: 114rpx;
    background: #F9F9F9;
    border-radius: 16rpx 16rpx 16rpx 16rpx;
    box-sizing: border-box;
    padding: 10rpx 0;
    text-align: center;
    margin-right: 20rpx;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    .time{
      font-size: 24rpx;
      color: #222222;
    }
    .type{
      font-size: 22rpx;
      color: #AAAAAA;
    }
    .price{
      font-size: 22rpx;
      color: #222222;
    }
  }
    .time-item.active {
      background: #FFE7E5;
    }

}

.seat-list {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  overflow-x: auto;
  white-space: nowrap;
  margin-top: 5px;
  scrollbar-width: none;
  margin-top: 24rpx;
  /* Firefox */
  -ms-overflow-style: none;
  /* IE/Edge */
}

.seat-list::-webkit-scrollbar {
  display: none;
  /* Chrome、Safari、微信小程序-web-view */
}

.seat-item {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 80rpx;
  background: #F9F9F9;
  border-radius: 16rpx 16rpx 16rpx 16rpx;
  box-sizing: border-box;
  padding: 10rpx 16rpx;
  margin-right: 20rpx;
  .seat-name {
    font-size: 24rpx;
    color: #222222;
  }

  .seat-price {
    font-size: 22rpx;
    color: #222222;
    margin-top: 10rpx;

  }

  .delete-seat {
    width: 20px;
    height: 20px;
    line-height: 20px;
    color: #727272;
    text-align: center;
    margin-left: 16rpx;
  }

}

.confirm {
  width: 100%;
  height: 80rpx;
  line-height: 80rpx;
  text-align: center;
  border-radius: 10px;
  font-size: 14px;
  color: #fff;
  background-color: #e54f4f;
}

.unbtn {
  background-color: #f69c9c;
}
</style>
