<template>
  <div class="pickup-time-cascader">
    <el-cascader
        ref="cascaderRef"
        v-model="selectedValue"
        :options="cascaderOptions"
        :props="cascaderProps"
        :show-all-levels="true"
        :placeholder="placeholder"
        :clearable="clearable"
        :filterable="filterable"
        :disabled="disabled"
        :size="size"
        @change="handleChange"
        @visible-change="handleVisibleChange"
        @expand-change="handleExpandChange"
    >
      <template #default="{ node, data }">
        <div class="cascader-item" :class="{'is-date': !data.timeLabel, 'is-time': data.timeLabel}">
          <span class="item-label">{{ data.label }}</span>
        </div>
      </template>

      <template #empty>
        <div class="empty-content">
          <span class="empty-text">无可用时间段</span>
        </div>
      </template>
    </el-cascader>
  </div>
</template>

<script setup>
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'

const props = defineProps({
  modelValue: {
    type: Array,
    default: () => []
  },
  placeholder: {
    type: String,
    default: '一小时内'
  },
  clearable: {
    type: Boolean,
    default: true
  },
  filterable: {
    type: Boolean,
    default: false
  },
  disabled: {
    type: Boolean,
    default: false
  },
  size: {
    type: String,
    default: 'large',
    validator: (value) => ['large', 'default', 'small'].includes(value)
  },
  // 显示天数
  days: {
    type: Number,
    default: 3
  },
  // 时间间隔（分钟）
  timeInterval: {
    type: Number,
    default: 60
  },
  // 开始时间
  startTime: {
    type: Number,
    default: 9
  },
  // 结束时间
  endTime: {
    type: Number,
    default: 20
  },
  // 当前时间（用于测试）
  currentTime: {
    type: Date,
    default: () => new Date()
  },
  // 是否自动选择推荐时间
  autoSelect: {
    type: Boolean,
    default: true
  }
})

const emit = defineEmits(['update:modelValue', 'change', 'select', 'clear'])

const selectedValue = ref([])
const cascaderRef = ref(null)
const currentTime = ref(new Date())
const timer = ref(null)

// 级联选择器配置
const cascaderProps = {
  expandTrigger: 'click',
  multiple: false,
  emitPath: true,
  value: 'value',
  label: 'label',
  children: 'children',
  disabled: 'disabled',
  checkStrictly: false,
  lazy: false
}

// 基础时间段配置（整点时段）
const baseTimeSlots = computed(() => {
  const slots = []
  const startHour = props.startTime
  const endHour = props.endTime
  const interval = props.timeInterval / 60 // 转换为小时

  for (let hour = startHour; hour < endHour; hour += interval) {
    const start = hour
    const end = hour + interval
    const startStr = start.toString().padStart(2, '0')
    const endStr = end.toString().padStart(2, '0')

    slots.push({
      start: start,
      end: end,
      label: `${startStr}:00-${endStr}:00`,
      value: `${startStr}:00-${endStr}:00`,
      startHour: start,
      endHour: end
    })
  }

  return slots
})

// 获取今天日期字符串
const todayDate = computed(() => {
  const today = new Date()
  return formatDate(today)
})

// 生成日期列表
const dateList = computed(() => {
  const days = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
  const list = []
  const today = new Date()

  for (let i = 0; i < props.days; i++) {
    const date = new Date(today)
    date.setDate(date.getDate() + i)

    const year = date.getFullYear()
    const month = date.getMonth() + 1
    const day = date.getDate()
    const week = days[date.getDay()]
    const dateStr = formatDate(date)

    let label = ''
    if (i === 0) {
      label = `今天 ${month}月${day}日 ${week}`
    } else if (i === 1) {
      label = `明天 ${month}月${day}日 ${week}`
    } else if (i === 2) {
      label = `后天 ${month}月${day}日 ${week}`
    } else {
      label = `${month}月${day}日 ${week}`
    }

    list.push({
      value: dateStr,
      label: label,
      year: year,
      month: month,
      day: day,
      week: week,
      isToday: i === 0,
      isTomorrow: i === 1,
      isDayAfterTomorrow: i === 2,
      fullLabel: `${month}月${day}日 ${week}`,
      displayDate: `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`
    })
  }

  return list
})

// 计算当前时间30分钟后的时间
const thirtyMinutesLater = computed(() => {
  const now = new Date()
  now.setMinutes(now.getMinutes() + 3)
  return now
})

// 计算一小时后的小时（向上取整）
const oneHourLaterHour = computed(() => {
  const now = new Date()
  now.setHours(now.getHours() + 1)
  return Math.ceil(now.getHours())
})

// 计算一小时内时间段（动态生成）
const withinOneHourSlot = computed(() => {
  if (!dateList.value.length || !dateList.value[0].isToday) return null

  const now = currentTime.value
  const later30min = thirtyMinutesLater.value

  // 计算开始时间：当前时间 + 30分钟，分钟向上取整到10的倍数
  const startMinutes = later30min.getMinutes()
  const roundedMinutes = Math.ceil(startMinutes / 10) * 10
  let startHour = later30min.getHours()
  let startMinute = roundedMinutes

  // 如果分钟超过60，小时加1，分钟归零
  if (startMinute >= 60) {
    startHour += 1
    startMinute = 0
  }

  // 计算结束时间：开始时间 + 1小时
  let endHour = startHour + 1
  let endMinute = startMinute

  // 如果开始时间已经超过结束时间限制，则不显示
  if (startHour >= props.endTime) return null

  // 如果结束时间超过结束时间限制，则调整
  if (endHour > props.endTime) {
    endHour = props.endTime
    endMinute = 0
  }

  // 如果开始时间小于开始时间限制，则调整
  if (startHour < props.startTime) {
    startHour = props.startTime
    startMinute = 0
  }

  // 检查时间段是否有效（至少30分钟）
  const slotDuration = (endHour - startHour) * 60 + (endMinute - startMinute)
  if (slotDuration < 3) return null

  const startStr = formatTime(startHour, startMinute)
  const endStr = formatTime(endHour, endMinute)

  return {
    start: startHour + startMinute / 60,
    end: endHour + endMinute / 60,
    label: `一小时内`, // 显示为“一小时内”
    value: `${startStr}-${endStr}`,
    isWithinOneHour: true,
    startHour: startHour,
    startMinute: startMinute,
    endHour: endHour,
    endMinute: endMinute
  }
})

// 推荐时间段（一小时内）
const recommendTime = computed(() => {
  if (!dateList.value.length || !dateList.value[0].isToday) return null
  if (withinOneHourSlot.value) {
    return withinOneHourSlot.value.value
  }
  return null
})

// 生成级联选择器选项
const cascaderOptions = computed(() => {
  const options = []

  dateList.value.forEach(date => {
    const dateOption = {
      value: date.value,
      label: date.label,
      date: date.value,
      dateLabel: date.label,
      isToday: date.isToday,
      children: [],
      disabled: false
    }

    const isToday = date.isToday
    const oneHourLater = oneHourLaterHour.value

    // 今天的时间段需要根据当前时间+1小时过滤
    if (isToday) {
      // 首先添加"一小时内"选项（如果有）
      if (withinOneHourSlot.value) {
        dateOption.children.push({
          value: withinOneHourSlot.value.value,
          label: withinOneHourSlot.value.label,
          timeLabel: withinOneHourSlot.value.value,
          recommend: true,
          tag: '推荐',
          tagClass: 'tag-recommend',
          disabled: false,
          soon: false,
          night: isNightTime(withinOneHourSlot.value.startHour),
          isWithinOneHour: true,
          startHour: withinOneHourSlot.value.startHour,
          startMinute: withinOneHourSlot.value.startMinute,
          endHour: withinOneHourSlot.value.endHour,
          endMinute: withinOneHourSlot.value.endMinute
        })
      }

      // 添加其他时间段（开始时间从一小时后开始）
      baseTimeSlots.value.forEach(slot => {
        // 时间段开始时间必须在当前时间+1小时之后
        const isDisabled = slot.start < oneHourLater
        if (!isDisabled) {
          dateOption.children.push({
            value: slot.value,
            label: slot.label,
            timeLabel: slot.label,
            recommend: false,
            tag: '',
            tagClass: '',
            disabled: false,
            soon: false,
            night: isNightTime(slot.start),
            startHour: slot.start,
            endHour: slot.end
          })
        }
      })
    } else {
      // 明天及以后显示所有时间段
      baseTimeSlots.value.forEach(slot => {
        dateOption.children.push({
          value: slot.value,
          label: slot.label,
          timeLabel: slot.label,
          recommend: false,
          tag: '',
          tagClass: '',
          disabled: false,
          soon: false,
          night: isNightTime(slot.start),
          startHour: slot.start,
          endHour: slot.end
        })
      })
    }

    // 如果没有可用的时间段，则禁用该日期
    if (dateOption.children.length === 0) {
      dateOption.disabled = true
      dateOption.label = `${dateOption.label} (无可选时间)`
    }

    options.push(dateOption)
  })

  return options
})

// 是否是夜间时间段
const isNightTime = (hour) => {
  return hour >= 18
}

// 获取开始小时（小数）
const getStartHour = (timeLabel, selectedTimeOption) => {
  if (selectedTimeOption && selectedTimeOption.isWithinOneHour) {
    return selectedTimeOption.startHour + selectedTimeOption.startMinute / 60
  }
  const match = timeLabel.match(/(\d{2}):/)
  return match ? parseInt(match[1]) : 0
}

// 获取结束小时（小数）
const getEndHour = (timeLabel, selectedTimeOption) => {
  if (selectedTimeOption && selectedTimeOption.isWithinOneHour) {
    return selectedTimeOption.endHour + selectedTimeOption.endMinute / 60
  }
  const match = timeLabel.match(/-(\d{2}):/)
  return match ? parseInt(match[1]) : 0
}

// 处理选择变化
const handleChange = (value) => {
  if (!value || value.length === 0) {
    emit('update:modelValue', [])
    emit('change', null)
    emit('clear')
    return
  }

  const [date, time] = value
  const selectedDate = dateList.value.find(d => d.value === date)
  const selectedTime = findTimeOption(date, time)

  if (!selectedDate || !selectedTime) {
    return
  }

  const startHour = getStartHour(time, selectedTime)
  const endHour = getEndHour(time, selectedTime)

  const startTimeStr = formatDateTime(date, startHour)
  const endTimeStr = formatDateTime(date, endHour)

  let displayText = ''
  if (selectedTime.isWithinOneHour) {
    displayText = `${selectedDate.label} 一小时内`
  } else {
    displayText = `${selectedDate.label} ${time}`
  }

  const timeData = {
    date: date,
    time: time,
    dateLabel: selectedDate.label,
    timeLabel: time,
    fullLabel: displayText,
    displayText: displayText,
    startTime: startTimeStr,
    endTime: endTimeStr,
    isToday: selectedDate.isToday,
    isImmediate: selectedTime.isWithinOneHour || false,
    isNight: selectedTime.night || false,
    isSoon: selectedTime.soon || false,
    startHour: startHour,
    endHour: endHour
  }

  emit('update:modelValue', value)
  emit('change', timeData)
  emit('select', timeData)
}

// 格式化日期时间
const formatDateTime = (dateStr, hour) => {
  const date = new Date(dateStr)
  const wholeHour = Math.floor(hour)
  const minutes = Math.round((hour - wholeHour) * 60)
  date.setHours(wholeHour, minutes, 0, 0)

  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  const hours = String(date.getHours()).padStart(2, '0')
  const mins = String(date.getMinutes()).padStart(2, '0')
  const seconds = String(date.getSeconds()).padStart(2, '0')

  return `${year}-${month}-${day} ${hours}:${mins}:${seconds}`
}

// 查找时间选项
const findTimeOption = (date, time) => {
  const dateOption = cascaderOptions.value.find(opt => opt.value === date)
  if (!dateOption || !dateOption.children) return null
  return dateOption.children.find(child => child.value === time)
}

// 处理弹窗显示/隐藏
const handleVisibleChange = (visible) => {
  if (visible) {
    currentTime.value = new Date()
    if (selectedValue.value.length === 0 && props.autoSelect) {
      nextTick(() => {
        const defaultOption = getDefaultOption()
        if (defaultOption) {
          selectedValue.value = defaultOption
          handleChange(defaultOption)
        }
      })
    }
  }
}

const handleExpandChange = () => {}

// 获取默认选项
const getDefaultOption = () => {
  if (!cascaderOptions.value.length) return null

  const todayOption = cascaderOptions.value[0]
  if (todayOption && todayOption.children && todayOption.children.length > 0) {
    const recommendOption = todayOption.children.find(child => child.recommend && !child.disabled)
    if (recommendOption) {
      return [todayOption.value, recommendOption.value]
    }
    const firstAvailable = todayOption.children.find(child => !child.disabled)
    if (firstAvailable) {
      return [todayOption.value, firstAvailable.value]
    }
  }

  for (let i = 1; i < cascaderOptions.value.length; i++) {
    const option = cascaderOptions.value[i]
    if (option.children && option.children.length > 0) {
      const firstAvailable = option.children.find(child => !child.disabled)
      if (firstAvailable) {
        return [option.value, firstAvailable.value]
      }
    }
  }

  return null
}

// 工具函数
const formatDate = (date) => {
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  return `${year}-${month}-${day}`
}

const formatTime = (hour, minute) => {
  const hourStr = hour.toString().padStart(2, '0')
  const minuteStr = minute.toString().padStart(2, '0')
  return `${hourStr}:${minuteStr}`
}

// 监听外部值变化
watch(() => props.modelValue, (newVal) => {
  if (JSON.stringify(newVal) !== JSON.stringify(selectedValue.value)) {
    selectedValue.value = newVal || []
  }
}, { immediate: true })

// 每分钟更新一次当前时间（仅当下拉框打开时）
onMounted(() => {
  timer.value = setInterval(() => {
    if (cascaderRef.value && cascaderRef.value.dropDownVisible) {
      currentTime.value = new Date()
    }
  }, 60000)
})

onUnmounted(() => {
  if (timer.value) {
    clearInterval(timer.value)
  }
})

defineExpose({
  getSelectedTimeData: () => {
    if (selectedValue.value.length !== 2) return null
    const [date, time] = selectedValue.value
    const selectedDate = dateList.value.find(d => d.value === date)
    const selectedTime = findTimeOption(date, time)
    if (!selectedDate || !selectedTime) return null

    const startHour = getStartHour(time, selectedTime)
    const endHour = getEndHour(time, selectedTime)
    const startTimeStr = formatDateTime(date, startHour)
    const endTimeStr = formatDateTime(date, endHour)

    let displayText = ''
    if (selectedTime.isWithinOneHour) {
      displayText = `${selectedDate.label} 一小时内`
    } else {
      displayText = `${selectedDate.label} ${time}`
    }

    return {
      date: date,
      time: time,
      dateLabel: selectedDate.label,
      timeLabel: time,
      fullLabel: displayText,
      startTime: startTimeStr,
      endTime: endTimeStr,
      isToday: selectedDate.isToday,
      isImmediate: selectedTime.isWithinOneHour || false,
      isNight: selectedTime.night || false,
      isSoon: selectedTime.soon || false,
      startHour: startHour,
      endHour: endHour
    }
  },
  clearSelection: () => {
    selectedValue.value = []
    emit('update:modelValue', [])
    emit('change', null)
    emit('clear')
  },
  refreshTime: () => {
    currentTime.value = new Date()
  },
  setSelectedTime: (date, time) => {
    const dateExists = dateList.value.some(d => d.value === date)
    if (dateExists) {
      selectedValue.value = [date, time]
      handleChange([date, time])
      return true
    }
    return false
  }
})
</script>


<style scoped lang="scss">
.pickup-time-cascader {
  width: 100%;

  :deep(.el-cascader) {
    width: 100%;

    .el-input {
      width: 100%;

      .el-input__wrapper {
        width: 100%;
        box-sizing: border-box;

        &.is-focus {
          box-shadow: 0 0 0 1px var(--el-color-primary) inset;
        }

        .el-input__inner {
          color: #333;
          font-weight: 500;
        }
      }
    }
  }

  :deep(.el-cascader__dropdown) {
    max-height: 400px;
    overflow-y: auto;
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);

    .el-cascader-panel {
      border: none;

      .el-cascader-menu {
        min-width: 200px;
        max-height: 400px;
        overflow-y: auto;

        &:first-child {
          min-width: 220px;
        }

        .el-cascader-node {
          height: auto;
          min-height: 40px;
          padding: 8px 12px;

          &:hover:not(.is-disabled) {
            background-color: #f5f7fa;
          }

          &.is-selectable {
            &.in-active-path,
            &.is-active {
              background-color: #f0f7ff;

              .cascader-item {
                .item-label {
                  color: var(--el-color-primary);
                  font-weight: 600;
                }
              }
            }
          }

          &.is-disabled {
            .cascader-item {
              .item-label {
                color: #c0c4cc;
              }
            }
          }

          .cascader-item {
            display: flex;
            align-items: center;
            justify-content: space-between;
            width: 100%;
            min-height: 32px;
            box-sizing: border-box;
            font-size: 14px;

            &.is-date {
              .item-label {
                font-weight: 500;
                color: #333;
              }

              &.is-today {
                .item-label {
                  color: #f2270c;
                }
              }
            }

            &.is-time {
              .item-label {
                color: #666;
              }
            }

            .item-label {
              flex: 1;
              text-align: left;
              overflow: hidden;
              text-overflow: ellipsis;
              white-space: nowrap;
            }

            .item-tag {
              font-size: 12px;
              padding: 2px 8px;
              border-radius: 10px;
              margin-left: 8px;
              font-weight: 500;

              &.tag-recommend {
                background-color: #fef2f0;
                color: #f2270c;
                border: 1px solid #f2270c;
              }

              &.tag-soon {
                background-color: #fff7e6;
                color: #ff9900;
                border: 1px solid #ff9900;
              }

              &.tag-night {
                background-color: #f0f5ff;
                color: #4a5cff;
                border: 1px solid #4a5cff;
              }
            }

            .item-recommend {
              font-size: 12px;
              color: #f2270c;
              font-weight: 500;
              margin-left: 8px;
              padding: 2px 6px;
              background-color: #fef2f0;
              border-radius: 4px;
            }

            .item-night {
              font-size: 12px;
              color: #4a5cff;
              font-weight: 500;
              margin-left: 8px;
              padding: 2px 6px;
              background-color: #f0f5ff;
              border-radius: 4px;
            }
          }
        }
      }
    }
  }

  .empty-content {
    padding: 20px;
    text-align: center;

    .empty-text {
      font-size: 14px;
      color: #999;
    }
  }
}

// 夜间时间段特殊样式
.night-time-option {
  :deep(.el-cascader-node) {
    .cascader-item {
      .item-label {
        color: #4a5cff !important;
      }
    }

    &.is-active {
      .cascader-item {
        .item-label {
          color: #4a5cff !important;
        }
      }
    }
  }
}

// 推荐时间段特殊样式
.recommend-time-option {
  :deep(.el-cascader-node) {
    .cascader-item {
      .item-label {
        color: #f2270c !important;
      }
    }

    &.is-active {
      .cascader-item {
        .item-label {
          color: #f2270c !important;
        }
      }
    }
  }
}
</style>