<template>
  <view class="page-shell cust-appt-create">
    <view class="create-nav nav-gradient" :style="navSafeStyle">
      <view class="nav-back" @click="goBack"><AppIcon name="back" :size="18" color="#ffffff" /></view>
      <text class="nav-title">创建预约</text>
      <view style="width:32px"></view>
    </view>

    <view class="c-hero">
      <text class="c-hero-title">预约宠物服务</text>
      <text class="c-hero-sub">在线预约，专业服务</text>
    </view>

    <view class="c-form-card">
      <view v-if="useCompactStoreRow" class="c-field">
        <text class="app-form-label">预约门店</text>
        <view class="c-store-summary-row">
          <text class="c-store-summary-name">{{ currentStoreDisplayName }}</text>
          <text
            v-if="orderedStores.length > 1 && storeLockedCompact"
            class="c-store-change-link"
            @click="expandStorePicker"
          >更换门店</text>
        </view>
        <text v-if="storeHintLine" class="c-store-hint">{{ storeHintLine }}</text>
      </view>
      <view v-else class="c-field">
        <text class="app-form-label">预约门店</text>
        <picker
          mode="selector"
          :range="orderedStores"
          range-key="pickerLabel"
          :value="selectedStoreIndex"
          :disabled="!orderedStores.length"
          @change="onStorePickerChange"
        >
          <view class="app-form-input app-form-picker">
            <text :class="{ 'app-form-placeholder': !orderedStores.length }">{{ storePickerDisplay }}</text>
            <text class="app-form-arrow">›</text>
          </view>
        </picker>
        <text
          v-if="showCollapseStoreLink"
          class="c-store-collapse"
          @click="onCollapseStorePicker"
        >收起</text>
        <text v-if="storeHintLine" class="c-store-hint">{{ storeHintLine }}</text>
      </view>
      <view class="c-field">
        <text class="app-form-label">宠物名字</text>
        <view class="pet-name-row">
          <input
            v-model="newAppt.petName"
            class="app-form-input pet-name-input"
            placeholder="请输入宠物名字"
            @input="onPetNameInput"
          />
          <button
            v-if="myPets.length > 1"
            class="app-btn-sm app-btn-soft pet-switch-btn"
            @click="openPetSwitcher"
          >切换宠物</button>
        </view>
      </view>
      <view class="c-field">
        <text class="app-form-label">宠物类型</text>
        <picker mode="selector" :range="petTypes" range-key="label" @change="onPetTypeChange">
          <view class="app-form-input app-form-picker">
            <text :class="{ 'app-form-placeholder': !newAppt.petType }">{{ newAppt.petType || '请选择' }}</text>
            <text class="app-form-arrow">›</text>
          </view>
        </picker>
      </view>
      <view class="c-field">
        <text class="app-form-label">服务类型</text>
        <picker mode="selector" :range="serviceTypes" range-key="label" @change="e => newAppt.serviceType = serviceTypes[e.detail.value].value">
          <view class="app-form-input app-form-picker">
            <text :class="{ 'app-form-placeholder': !newAppt.serviceType }">{{ newAppt.serviceType || '请选择' }}</text>
            <text class="app-form-arrow">›</text>
          </view>
        </picker>
      </view>
      <view class="c-field">
        <text class="app-form-label">预约时段</text>
        <view class="c-time-row">
          <picker mode="date" :value="selectedDateStr" @change="onAppointmentDateChange" class="c-time-half">
            <view class="app-form-input app-form-picker">
              <text :class="{ 'app-form-placeholder': !selectedDateStr }">{{ selectedDateStr || '日期' }}</text>
            </view>
          </picker>
          <picker
            mode="selector"
            :range="availableSlotLabels"
            :value="slotPickerIndex"
            :disabled="!availableTimes.length"
            @change="onAppointmentTimeOnlyChange"
            class="c-time-half c-time-half--slot"
          >
            <view class="app-form-input app-form-picker">
              <text class="slot-range-text" :class="{ 'app-form-placeholder': !appointmentTime && !loadingSlots }">{{ loadingSlots ? '加载中…' : (selectedSlotRangeLabel || '选择时段') }}</text>
            </view>
          </picker>
        </view>
        <text class="c-store-hint">{{ bookingWindowHint }}</text>
        <button
          v-if="showTryTomorrow"
          class="app-btn-sm app-btn-soft c-try-tomorrow"
          @click="tryPickTomorrow"
        >试选明天</button>
      </view>
      <view class="c-field">
        <text class="app-form-label">备注（可选）</text>
        <input v-model="newAppt.remark" class="app-form-input" placeholder="可选" />
      </view>
      <button class="app-btn-main app-btn-primary" style="margin-top:20px" :loading="creatingAppt" @click="confirmNewAppt">提交预约</button>
    </view>
  </view>
</template>

<script setup>
import { ref, computed, onMounted, watch } from 'vue'
import { onLoad, onUnload } from '@dcloudio/uni-app'
import {
  createAppointment,
  getServiceTypeList,
  getPetList,
  getStoreList,
  createPet,
  getAppointmentAvailableSlots
} from '../../api/index.js'
import AppIcon from '../../components/AppIcon.vue'
import { getUserSession, getStoreSession, setStoreSession, getGuestApptDraft, saveGuestApptDraft, clearGuestApptDraft, apptDraftUserKey } from '../../utils/session.js'
import { haversineKm } from '../../utils/geo.js'
import { normalizeToHalfHour, ymdLocal, formatHalfHourSlotRange } from '../../utils/halfHourTime.js'

const userInfo = getUserSession()
const storeInfo = getStoreSession()
const LAST_SUBMITTED_PET_KEY = `petstore_last_submitted_pet_${userInfo.id || 'guest'}`

const BOOKING_STORE_ID_KEY = 'petstore_booking_store_id'

const lastServiceStorageKey = (storeId) =>
  `petstore_last_service_${userInfo.id || 'guest'}_${storeId}`

/** 扫码/深链带入的门店 id，用于预填并支持折叠展示 */
const routeStoreId = ref('')
const storeExpanded = ref(false)

/**
 * 解析小程序码 scene 字段中的 storeId。
 * 支持形如 `storeId=1`、`sid=1`、`?storeId=1` 的 query 串；也兼容被 encodeURIComponent 编码过的字符串。
 */
function parseSceneStoreId(scene) {
  if (!scene) return ''
  let decoded = String(scene)
  try { decoded = decodeURIComponent(decoded) } catch (_) {}
  const params = new URLSearchParams(decoded.replace(/^\?/, ''))
  return params.get('storeId') || params.get('sid') || ''
}

const orderedStores = ref([])
const selectedStoreIndex = ref(0)
const hasUserLocation = ref(false)

onLoad((options) => {
  // 读取顺序：普通 storeId query > 小程序码 scene 解码
  const directStoreId = options?.storeId != null && String(options.storeId).trim() !== ''
    ? String(options.storeId).trim()
    : ''
  routeStoreId.value = directStoreId || parseSceneStoreId(options?.scene)
})

const storeLockedCompact = computed(() => {
  if (!routeStoreId.value || !orderedStores.value.length) return false
  const cur = orderedStores.value[selectedStoreIndex.value]
  return !!(cur && String(cur.id) === String(routeStoreId.value))
})

const useCompactStoreRow = computed(() => {
  if (!orderedStores.value.length) return false
  if (orderedStores.value.length === 1) return true
  return storeLockedCompact.value && !storeExpanded.value
})

const showCollapseStoreLink = computed(
  () =>
    !!routeStoreId.value &&
    orderedStores.value.length > 1 &&
    storeLockedCompact.value &&
    storeExpanded.value
)

const currentStoreDisplayName = computed(() => {
  const row = orderedStores.value[selectedStoreIndex.value]
  if (!row) return orderedStores.value.length ? '请选择' : '暂无可选门店'
  return row.pickerLabel || row.name || '—'
})

const expandStorePicker = () => {
  storeExpanded.value = true
}

const onCollapseStorePicker = () => {
  storeExpanded.value = false
}

const navSafeStyle = (() => {
  const statusBarHeight = uni.getSystemInfoSync?.().statusBarHeight || 20
  let navHeight = statusBarHeight + 44
  const menuRect = uni.getMenuButtonBoundingClientRect?.()
  if (menuRect && menuRect.top && menuRect.height) {
    const verticalGap = Math.max(menuRect.top - statusBarHeight, 4)
    navHeight = statusBarHeight + verticalGap * 2 + menuRect.height
  }
  return `padding-top:${statusBarHeight}px;height:${navHeight}px;`
})()

const petTypes = [
  { label: '猫', value: '猫' },
  { label: '狗', value: '狗' },
  { label: '其他', value: '其他' }
]

const serviceTypes = ref([])

const storePickerDisplay = computed(() => {
  const row = orderedStores.value[selectedStoreIndex.value]
  if (!row) return orderedStores.value.length ? '请选择' : '暂无可选门店'
  return row.pickerLabel
})

const storeHintLine = computed(() => {
  if (!orderedStores.value.length) return ''
  if (hasUserLocation.value) return '已根据定位优先展示最近门店，可点击切换'
  return '未获取到定位时按列表排序，可手动选择门店'
})

const buildOrderedStores = (raw, lat, lng) => {
  const withDist = raw.map((s) => {
    const d =
      lat != null && lng != null ? haversineKm(lat, lng, s.latitude, s.longitude) : null
    return { ...s, distKm: d }
  })
  withDist.sort((a, b) => {
    if (a.distKm == null && b.distKm == null) return (a.name || '').localeCompare(b.name || '', 'zh')
    if (a.distKm == null) return 1
    if (b.distKm == null) return -1
    return a.distKm - b.distKm
  })
  return withDist.map((s) => ({
    ...s,
    pickerLabel:
      s.distKm != null
        ? `${s.name} · 约${s.distKm < 10 ? s.distKm.toFixed(1) : Math.round(s.distKm)}km`
        : s.name
  }))
}

const applySelectedStoreToSession = () => {
  const s = orderedStores.value[selectedStoreIndex.value]
  if (!s?.id) return
  uni.setStorageSync(BOOKING_STORE_ID_KEY, s.id)
  setStoreSession({
    id: s.id,
    name: s.name,
    address: s.address,
    phone: s.phone,
    latitude: s.latitude,
    longitude: s.longitude,
    logo: s.logo
  })
}

const initStoresAndLocation = async () => {
  const res = await getStoreList()
  if (res.code !== 200 || !Array.isArray(res.data) || !res.data.length) {
    uni.showToast({ title: '暂无可预约门店', icon: 'none' })
    return
  }
  let lat
  let lng
  try {
    const loc = await new Promise((resolve, reject) => {
      uni.getLocation({
        type: 'gcj02',
        success: resolve,
        fail: reject
      })
    })
    lat = loc.latitude
    lng = loc.longitude
    hasUserLocation.value = true
  } catch (_) {
    hasUserLocation.value = false
  }

  orderedStores.value = buildOrderedStores(res.data, lat, lng)

  const savedId = uni.getStorageSync(BOOKING_STORE_ID_KEY)
  const sid = storeInfo?.id ?? userInfo?.storeId
  let pickIdx = 0
  const qrIdx =
    routeStoreId.value && orderedStores.value.length
      ? orderedStores.value.findIndex((x) => String(x.id) === String(routeStoreId.value))
      : -1
  if (qrIdx >= 0) {
    pickIdx = qrIdx
    storeExpanded.value = false
  } else if (savedId && orderedStores.value.some((x) => String(x.id) === String(savedId))) {
    pickIdx = orderedStores.value.findIndex((x) => String(x.id) === String(savedId))
  } else if (sid && orderedStores.value.some((x) => String(x.id) === String(sid))) {
    pickIdx = orderedStores.value.findIndex((x) => String(x.id) === String(sid))
  }
  selectedStoreIndex.value = Math.max(0, pickIdx)
  applySelectedStoreToSession()
}

const onStorePickerChange = async (e) => {
  selectedStoreIndex.value = Number(e.detail.value)
  applySelectedStoreToSession()
  newAppt.value.serviceType = ''
  await loadServiceTypesForSelected()
  await loadAvailableSlots()
}
const myPets = ref([])
const selectedPetId = ref(null)
const newAppt = ref({ petName: '', petType: '', serviceType: '', appointmentTime: '', remark: '' })
const creatingAppt = ref(false)

/** 与日期选择器同步，避免无号源时丢失已选日期 */
const selectedDateStr = ref(ymdLocal())
const availableTimes = ref([])
const loadingSlots = ref(false)
const bookingWindowHint = ref('请选择半小时时间段；同一时段仅接待一单，已满或已过期不可选')

const normalizeText = (s) => (s || '').toString().trim().toLowerCase()

const findMatchedPet = (name, petType) =>
  myPets.value.find(
    (p) => normalizeText(p.name) === normalizeText(name) && normalizeText(p.petType) === normalizeText(petType)
  )

const applyPetToForm = (pet) => {
  if (!pet) return
  selectedPetId.value = pet.id || null
  newAppt.value.petName = pet.name || ''
  newAppt.value.petType = pet.petType || ''
}

const openPetSwitcher = () => {
  if (myPets.value.length <= 1) return
  uni.showActionSheet({
    itemList: myPets.value.map((p) => `${p.name}（${p.petType}）`),
    success: (res) => {
      const pet = myPets.value[res.tapIndex]
      if (pet) applyPetToForm(pet)
    }
  })
}

const onPetNameInput = (e) => {
  const currentName = e?.detail?.value ?? newAppt.value.petName
  if (!selectedPetId.value) return
  const cur = myPets.value.find((p) => p.id === selectedPetId.value)
  if (!cur) {
    selectedPetId.value = null
    return
  }
  if (normalizeText(currentName) !== normalizeText(cur.name)) {
    selectedPetId.value = null
  }
}

const onPetTypeChange = (e) => {
  const i = Number(e.detail.value)
  const nextType = petTypes[i]?.value || ''
  newAppt.value.petType = nextType
  if (!selectedPetId.value) return
  const cur = myPets.value.find((p) => p.id === selectedPetId.value)
  if (!cur || normalizeText(nextType) !== normalizeText(cur.petType)) {
    selectedPetId.value = null
  }
}

const appointmentTime = computed(() => {
  const raw = newAppt.value.appointmentTime || ''
  if (!raw.includes('T')) return ''
  const part = (raw.split('T')[1] || '').slice(0, 5)
  return normalizeToHalfHour(part)
})

const slotPickerIndex = computed(() => {
  const t = appointmentTime.value
  const i = availableTimes.value.indexOf(t)
  return i >= 0 ? i : 0
})

/** 滚轮选项展示为「09:00–09:30」 */
const availableSlotLabels = computed(() =>
  availableTimes.value.map((t) => formatHalfHourSlotRange(t))
)

const selectedSlotRangeLabel = computed(() =>
  appointmentTime.value ? formatHalfHourSlotRange(appointmentTime.value) : ''
)

const showTryTomorrow = computed(
  () =>
    !loadingSlots.value &&
    !!selectedDateStr.value &&
    availableTimes.value.length === 0
)

const tryPickTomorrow = () => {
  const cur = selectedDateStr.value
  if (!cur) return
  const parts = cur.split('-').map((x) => parseInt(x, 10))
  if (parts.length !== 3 || parts.some((n) => Number.isNaN(n))) return
  const d = new Date(parts[0], parts[1] - 1, parts[2])
  if (Number.isNaN(d.getTime())) return
  d.setDate(d.getDate() + 1)
  selectedDateStr.value = ymdLocal(d)
  loadAvailableSlots()
}

const loadAvailableSlots = async () => {
  const row = orderedStores.value[selectedStoreIndex.value]
  const storeId = row?.id
  const date = selectedDateStr.value
  if (!storeId || !date) {
    availableTimes.value = []
    return
  }
  loadingSlots.value = true
  try {
    const res = await getAppointmentAvailableSlots(storeId, date)
    loadingSlots.value = false
    if (res.code !== 200 || !res.data?.slots) {
      availableTimes.value = []
      uni.showToast({ title: res.message || '号源加载失败', icon: 'none' })
      return
    }
    const ds = res.data.dayStart
    const le = res.data.lastSlotStart
    if (ds != null && le != null) {
      const a = String(ds).slice(0, 5)
      const b = String(le).slice(0, 5)
      bookingWindowHint.value = `本店可约 ${a}～${b}；以下为半小时时段，同一时段仅一单，已满或已过不可选`
    }
    availableTimes.value = res.data.slots.filter((s) => s.available).map((s) => s.time)
    if (!availableTimes.value.length) {
      newAppt.value.appointmentTime = ''
      uni.showToast({ title: '当日已无号源，请换一天', icon: 'none' })
      return
    }
    const raw = newAppt.value.appointmentTime || ''
    const datePart = raw.includes('T') ? raw.split('T')[0] : ''
    const timePart = raw.includes('T')
      ? normalizeToHalfHour((raw.split('T')[1] || '').slice(0, 5))
      : ''
    if (datePart === date && timePart && availableTimes.value.includes(timePart)) {
      newAppt.value.appointmentTime = `${date}T${timePart}`
    } else {
      newAppt.value.appointmentTime = `${date}T${availableTimes.value[0]}`
    }
  } catch (_) {
    loadingSlots.value = false
    availableTimes.value = []
    uni.showToast({ title: '号源加载失败', icon: 'none' })
  }
}

const onAppointmentDateChange = (e) => {
  const date = e?.detail?.value || ''
  if (!date) {
    selectedDateStr.value = ''
    newAppt.value.appointmentTime = ''
    availableTimes.value = []
    return
  }
  selectedDateStr.value = date
  loadAvailableSlots()
}

const onAppointmentTimeOnlyChange = (e) => {
  const idx = Number(e.detail.value)
  const time = availableTimes.value[idx]
  const date = selectedDateStr.value
  if (!date) {
    uni.showToast({ title: '请先选择日期', icon: 'none' })
    return
  }
  if (!time) return
  newAppt.value.appointmentTime = `${date}T${time}`
}

const loadServiceTypesForSelected = async () => {
  const row = orderedStores.value[selectedStoreIndex.value]
  const sid = row?.id
  const res = await getServiceTypeList(sid ?? undefined)
  if (res.code === 200 && Array.isArray(res.data)) {
    serviceTypes.value = res.data.map((s) => ({ label: s.name, value: s.name }))
    if (sid) {
      try {
        const last = uni.getStorageSync(lastServiceStorageKey(sid))
        if (last && serviceTypes.value.some((s) => s.value === last)) {
          newAppt.value.serviceType = last
        }
      } catch (_) {}
    }
  }
}

const hydrateDefaultPet = () => {
  if (!myPets.value.length) return
  let picked = null
  try {
    const saved = JSON.parse(uni.getStorageSync(LAST_SUBMITTED_PET_KEY) || 'null')
    if (saved) {
      if (saved.petId) picked = myPets.value.find((p) => String(p.id) === String(saved.petId)) || null
      if (!picked && saved.name && saved.petType) picked = findMatchedPet(saved.name, saved.petType) || null
    }
  } catch (_) {}
  if (!picked) picked = myPets.value[0]
  applyPetToForm(picked)
}

const rememberLastSubmittedPet = (pet) => {
  if (!pet) return
  uni.setStorageSync(
    LAST_SUBMITTED_PET_KEY,
    JSON.stringify({ petId: pet.id || null, name: pet.name || '', petType: pet.petType || '' })
  )
}

const ensurePetProfile = async (name, petType) => {
  const current = myPets.value.find((p) => String(p.id) === String(selectedPetId.value))
  if (
    current &&
    normalizeText(current.name) === normalizeText(name) &&
    normalizeText(current.petType) === normalizeText(petType)
  ) {
    return current
  }
  const matched = findMatchedPet(name, petType)
  if (matched) {
    selectedPetId.value = matched.id || null
    return matched
  }
  const res = await createPet({
    ownerUserId: userInfo.id,
    name: name.trim(),
    petType: petType
  })
  if (res.code !== 200 || !res.data) {
    return null
  }
  const created = res.data
  myPets.value.unshift(created)
  selectedPetId.value = created.id || null
  return created
}

const confirmNewAppt = async () => {
  const a = newAppt.value
  if (!a.petName) { uni.showToast({ title: '请输入宠物名字', icon: 'none' }); return }
  if (!a.petType) { uni.showToast({ title: '请选择宠物类型', icon: 'none' }); return }
  if (!a.serviceType) { uni.showToast({ title: '请选择服务类型', icon: 'none' }); return }
  if (!a.appointmentTime) { uni.showToast({ title: '请选择预约时间', icon: 'none' }); return }
  if (!availableTimes.value.includes(appointmentTime.value)) {
    uni.showToast({ title: '该时段不可预约，请重新选择', icon: 'none' })
    await loadAvailableSlots()
    return
  }
  const row = orderedStores.value[selectedStoreIndex.value]
  const storeId = row?.id
  if (!storeId) {
    uni.showToast({ title: '请先选择预约门店', icon: 'none' })
    return
  }
  // 提交时登录策略：未登录先保存 guest 草稿，跳登录页，登录后回到本页并恢复草稿。
  if (!userInfo?.id) {
    saveApptDraft()
    const target = `/pages/appointment/CustAppointmentCreate?storeId=${encodeURIComponent(storeId)}`
    const redirect = encodeURIComponent(target)
    uni.navigateTo({ url: `/pages/login/Login?redirect=${redirect}` })
    return
  }
  creatingAppt.value = true
  const ensuredPet = await ensurePetProfile(a.petName, a.petType)
  if (!ensuredPet?.id) {
    creatingAppt.value = false
    uni.showToast({ title: '宠物档案保存失败，请重试', icon: 'none' })
    return
  }
  const payload = { ...a, storeId }
  payload.petId = ensuredPet.id
  const res = await createAppointment(payload)
  creatingAppt.value = false
  if (res.code === 200) {
    rememberLastSubmittedPet(ensuredPet)
    try {
      uni.setStorageSync(lastServiceStorageKey(storeId), a.serviceType)
    } catch (_) {}
    try {
      const key = apptDraftStorageKey()
      if (key) uni.removeStorageSync(key)
      clearGuestApptDraft()
    } catch (_) {}
    uni.showToast({ title: '预约成功', icon: 'success' })
    setTimeout(() => uni.navigateBack(), 600)
  } else {
    uni.showToast({ title: res.message || '创建失败', icon: 'none' })
  }
}

const goBack = () => {
  const pages = getCurrentPages()
  if (pages.length > 1) uni.navigateBack()
  else uni.reLaunch({ url: '/pages/home/Home' })
}

const loadMyPets = async () => {
  // 未登录时跳过宠物列表请求；提交时登录后会重新加载本页并恢复草稿。
  if (!userInfo?.id) {
    myPets.value = []
    return
  }
  const res = await getPetList({ ownerUserId: userInfo.id })
  if (res.code === 200) {
    myPets.value = res.data || []
    hydrateDefaultPet()
  }
}

/**
 * P0 C3：草稿策略冻结为「提交时登录 + guest 草稿恢复」。
 * - 未登录：写入 guest 草稿 key（不依赖 userId）。
 * - 登录后：优先读 guest 草稿恢复，恢复成功后删除 guest 草稿；同时按 userId 维度保存草稿。
 * 草稿有效期 7 天。
 */
const apptDraftStorageKey = () => {
  const uid = userInfo?.id
  return uid ? apptDraftUserKey(uid) : ''
}

const buildDraftPayload = () => {
  const row = orderedStores.value[selectedStoreIndex.value]
  return {
    v: 1,
    at: Date.now(),
    petName: newAppt.value.petName,
    petType: newAppt.value.petType,
    serviceType: newAppt.value.serviceType,
    appointmentTime: newAppt.value.appointmentTime,
    remark: newAppt.value.remark,
    selectedDateStr: selectedDateStr.value,
    storeIndex: selectedStoreIndex.value,
    storeId: row?.id
  }
}

const applyDraft = (d) => {
  if (!d || d.v !== 1) return
  if (typeof d.remark === 'string') newAppt.value.remark = d.remark
  if (d.serviceType) newAppt.value.serviceType = d.serviceType
  if (d.appointmentTime) newAppt.value.appointmentTime = d.appointmentTime
  if (d.petName) newAppt.value.petName = d.petName
  if (d.petType) newAppt.value.petType = d.petType
  if (typeof d.selectedDateStr === 'string' && d.selectedDateStr) selectedDateStr.value = d.selectedDateStr
  if (typeof d.storeIndex === 'number' && orderedStores.value[d.storeIndex]) {
    selectedStoreIndex.value = d.storeIndex
    applySelectedStoreToSession()
  } else if (d.storeId && orderedStores.value.some((x) => String(x.id) === String(d.storeId))) {
    selectedStoreIndex.value = orderedStores.value.findIndex((x) => String(x.id) === String(d.storeId))
    applySelectedStoreToSession()
  }
  selectedPetId.value = null
}

const saveApptDraft = () => {
  try {
    const payload = buildDraftPayload()
    // 未登录：只写 guest 草稿；登录态：按 userId 维度保存。
    if (!userInfo?.id) {
      saveGuestApptDraft(payload)
      return
    }
    const key = apptDraftStorageKey()
    if (key) uni.setStorageSync(key, JSON.stringify(payload))
  } catch (_) {}
}

const restoreApptDraft = () => {
  try {
    // 登录后优先恢复 guest 草稿（提交时登录场景），恢复后清理 guest 草稿。
    const guest = getGuestApptDraft()
    if (guest) {
      if (Date.now() - (guest.at || 0) <= 7 * 86400000) {
        applyDraft(guest)
      }
      clearGuestApptDraft()
      return
    }
    if (!userInfo?.id) return
    const key = apptDraftStorageKey()
    if (!key) return
    const raw = uni.getStorageSync(key)
    if (!raw) return
    const d = JSON.parse(raw)
    if (Date.now() - (d.at || 0) > 7 * 86400000) {
      uni.removeStorageSync(key)
      return
    }
    applyDraft(d)
  } catch (_) {}
}

let apptDraftTimer = null
watch(
  () =>
    JSON.stringify({
      n: newAppt.value,
      si: selectedStoreIndex.value,
      ds: selectedDateStr.value
    }),
  () => {
    if (apptDraftTimer) clearTimeout(apptDraftTimer)
    apptDraftTimer = setTimeout(saveApptDraft, 650)
  }
)

onUnload(() => {
  saveApptDraft()
})

onMounted(async () => {
  selectedDateStr.value = ymdLocal()
  await initStoresAndLocation()
  if (orderedStores.value.length) {
    await loadServiceTypesForSelected()
  }
  await loadMyPets()
  restoreApptDraft()
  if (orderedStores.value.length) {
    await loadServiceTypesForSelected()
  }
  await loadAvailableSlots()
})
</script>

<style scoped>
.cust-appt-create {
  background: #fafaf8;
  min-height: 100vh;
  padding-bottom: env(safe-area-inset-bottom);
}
.create-nav {
  padding: 14px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: sticky;
  top: 0;
  z-index: 10;
}
.nav-back { font-size: 20px; color: #fff; }
.nav-title { font-size: 18px; font-weight: 700; color: #fff; }

.c-hero { padding: 24px 20px 20px; }
.c-hero-title {
  display: block;
  font-size: 26px;
  font-weight: 800;
  color: #1a1a1a;
  letter-spacing: -0.5px;
}
.c-hero-sub {
  display: block;
  font-size: 14px;
  color: var(--c-text-3);
  margin-top: 4px;
}
.c-form-card {
  margin: 0 16px;
  background: #fff;
  border-radius: 16px;
  padding: 24px 20px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}
.c-field { margin-bottom: 16px; }
.c-time-row { display: flex; gap: 10px; }
.c-time-half { flex: 1; min-width: 0; }
.c-time-half--slot .slot-range-text {
  font-size: 15px;
  letter-spacing: 0;
}
.pet-name-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.pet-name-input {
  flex: 1;
  min-width: 0;
}
.pet-switch-btn {
  width: 68px !important;
  padding: 0 !important;
  color: var(--c-brand) !important;
  flex-shrink: 0;
}
.c-store-hint {
  display: block;
  margin-top: 8px;
  font-size: 13px;
  color: #666660;
  line-height: 1.5;
}
.c-store-summary-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  background: #f5f5f2;
  border-radius: 12px;
}
.c-store-summary-name {
  flex: 1;
  min-width: 0;
  font-size: 15px;
  font-weight: 600;
  color: #1a1a1a;
}
.c-store-change-link {
  flex-shrink: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--c-brand);
  padding: 6px 0 6px 8px;
}
.c-store-collapse {
  display: block;
  margin-top: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--c-brand);
}
.c-try-tomorrow {
  margin-top: 12px;
  width: 100%;
}
</style>
