<script lang="ts" setup>
import { computed, defineEmits, defineProps, onMounted, onUnmounted, ref, watch } from 'vue'

const props = defineProps({
  modelValue: {
    type: [String, Date, null],
    default: null,
  },
  minDate: {
    type: [String, Date],
    default: null,
  },
  maxDate: {
    type: [String, Date],
    default: null,
  },
  format: {
    type: String,
    default: 'YYYY-MM-DD HH:mm:ss',
  },
})

const emits = defineEmits(['update:modelValue', 'change'])
const dateText = ref()
const hoursOptions = ref(Array.from({ length: 24 }, (_, i) => i))
const minuteOptions = ref(Array.from({ length: 60 }, (_, i) => i))
const secondOptions = ref(Array.from({ length: 60 }, (_, i) => i))
// 初始化日期时间
const selectedDate = ref<Date | null>(null)
const currentYear = ref(0)
const currentMonth = ref(0)
const today = new Date()
const weekdays = ['日', '一', '二', '三', '四', '五', '六']
const isDropdownVisible = ref(false)
const selectedHour = ref('00')
const selectedMinute = ref('00')
const selectedSecond = ref('00')

// 格式化显示值
const displayValue = () => {
  if (!selectedDate.value) {
    return ''
  }
  const year = selectedDate.value.getFullYear()
  const month = (selectedDate.value.getMonth() + 1).toString().padStart(2, '0')
  const date = selectedDate.value.getDate().toString().padStart(2, '0')
  const hour = selectedDate.value.getHours().toString().padStart(2, '0')
  const minute = selectedDate.value.getMinutes().toString().padStart(2, '0')
  const second = selectedDate.value.getSeconds().toString().padStart(2, '0')
  dateText.value = `${year}-${month}-${date} ${hour}:${minute}:${second}`
}

watch(selectedDate, (newVal) => {
  if (newVal) {
    const year = newVal.getFullYear()
    const month = (newVal.getMonth() + 1).toString().padStart(2, '0')
    const date = newVal.getDate().toString().padStart(2, '0')
    const hour = newVal.getHours().toString().padStart(2, '0')
    const minute = newVal.getMinutes().toString().padStart(2, '0')
    const second = newVal.getSeconds().toString().padStart(2, '0')
    dateText.value = `${year}-${month}-${date} ${hour}:${minute}:${second}`
  }
})

// 计算当前月份的天数及上个月和下个月的部分天数
const daysInMonth: any = computed(() => {
  const days: Record<string, any>[] = []

  // 获取当前月份第一天是星期几
  const firstDay = new Date(currentYear.value, currentMonth.value, 1).getDay()

  // 获取上个月的最后几天
  const prevMonthLastDay = new Date(currentYear.value, currentMonth.value, 0).getDate()
  for (let i = firstDay; i > 0; i--) {
    const date = new Date(currentYear.value, currentMonth.value - 1, prevMonthLastDay - i + 1)
    days.push({ date, month: currentMonth.value - 1 })
  }

  // 获取当前月份的所有天数
  const currentMonthDays = new Date(currentYear.value, currentMonth.value + 1, 0).getDate()
  for (let i = 1; i <= currentMonthDays; i++) {
    const date = new Date(currentYear.value, currentMonth.value, i)
    days.push({ date, month: currentMonth.value })
  }

  // 获取下个月的前几天
  const remainingDays = 42 - days.length // 6行7列共42个格子
  for (let i = 1; i <= remainingDays; i++) {
    const date = new Date(currentYear.value, currentMonth.value + 1, i)
    days.push({ date, month: currentMonth.value + 1 })
  }

  return days
})

// 初始化
onMounted(() => {
  const initialDate = props.modelValue ? new Date(Number(props.modelValue)) : new Date()
  selectedDate.value = initialDate
  currentYear.value = initialDate.getFullYear()
  currentMonth.value = initialDate.getMonth()
  selectedHour.value = initialDate.getHours().toString().padStart(2, '0')
  selectedMinute.value = initialDate.getMinutes().toString().padStart(2, '0')
  selectedSecond.value = initialDate.getSeconds().toString().padStart(2, '0')
})

// 监听props变化
watch(() => props.modelValue, (newVal) => {
  if (newVal) {
    const date = new Date(Number(newVal))
    if (!Number.isNaN(date.getTime())) {
      selectedDate.value = date
      currentYear.value = date.getFullYear()
      currentMonth.value = date.getMonth()
      selectedHour.value = date.getHours().toString().padStart(2, '0')
      selectedMinute.value = date.getMinutes().toString().padStart(2, '0')
      selectedSecond.value = date.getSeconds().toString().padStart(2, '0')
    }
  }
  else {
    selectedDate.value = null
  }
}, { deep: true })

// 日期操作
const prevMonth = () => {
  if (currentMonth.value === 0) {
    currentMonth.value = 11
    currentYear.value--
  }
  else {
    currentMonth.value--
  }
}

const nextMonth = () => {
  if (currentMonth.value === 11) {
    currentMonth.value = 0
    currentYear.value++
  }
  else {
    currentMonth.value++
  }
}

const prevYear = () => {
  currentYear.value--
}

const nextYear = () => {
  currentYear.value++
}

// 日期选择
const selectDate = (date: Date) => {
  if (!isDateInRange(date)) {
    return
  }

  if (!selectedDate.value) {
    selectedDate.value = new Date(date)
  }
  else {
    // 保留原来的时分秒
    selectedDate.value.setFullYear(date.getFullYear())
    selectedDate.value.setMonth(date.getMonth())
    selectedDate.value.setDate(date.getDate())
  }
  displayValue()
}

// 时间更新
const updateTime = () => {
  console.log('selectedDate.value--', selectedDate.value, selectedHour.value)
  if (selectedDate.value) {
    selectedDate.value.setHours(Number(selectedHour.value))
    selectedDate.value.setMinutes(Number(selectedMinute.value))
    selectedDate.value.setSeconds(Number(selectedSecond.value))
  }
  displayValue()
}

// 确认选择
const confirmSelection = () => {
  if (selectedDate.value) {
    const dateValue = formatDate(selectedDate.value, props.format)
    // emits('update:modelValue', dateValue)
    emits('change', dateValue)
  }
  isDropdownVisible.value = false
}

// 日期格式化工具函数
const formatDate = (date: Date, format: string): string => {
  if (!date) {
    return ''
  }

  const year = date.getFullYear()
  const month = date.getMonth() + 1
  const day = date.getDate()
  const hour = date.getHours()
  const minute = date.getMinutes()
  const second = date.getSeconds()
  return format
    .replace('YYYY', year.toString())
    .replace('MM', month.toString().padStart(2, '0'))
    .replace('DD', day.toString().padStart(2, '0'))
    .replace('HH', hour.toString().padStart(2, '0'))
    .replace('mm', minute.toString().padStart(2, '0'))
    .replace('ss', second.toString().padStart(2, '0'))
}

// 取消选择
const cancelSelection = () => {
  // 恢复之前的值
  // if (props.modelValue) {
  //   const date = new Date(props.modelValue)
  //   if (!isNaN(date.getTime())) {
  //     selectedDate.value = date
  //     selectedHour.value = date.getHours().toString().padStart(2, '0')
  //     selectedMinute.value = date.getMinutes().toString().padStart(2, '0')
  //     selectedSecond.value = date.getSeconds().toString().padStart(2, '0')
  //   }
  // } else {
  //   selectedDate.value = null
  // }
  isDropdownVisible.value = false
}

// 切换下拉框显示
const toggleDropdown = (event?: MouseEvent) => {
  if (event) {
    event.stopPropagation()
  }
  isDropdownVisible.value = !isDropdownVisible.value
}

// 工具函数
const isSameDay = (date1: Date, date2: Date | null) => {
  if (!date2) {
    return false
  }
  return (
    date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && date1.getDate() === date2.getDate()
  )
}

const isDateInRange = (date: Date) => {
  const min = props.minDate ? new Date(props.minDate) : null
  const max = props.maxDate ? new Date(props.maxDate) : null

  if (min && date < min) {
    return false
  }
  if (max && date > max) {
    return false
  }
  return true
}

// 点击外部关闭下拉框
const closeDropdownOnClickOutside = (event: MouseEvent) => {
  if (!isDropdownVisible.value) {
    return
  }

  const target = event.target as HTMLElement
  const container = document.querySelector('.date-time-picker')

  if (container && !container.contains(target)) {
    isDropdownVisible.value = false
  }
}

// 添加和移除事件监听
onMounted(() => {
  document.addEventListener('click', closeDropdownOnClickOutside)
})

onUnmounted(() => {
  document.removeEventListener('click', closeDropdownOnClickOutside)
})
</script>

<template>
  <div class="date-time-picker">
    <div class="input-group">
      <input
        v-model="dateText"
        type="text"
        readonly
        placeholder="请选择日期时间"
        class="form-input"
        @click="toggleDropdown"
      >
      <span class="input-icon" @click="toggleDropdown">
        <i class="fa fa-calendar" />
      </span>
    </div>
    <transition name="fade">
      <div v-show="isDropdownVisible" class="dropdown-container">
        <div class="calendar-header">
          <button class="nav-btn" @click="prevYear">
            <el-icon><DArrowLeft /></el-icon>
          </button>
          <button class="nav-btn" @click="prevMonth">
            <el-icon><ArrowLeft /></el-icon>
          </button>
          <span class="current-date">
            {{ currentYear }}年 {{ currentMonth + 1 }}月
          </span>
          <button class="nav-btn" @click="nextMonth">
            <el-icon><ArrowRight /></el-icon>
          </button>
          <button class="nav-btn" @click="nextYear">
            <el-icon><DArrowRight /></el-icon>
          </button>
        </div>
        <div class="weekdays">
          <div v-for="day in weekdays" :key="day" class="weekday">
            {{ day }}
          </div>
        </div>
        <div class="days">
          <div
            v-for="(day, index) in daysInMonth"
            :key="index"
            class="day"
            :class="{
              'other-month': day.month !== currentMonth,
              'selected': isSameDay(day.date, selectedDate),
              'today': isSameDay(day.date, today),
              'disabled': !isDateInRange(day.date),
            }"
            @click="selectDate(day.date)"
          >
            {{ day.date.getDate() }}
          </div>
        </div>
        <div class="time-selector">
          <div class="time-label">
            时间:
          </div>
          <el-select v-model="selectedHour" class="time-select" @change="updateTime">
            <el-option v-for="i in hoursOptions" :key="i" :value="i.toString().padStart(2, '0')" style="font-size: 20px;line-height: 2px;height: 5rem;display: flex; align-items: center;">
              {{ i.toString().padStart(2, '0') }}
            </el-option>
          </el-select>
          <span class="time-separator">:</span>
          <el-select v-model="selectedMinute" class="time-select" @change="updateTime">
            <el-option v-for="i in minuteOptions" :key="i" :value="i.toString().padStart(2, '0')" style="font-size: 20px;line-height: 2px;height: 5rem;display: flex; align-items: center;">
              {{ i.toString().padStart(2, '0') }}
            </el-option>
          </el-select>
          <span class="time-separator">:</span>
          <el-select v-model="selectedSecond" class="time-select" @change="updateTime">
            <el-option v-for="i in secondOptions" :key="i" :value="i.toString().padStart(2, '0')" style="font-size: 20px;line-height: 2px;height: 5rem;display: flex; align-items: center;">
              {{ i.toString().padStart(2, '0') }}
            </el-option>
          </el-select>
        </div>
        <div class="calendar-footer">
          <button class="confirm-btn" @click="confirmSelection">
            确定
          </button>
          <button class="cancel-btn" @click="cancelSelection">
            取消
          </button>
        </div>
      </div>
    </transition>
  </div>
</template>

<style lang="scss" scoped>
$fontSize: 1.5rem;
:deep(body) {
  --el-font-size-base: 20px;
}
.date-time-picker {
  position: relative;
  width: 340px;
}

.input-group {
  display: flex;
  position: relative;
}

.form-input {
  flex: 1;
  padding: 10px 14px;
  border: 1px solid #e2e8f0;
  border-radius: 4px;
  font-size: $fontSize;
  outline: none;
  transition: border-color 0.2s;
}

.form-input:focus {
  border-color: #4f46e5;
}

.input-icon {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: #94a3b8;
  cursor: pointer;
  font-size: $fontSize;
}

.dropdown-container {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  width: 28rem;
  background-color: white;
  border: 1px solid #e2e8f0;
  border-radius: 4px;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
  z-index: 100;
  padding: 12px;
}

.calendar-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.nav-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: #64748b;
  font-size: $fontSize;
  padding: 6px;
  border-radius: 4px;
  transition: background-color 0.2s;
}

.nav-btn:hover {
  background-color: #f1f5f9;
}

.current-date {
  font-weight: 500;
  color: #334155;
  font-size: $fontSize;
}

.weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  margin-bottom: 6px;
}

.weekday {
  text-align: center;
  font-size: $fontSize;
  color: #64748b;
  padding: 6px;
}

.days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 3px;
  margin-bottom: 12px;
}

.day {
  text-align: center;
  padding: 8px;
  border-radius: 4px;
  font-size: $fontSize;
  cursor: pointer;
  transition: background-color 0.2s;
}

.day:hover:not(.disabled) {
  background-color: #e0f2fe;
}

.day.other-month {
  color: #94a3b8;
}

.day.selected {
  background-color: #3b82f6;
  color: white;
}

.day.today:not(.selected) {
  font-weight: 500;
  color: #3b82f6;
}

.day.disabled {
  color: #cbd5e1;
  cursor: not-allowed;
}

.time-selector {
  display: flex;
  align-items: center;
  margin-bottom: 12px;
  .time-select {
    padding: 4px 8px;
    border-radius: 4px;
    font-size: 20px;
    outline: none;
    background-color: white;
    margin-right: 4px;
    /* 最大高度限制，溢出滚动 */
    max-height: 3rem;
    width: 8rem;
    border: none;
  }
}

select option {
  max-height: 3rem;
  border: 1px solid red;
}

.time-label {
  margin-right: 12px;
  font-size: $fontSize;
  color: #334155;
  width: 5rem;
}

.select-option{
  max-height: 3rem;
}

select {
  padding: 6px 10px;
  border: 1px solid #e2e8f0;
  border-radius: 4px;
  font-size: $fontSize;
  outline: none;
  background-color: white;
  margin-right: 6px;
  width: 60px;
}

.time-separator {
  margin: 0 3px;
  font-size: $fontSize;
  color: #334155;
}

.calendar-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.confirm-btn, .cancel-btn {
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  font-size: $fontSize;
  cursor: pointer;
  transition: background-color 0.2s;
}

.confirm-btn {
  background-color: #3b82f6;
  color: white;
}

.confirm-btn:hover {
  background-color: #2563eb;
}

.cancel-btn {
  background-color: #f1f5f9;
  color: #334155;
}

.cancel-btn:hover {
  background-color: #e2e8f0;
}

.fade-enter-active, .fade-leave-active {
  transition: opacity 0.2s;
}

.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
// 修改选择框本身的宽高
:deep(.el-select__wrapper){
  height: 3rem;
  font-size: 20px;
}
</style>
