<template>
  <view class="safe-page detail-page">
    <scroll-view scroll-y class="detail-scroll">
      <swiper v-if="images.length" class="swiper" circular indicator-dots>
        <swiper-item v-for="img in images" :key="img">
          <image class="hero-img" :src="img" mode="aspectFill" />
        </swiper-item>
      </swiper>
      <view v-else class="empty-img">订餐</view>

    <view v-if="item" class="card main-card">
      <view class="title-row">
        <view class="name">{{ item.itemName }}</view>
        <view class="price">¥{{ formatMoney(finalSalePrice) }}</view>
      </view>
      <view v-if="item.tags?.length" class="tags">
        <text v-for="tag in item.tags" :key="tag" class="tag">{{ tag }}</text>
      </view>
      <view :class="['stock', soldOut && 'danger']">{{ stockText }}</view>
    </view>

    <view v-if="item" class="card info-card" @click="goServiceAreaSelect">
      <view class="section-title">当前服务区域</view>
      <view class="area-row">
        <view>
          <view class="area-name">{{ currentServiceArea?.name || item.serviceArea?.name || item.restaurant?.name || '未选择服务区域' }}</view>
          <view class="muted">{{ currentServiceArea?.floorLabel || currentServiceArea?.locationLabel || item.serviceArea?.locationLabel || item.serviceArea?.address || item.restaurant?.locationLabel || item.restaurant?.address || '暂无位置信息' }}</view>
          <view v-if="currentServiceArea?.phone || item.serviceArea?.phone || item.restaurant?.phone" class="muted">电话：{{ currentServiceArea?.phone || item.serviceArea?.phone || item.restaurant?.phone }}</view>
        </view>
        <view class="switch-link">切换</view>
      </view>
    </view>

    <view v-if="item" class="card info-card">
      <view class="section-title">取餐信息</view>
      <view class="info-line">取货方式：自提</view>
      <view class="info-line">取货日期：{{ item.pickupDate || item.menuDate || '以订单为准' }}</view>
      <view class="info-line">取餐点：{{ item.pickupLocation || currentServiceArea?.pickupLocation || '以现场通知为准' }}</view>
    </view>

    <view v-if="item" class="card info-card">
      <view class="section-title">下单倒计时</view>
      <view :class="['countdown', hasDeadline && countdown <= 0 && 'danger']">{{ countdownText }}</view>
    </view>

    <view v-if="item?.specs?.length" class="card info-card">
      <view class="section-title">菜品规格</view>
      <view class="specs">
        <view v-for="spec in item.specs" :key="spec.id || spec.name" :class="['spec', isSpecSelected(spec) && 'active']" @click="selectSpec(spec)">
          <view>{{ spec.name }}</view>
          <view v-if="spec.description" class="muted">{{ spec.description }}</view>
          <view class="muted">{{ specStockText(spec) }}</view>
        </view>
      </view>
    </view>

    <view v-if="item" class="card info-card">
      <view class="section-title">购买数量</view>
      <view class="stepper-row">
        <view class="stepper">
          <view :class="['step-btn', quantity <= 1 && 'step-disabled']" @click="changeQuantity(-1)">-</view>
          <text class="step-num">{{ quantity }}</text>
          <view :class="['step-btn', quantity >= maxQuantity && 'step-disabled']" @click="changeQuantity(1)">+</view>
        </view>
        <view v-if="maxQuantityText" class="muted step-tip">{{ maxQuantityText }}</view>
      </view>
    </view>

      <view v-if="item?.descriptionHtml" class="card info-card">
        <view class="section-title">菜品描述</view>
        <rich-text :nodes="item.descriptionHtml" />
      </view>
      <view class="detail-bottom-spacer" />
    </scroll-view>

    <view class="bottom-bar">
      <button :class="['buy-btn', (!canBuy || loading) && 'disabled']" :disabled="!canBuy || loading" @click="buyNow">{{ buttonText }}</button>
    </view>
  </view>
</template>

<script setup lang="ts">
import { computed, onUnmounted, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { fetchMealMenuItemDetail } from '@/api/modules/meal'
import { fetchCompanyMealMenuItemDetail, trialCompanyMealOrder } from '@/api/modules/companyMeal'
import { useCompanyStore } from '@/store/modules/company'
import { useMealStore } from '@/store/modules/meal'
import type { FoodMealMenuItemDetail, FoodMealMenuItemSpec } from '@/types/meal'
import { formatMoney } from '@/utils/money'
import { requireLoginNavigate } from '@/utils/auth'

type StockSnapshot = {
  stockQuantity?: number | null
  soldQuantity?: number | null
  remainingQuantity?: number | null
  soldOut?: boolean
  limitQuantityPerUser?: number | null
}

type SpecWithStock = FoodMealMenuItemSpec & StockSnapshot

const company = useCompanyStore()
const meal = useMealStore()
const item = ref<FoodMealMenuItemDetail | null>(null)
const loading = ref(false)
const menuItemId = ref('')
const mode = ref<'personal' | 'company'>('personal')
const companyId = ref('')
const countdown = ref(0)
const selectedSpec = ref<SpecWithStock | null>(null)
const quantity = ref(1)
let timer: ReturnType<typeof setInterval> | null = null
let countdownRefreshed = false

const currentServiceArea = computed(() => item.value?.serviceArea || meal.currentServiceArea || item.value?.restaurant)
const detailServiceAreaId = computed(() => item.value?.serviceAreaId || item.value?.serviceArea?.id || item.value?.restaurantId || item.value?.restaurant?.id)
const serviceAreaChanged = computed(() => {
  return Boolean(meal.currentServiceArea?.id && detailServiceAreaId.value && meal.currentServiceArea.id !== detailServiceAreaId.value)
})
const images = computed(() => item.value?.images?.length ? item.value.images : (item.value?.itemImage ? [item.value.itemImage] : []))
const hasSpecs = computed(() => Boolean(item.value?.specs?.length))
const finalSalePrice = computed(() => selectedSpec.value?.salePrice ?? item.value?.salePrice ?? 0)
const currentStockSource = computed<StockSnapshot | null>(() => selectedSpec.value || item.value)
const currentLimitQuantityPerUser = computed(() => selectedSpec.value?.limitQuantityPerUser ?? item.value?.limitQuantityPerUser ?? null)
const currentRemainingQuantity = computed(() => currentStockSource.value ? remainingQuantity(currentStockSource.value) : null)
const soldOut = computed(() => {
  if (selectedSpec.value?.soldOut === true) return true
  if (!selectedSpec.value && item.value?.soldOut === true) return true
  return currentRemainingQuantity.value != null && currentRemainingQuantity.value <= 0
})
const hasDeadline = computed(() => item.value?.deadlineRemainSeconds != null)
const maxQuantity = computed(() => {
  const stock = currentRemainingQuantity.value == null ? 999 : currentRemainingQuantity.value
  const limit = currentLimitQuantityPerUser.value == null ? 999 : currentLimitQuantityPerUser.value
  return Math.max(Math.min(stock, limit), 1)
})
const maxQuantityText = computed(() => {
  const remain = currentRemainingQuantity.value
  const limit = currentLimitQuantityPerUser.value
  if (remain != null && limit != null) return `本单最多可选 ${Math.min(remain, limit)} 份`
  if (remain != null) return `本单最多可选 ${remain} 份`
  if (limit != null) return `每人限购 ${limit} 份`
  return ''
})
const canBuy = computed(() => Boolean(item.value && !soldOut.value && item.value.orderable !== false && (!hasDeadline.value || countdown.value > 0)))
const stockText = computed(() => {
  const remain = currentRemainingQuantity.value
  const stock = remain == null ? '库存充足' : (remain <= 0 ? '仅剩 0，已售罄' : `仅剩 ${remain} 份`)
  if (currentLimitQuantityPerUser.value != null) return `${stock}，每人限购 ${currentLimitQuantityPerUser.value} 份`
  return stock
})
const countdownText = computed(() => {
  if (item.value?.orderable === false) return item.value.notOrderableReason || '已停止接单'
  if (hasDeadline.value && countdown.value <= 0) return '已截单/停止接单'
  if (!hasDeadline.value) return '随时可订'
  const h = Math.floor(countdown.value / 3600).toString().padStart(2, '0')
  const m = Math.floor((countdown.value % 3600) / 60).toString().padStart(2, '0')
  const s = Math.floor(countdown.value % 60).toString().padStart(2, '0')
  return `${h}:${m}:${s}`
})
const buttonText = computed(() => {
  if (soldOut.value) return '已售罄'
  if (item.value?.orderable === false) return '已停止接单'
  if (hasDeadline.value && countdown.value <= 0) return '已截单'
  return '立即购买'
})

onLoad(async query => {
  menuItemId.value = String(query?.menuItemId || '')
  mode.value = query?.mode === 'company' ? 'company' : 'personal'
  companyId.value = String(query?.companyId || '')
  await loadDetail()
})

onUnmounted(() => stopTimer())

async function loadDetail() {
  if (!menuItemId.value) return
  loading.value = true
  try {
    const currentCompanyId = companyId.value || company.currentCompany?.companyId
    const res = mode.value === 'company' && currentCompanyId
      ? await fetchCompanyMealMenuItemDetail(currentCompanyId, menuItemId.value)
      : await fetchMealMenuItemDetail(menuItemId.value)
    const detail = res.data
    item.value = detail
    selectedSpec.value = detail.specs?.find(spec => !specSoldOut(spec)) || detail.specs?.[0] || null
    quantity.value = 1
    countdown.value = Math.max(Number(detail.deadlineRemainSeconds || 0), 0)
    countdownRefreshed = false
    startTimer()
  } finally {
    loading.value = false
  }
}

function startTimer() {
  stopTimer()
  if (!item.value || !hasDeadline.value || countdown.value <= 0) return
  timer = setInterval(async () => {
    countdown.value = Math.max(countdown.value - 1, 0)
    if (countdown.value <= 0) {
      stopTimer()
      if (!countdownRefreshed) {
        countdownRefreshed = true
        await refreshDetailOnce()
      }
    }
  }, 1000)
}

function stopTimer() {
  if (timer) clearInterval(timer)
  timer = null
}

async function refreshDetailOnce() {
  if (!menuItemId.value) return
  const currentCompanyId = companyId.value || company.currentCompany?.companyId
  const res = mode.value === 'company' && currentCompanyId
    ? await fetchCompanyMealMenuItemDetail(currentCompanyId, menuItemId.value)
    : await fetchMealMenuItemDetail(menuItemId.value)
  const detail = res.data
  item.value = detail
  selectedSpec.value = detail.specs?.find(spec => selectedSpec.value?.id ? spec.id === selectedSpec.value.id : spec.name === selectedSpec.value?.name) as SpecWithStock || detail.specs?.find(spec => !specSoldOut(spec)) || detail.specs?.[0] || null
  countdown.value = Math.max(Number(detail.deadlineRemainSeconds || 0), 0)
}

function modeQuery() {
  const params = [`mode=${mode.value}`]
  const currentCompanyId = companyId.value || company.currentCompany?.companyId
  if (mode.value === 'company' && currentCompanyId) params.push(`companyId=${encodeURIComponent(currentCompanyId)}`)
  return params.join('&')
}

function goServiceAreaSelect() {
  uni.navigateTo({ url: `/package-views/pages/meal/restaurant-select?from=detail&${modeQuery()}` })
}

function remainingQuantity(source: { stockQuantity?: number | null; soldQuantity?: number | null; remainingQuantity?: number | null }) {
  if (source.remainingQuantity != null) return source.remainingQuantity
  if (source.stockQuantity == null) return null
  return Math.max(source.stockQuantity - (source.soldQuantity || 0), 0)
}

function specSoldOut(spec: FoodMealMenuItemSpec) {
  const snapshot = spec as SpecWithStock
  const remain = remainingQuantity(snapshot)
  return snapshot.soldOut === true || (remain != null && remain <= 0)
}

function specStockText(spec: FoodMealMenuItemSpec) {
  const snapshot = spec as SpecWithStock
  const remain = remainingQuantity(snapshot)
  const stock = remain == null ? '库存充足' : (remain <= 0 ? '仅剩 0，已售罄' : `仅剩 ${remain} 份`)
  if (snapshot.limitQuantityPerUser != null) return `${stock}，每人限购 ${snapshot.limitQuantityPerUser} 份`
  return stock
}

function selectSpec(spec: FoodMealMenuItemSpec) {
  selectedSpec.value = spec as SpecWithStock
  quantity.value = 1
}

function changeQuantity(delta: number) {
  if (delta < 0 && quantity.value <= 1) return
  if (delta > 0 && quantity.value >= maxQuantity.value) return
  const next = Math.max(1, Math.min(quantity.value + delta, maxQuantity.value))
  if (next === quantity.value && delta > 0) {
    uni.showToast({ title: '已达可选上限', icon: 'none' })
  }
  quantity.value = next
}

function isSpecSelected(spec: FoodMealMenuItemSpec) {
  if (!selectedSpec.value) return false
  if (selectedSpec.value.id || spec.id) return selectedSpec.value.id === spec.id
  return selectedSpec.value.name === spec.name
}

async function buyNow() {
  if (!item.value || !canBuy.value) return
  if (serviceAreaChanged.value) {
    uni.showModal({
      title: '服务区域已切换',
      content: '请返回菜单重新选择当前服务区域的菜品',
      confirmText: '返回菜单',
      success: res => {
        if (res.confirm) uni.redirectTo({ url: `/package-views/pages/meal/menu?${modeQuery()}` })
      }
    })
    return
  }
  if (!requireLoginNavigate(`/package-views/pages/meal/detail?menuItemId=${encodeURIComponent(menuItemId.value)}&${modeQuery()}`)) return
  if (hasSpecs.value && !selectedSpec.value?.id) {
    uni.showToast({ title: '请选择规格', icon: 'none' })
    return
  }
  const currentCompanyId = companyId.value || company.currentCompany?.companyId
  if (mode.value === 'company' && !currentCompanyId) {
    uni.showToast({ title: '请选择企业', icon: 'none' })
    return
  }
  const serviceArea = item.value.serviceArea || item.value.restaurant || currentServiceArea.value
  const stockSnapshot = selectedSpec.value || item.value
  const checkoutItem = {
    menuItemId: item.value.id,
    specId: selectedSpec.value?.id,
    specName: selectedSpec.value?.name,
    specDescription: selectedSpec.value?.description,
    quantity: quantity.value,
    itemName: item.value.itemName,
    salePrice: finalSalePrice.value,
    totalAmount: finalSalePrice.value * quantity.value,
    stockQuantity: stockSnapshot.stockQuantity,
    soldQuantity: stockSnapshot.soldQuantity,
    remainingQuantity: remainingQuantity(stockSnapshot),
    limitQuantityPerUser: stockSnapshot.limitQuantityPerUser
  }
  let trial
  if (mode.value === 'company' && currentCompanyId) {
    const trialRes = await trialCompanyMealOrder({
      companyId: currentCompanyId,
      serviceAreaId: detailServiceAreaId.value || serviceArea?.id,
      menuId: item.value.menuId,
      mealDate: item.value.menuDate || '',
      mealType: item.value.mealType || '',
      items: [{ menuItemId: item.value.id, specId: selectedSpec.value?.id, quantity: quantity.value }]
    })
    trial = {
      originalAmount: trialRes.data.originalAmount,
      discountAmount: trialRes.data.discountAmount,
      companyPayAmount: trialRes.data.companyPayAmount,
      employeePayAmount: trialRes.data.employeePayAmount
    }
  }
  uni.setStorageSync('meal_checkout_payload', {
    mode: mode.value,
    ...(mode.value === 'company' ? { companyId: currentCompanyId, companyName: company.currentCompany?.companyName, trial } : {}),
    menuId: item.value.menuId,
    serviceAreaId: detailServiceAreaId.value || serviceArea?.id,
    serviceAreaName: item.value.serviceAreaName || serviceArea?.name,
    serviceAreaPhone: serviceArea?.phone,
    serviceArea,
    mealDate: item.value.menuDate,
    mealType: item.value.mealType,
    pickupType: 'pickup',
    pickupDate: item.value.pickupDate || item.value.menuDate,
    pickupLocation: item.value.pickupLocation || item.value.serviceArea?.pickupLocation || item.value.restaurant?.pickupLocation || serviceArea?.pickupLocation,
    deadlineTime: item.value.deadlineTime,
    deadlineRemainSeconds: countdown.value,
    items: [checkoutItem],
    totalAmount: finalSalePrice.value * quantity.value
  })
  uni.navigateTo({ url: '/package-views/pages/meal/checkout' })
}
</script>

<style scoped lang="scss">
.detail-page {
  height: 100vh;
  padding: 0;
  overflow: hidden;
}
.detail-scroll {
  height: calc(100vh - 148rpx - env(safe-area-inset-bottom));
  padding: 24rpx 24rpx 0;
  box-sizing: border-box;
}
.detail-bottom-spacer {
  height: 40rpx;
}
.swiper,
.hero-img,
.empty-img {
  width: 100%;
  height: 430rpx;
  border-radius: 28rpx;
  overflow: hidden;
}
.empty-img {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #00838f;
  background: #e0f7fa;
  font-size: 42rpx;
  font-weight: 700;
}
.main-card,
.info-card {
  margin-top: 22rpx;
}
.title-row,
.area-row {
  display: flex;
  justify-content: space-between;
  gap: 20rpx;
}
.name {
  flex: 1;
  font-size: 38rpx;
  font-weight: 700;
}
.price {
  color: #ef4444;
  font-size: 38rpx;
  font-weight: 800;
}
.tags {
  margin-top: 18rpx;
  display: flex;
  gap: 10rpx;
  flex-wrap: wrap;
}
.tag {
  padding: 5rpx 14rpx;
  border-radius: 999rpx;
  background: #fff7ed;
  color: #f97316;
  font-size: 22rpx;
}
.stock,
.countdown {
  margin-top: 18rpx;
  font-size: 30rpx;
  font-weight: 700;
  color: #16a34a;
}
.danger {
  color: #ef4444;
}
.section-title {
  font-size: 30rpx;
  font-weight: 700;
  margin-bottom: 16rpx;
}
.area-name {
  font-weight: 700;
  font-size: 30rpx;
}
.switch-link {
  color: #f97316;
  font-weight: 700;
}
.info-line {
  margin-top: 10rpx;
  color: #334155;
}
.specs {
  display: flex;
  flex-direction: column;
  gap: 14rpx;
}
.spec {
  padding: 18rpx;
  border-radius: 18rpx;
  border: 2rpx solid #e2e8f0;
}
.spec.disabled {
  opacity: 0.58;
}
.spec-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16rpx;
  font-weight: 700;
}
.spec-price {
  color: #ef4444;
}
.spec.active {
  border-color: #00bcd4;
  background: #e0f7fa;
}
.stepper-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20rpx;
}
.stepper {
  display: flex;
  align-items: center;
  gap: 24rpx;
}
.step-btn {
  width: 56rpx;
  height: 56rpx;
  line-height: 52rpx;
  padding: 0;
  border-radius: 50%;
  border: 2rpx solid #e2e8f0;
  background: #f8fafc;
  font-size: 32rpx;
  color: #334155;
}
.step-btn[disabled],
.step-disabled {
  opacity: 0.4;
}
.step-num {
  min-width: 48rpx;
  text-align: center;
  font-size: 32rpx;
  font-weight: 700;
}
.step-tip {
  font-size: 24rpx;
}
.bottom-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 20rpx 28rpx calc(20rpx + env(safe-area-inset-bottom));
  background: #fff;
  box-shadow: 0 -8rpx 30rpx rgba(15, 23, 42, 0.08);
}
.buy-btn {
  height: 88rpx;
  line-height: 88rpx;
  border-radius: 999rpx;
  background: #00bcd4;
  color: #fff;
  font-weight: 700;
}
.buy-btn.disabled {
  background: #cbd5e1;
}
</style>
