<template>
  <div class="reserve-container">
    <div class="intro">请选择参观日期与时段（可预约明日起7天内，含今日展示但不可预约）</div>
    <div class="date-bar">
      <div
        class="date-chip"
        v-for="d in dateRange"
        :key="d.key"
        :class="[{ active: d.key === selectedDateKey }, { disabled: d.isToday }]"
        @click="!d.isToday && (selectedDateKey = d.key)"
      >
        <div class="d1">{{ d.label }}</div>
        <div class="d2">{{ d.dateStr }}</div>
      </div>
    </div>
    <div class="slot-panel" v-loading="loading">
      <div class="slot-empty" v-if="!slotsByDate[selectedDateKey] || slotsByDate[selectedDateKey].length === 0">暂无时段</div>
      <div class="slot-grid" v-else>
        <div class="slot-card" v-for="tp in timePoints[selectedDateKey]" :key="tp.key" :class="{ disabled: tp.disabled }">
          <div class="slot-time">{{ tp.label }}</div>
          <div class="slot-actions">
            <el-button type="primary" size="large" :disabled="tp.disabled" @click="openReserve(tp)">预约</el-button>
          </div>
        </div>
      </div>
    </div>

    <el-dialog v-model="dialogOpen" title="添加游客信息" width="600px" append-to-body>
      <el-form ref="visitorFormRef" :model="visitorForm">
        <div class="visitor-list">
          <div class="visitor-item" v-for="(v,idx) in visitorForm.visitors" :key="idx">
            <div class="visitor-index">{{ idx + 1 }}</div>
            <div class="visitor-fields">
              <el-form-item :prop="'visitors.' + idx + '.realName'" :rules="[
                { required: true, message: '请输入姓名', trigger: 'blur' },
                { min: 1, max: 30, message: '长度1-30', trigger: 'blur' }
              ]">
                <el-input v-model="v.realName" placeholder="姓名" />
              </el-form-item>
              <el-form-item :prop="'visitors.' + idx + '.idCard'" :rules="[
                { required: true, message: '请输入身份证号', trigger: 'blur' },
                { pattern: /^[1-9]\d{16}[\dXx]$/, message: '身份证号须18位，最后一位可为X', trigger: 'blur' }
              ]">
                <el-input v-model="v.idCard" placeholder="身份证号" />
              </el-form-item>
              <el-form-item :prop="'visitors.' + idx + '.phone'" :rules="[
                { required: true, message: '请输入手机号', trigger: 'blur' },
                { pattern: /^1\d{10}$/, message: '手机号须11位数字且以1开头', trigger: 'blur' }
              ]">
                <el-input v-model="v.phone" placeholder="手机号" />
              </el-form-item>
            </div>
            <div class="visitor-remove">
              <el-button type="danger" plain @click="removeVisitor(idx)">删除</el-button>
            </div>
          </div>
        </div>
        <div class="visitor-actions">
          <el-button type="primary" plain @click="addVisitor">添加预约人</el-button>
        </div>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitReserve">提 交</el-button>
          <el-button @click="dialogOpen=false">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, reactive, getCurrentInstance } from 'vue'
import { listNext7Days } from '@/api/reservationTimeSlot'
import { addReservation } from '@/api/reservation'
import { getCurrentSysUser } from '@/api/sysUser'

const loading = ref(false)
const dateRange = ref([])
const selectedDateKey = ref('')
const slotsByDate = ref({})
const timePoints = ref({})
const dialogOpen = ref(false)
const visitorFormRef = ref()
const visitorForm = reactive({ visitors: [{ realName: '', idCard: '', phone: '' }] })
const selectedTp = ref(null)
const currentUserId = ref(null)
const { proxy } = getCurrentInstance()

function genDateRange() {
  const today = new Date()
  const arr = []
  for (let i = 0; i <= 7; i++) {
    const d = new Date(today)
    d.setDate(today.getDate() + i)
    const yyyy = d.getFullYear()
    const MM = String(d.getMonth() + 1).padStart(2, '0')
    const DD = String(d.getDate()).padStart(2, '0')
    const key = `${yyyy}-${MM}-${DD}`
    const weekday = ['日','一','二','三','四','五','六'][d.getDay()]
    arr.push({ key, label: i === 0 ? '今天' : `周${weekday}`, dateStr: `${MM}-${DD}`, isToday: i === 0 })
  }
  dateRange.value = arr
  selectedDateKey.value = arr[1]?.key || arr[0]?.key
}

function groupSlots(list) {
  const map = {}
  list.forEach(s => {
    const d = normalizeDate(s)
    if (!d) return
    if (!map[d]) map[d] = []
    map[d].push(s)
  })
  return map
}

function buildTimePoints() {
  const res = {}
  Object.keys(slotsByDate.value || {}).forEach(d => {
    const arr = []
    ;(slotsByDate.value[d] || []).forEach(s => {
      const pts = genHalfHourPoints(s)
      const full = Number(s.currentPeople || 0) >= Number(s.maxPeople || 0)
      const disabledBase = Number(s.status) !== 1 || full
      pts.forEach(t => arr.push({ key: `${d}-${t}`, label: t, slotId: s.id, date: d, disabled: disabledBase }))
    })
    res[d] = arr
  })
  timePoints.value = res
}

function genHalfHourPoints(s) {
  const start = parseToDateTime(s.date, s.startTime)
  const end = parseToDateTime(s.date, s.endTime)
  if (!start || !end || end <= start) return []
  const out = []
  let cur = new Date(start)
  while (cur <= end) {
    const HH = String(cur.getHours()).padStart(2, '0')
    const mm = String(cur.getMinutes()).padStart(2, '0')
    out.push(`${HH}:${mm}`)
    cur = new Date(cur.getTime() + 30 * 60 * 1000)
  }
  return out
}

function parseToDateTime(dateStr, timeStr) {
  if (!dateStr || !timeStr) return null
  const t = typeof timeStr === 'string' && timeStr.length === 8 ? timeStr : getTimeStr(timeStr)
  if (!t || t === '--:--') return null
  return new Date(`${dateStr} ${t}:00`)
}

function normalizeDate(s) {
  if (typeof s.date === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(s.date)) {
    return s.date
  }
  const val = s.startTime || s.endTime
  if (!val) return ''
  if (typeof val === 'string' && /^\d{4}-\d{2}-\d{2} /.test(val)) {
    return val.slice(0, 10)
  }
  const d = new Date(val)
  if (isNaN(d.getTime())) return ''
  const yyyy = d.getFullYear()
  const MM = String(d.getMonth() + 1).padStart(2, '0')
  const DD = String(d.getDate()).padStart(2, '0')
  return `${yyyy}-${MM}-${DD}`
}

function formatTimeRange(s) {
  const t1 = getTimeStr(s.startTime)
  const t2 = getTimeStr(s.endTime)
  return `${t1} - ${t2}`
}

function getTimeStr(v) {
  if (!v) return '--:--'
  if (typeof v === 'string') {
    // "HH:mm:ss" or "YYYY-MM-DD HH:mm:ss"
    const m = v.match(/(\d{2}:\d{2})/)
    return m ? m[1] : '--:--'
  }
  const d = new Date(v)
  if (isNaN(d.getTime())) return '--:--'
  const HH = String(d.getHours()).padStart(2, '0')
  const mm = String(d.getMinutes()).padStart(2, '0')
  return `${HH}:${mm}`
}

function loadSlots() {
  loading.value = true
  listNext7Days().then(res => {
    const list = Array.isArray(res) ? res : (res.data || res.list || [])
    slotsByDate.value = groupSlots(Array.isArray(list) ? list : [])
    buildTimePoints()
  }).finally(() => (loading.value = false))
}

function openReserve(tp) {
  if (tp?.disabled) return
  selectedTp.value = tp
  dialogOpen.value = true
}

function addVisitor() {
  visitorForm.visitors.push({ realName: '', idCard: '', phone: '' })
}
function removeVisitor(idx) {
  visitorForm.visitors.splice(idx, 1)
  if (visitorForm.visitors.length === 0) visitorForm.visitors.push({ realName: '', idCard: '', phone: '' })
}

async function submitReserve() {
  if (!selectedTp.value) return
  const valid = await new Promise(resolve => {
    if (visitorFormRef.value && visitorFormRef.value.validate) {
      visitorFormRef.value.validate(v => resolve(v))
    } else {
      resolve(true)
    }
  })
  if (!valid) return
  // 构造整单预约入参（包含预约基础信息与游客明细），一次请求完成提交
  const payload = {
    userId: currentUserId.value,
    timeSlotId: selectedTp.value.slotId,
    reserveTime: `${selectedTp.value.label}:00`,
    totalVisitors: visitorForm.visitors.length,
    status: 0,
    // 游客列表：默认 verifyStatus 为 0（未验证）
    reservationVisitors: visitorForm.visitors.map(v => ({ realName: v.realName, idCard: v.idCard, phone: v.phone, verifyStatus: 0 }))
  }
  try {
    const res = await addReservation(payload)
    if (res && Number(res.code) === 200) {
      proxy.$message({ message: '预约提交成功，等待审核', type: 'success' })
      dialogOpen.value = false
    } else {
      const msg = (res && res.msg) || '提交失败'
      proxy.$message({ message: msg, type: 'error' })
    }
  } catch (e) {
    proxy.$message({ message: '服务异常！', type: 'error' })
  }
}

onMounted(() => {
  genDateRange()
  loadSlots()
  getCurrentSysUser().then(u => {
    const data = u && (u.data || u)
    currentUserId.value = data && (data.id || data.userId)
  })
})
</script>

<style scoped>
.reserve-container {
  width: 80%;
  margin: 24px auto 40px;
  padding-top: 16px;
}
.intro {
  color: #606266;
  margin-bottom: 12px;
}
.date-bar {
  display: flex;
  gap: 10px;
  margin-bottom: 16px;
}
.date-chip {
  border: 1px solid #e7dfcf;
  background: #f9f6f1;
  border-radius: 12px;
  padding: 8px 12px;
  cursor: pointer;
}
.date-chip.active {
  border-color: #8a2b2b;
  box-shadow: 0 6px 14px rgba(138,43,43,0.12);
}
.date-chip.disabled {
  cursor: not-allowed;
  opacity: 0.6;
}
.d1 { font-weight: 700; color: #2c1f1f; }
.d2 { font-size: 12px; color: #8a2b2b; }
.slot-panel { background: #fff; border: 1px solid #e7dfcf; border-radius: 12px; padding: 16px; }
.slot-empty { color: #909399; text-align: center; padding: 20px 0; }
.slot-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.slot-card { background: #f9f6f1; border: 1px solid #e7dfcf; border-radius: 12px; padding: 12px; display: flex; align-items: center; justify-content: space-between; }
.slot-time { font-weight: 700; color: #2c1f1f; }
.slot-card.disabled { opacity: 0.6; }
.visitor-list { display: flex; flex-direction: column; gap: 8px; }
.visitor-item { display: grid; grid-template-columns: 40px 1fr auto; gap: 12px; align-items: center; background: #f9f6f1; border: 1px solid #e7dfcf; border-radius: 12px; padding: 12px; }
.visitor-index { width: 32px; height: 32px; border-radius: 999px; background: #8a2b2b; color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 800; }
.visitor-fields { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.visitor-fields :deep(.el-input) { width: 100%; }
.visitor-remove { display: flex; align-items: center; }
.visitor-actions { margin-top: 10px; display: flex; justify-content: center; }
</style>
