<template>
  <view class="calendar-container">
    <!-- 日历头部 -->
    <view class="calendar-header">
      <view class="header-controls">
        <button class="control-btn" @click="handlePrevMonth">
          <text class="control-icon">‹</text>
        </button>
        
        <view class="current-date" @click="handleDatePickerShow">
          <text class="year-month">{{ currentYear }}年{{ currentMonth }}月</text>
          <text class="date-picker-icon">▼</text>
        </view>
        
        <button class="control-btn" @click="handleNextMonth">
          <text class="control-icon">›</text>
        </button>
      </view>
      
      <!-- 今天按钮 -->
      <button class="today-btn" @click="handleToday" v-if="showTodayButton">
        今天
      </button>
    </view>
    
    <!-- 星期标题 -->
    <view class="calendar-weekdays">
      <view
        class="weekday-item"
        v-for="weekday in weekdays"
        :key="weekday"
      >
        {{ weekday }}
      </view>
    </view>
    
    <!-- 日历主体 -->
    <view class="calendar-body">
      <view
        class="calendar-week"
        v-for="(week, weekIndex) in calendarWeeks"
        :key="weekIndex"
      >
        <view
          class="calendar-day"
          :class="getDayClass(day)"
          v-for="(day, dayIndex) in week"
          :key="dayIndex"
          @click="handleDayClick(day)"
          @longpress="handleDayLongPress(day)"
        >
          <view class="day-content">
            <text class="day-number">{{ day.day }}</text>
            
            <!-- 农历 -->
            <text class="lunar-text" v-if="showLunar && day.lunar">
              {{ day.lunar }}
            </text>
            
            <!-- 标记点 -->
            <view class="day-marks" v-if="day.marks && day.marks.length">
              <view
                class="mark-dot"
                :style="{ backgroundColor: mark.color }"
                v-for="mark in day.marks.slice(0, 3)"
                :key="mark.id"
              />
            </view>
            
            <!-- 事件数量 -->
            <view class="event-count" v-if="day.eventCount > 0">
              {{ day.eventCount > 99 ? '99+' : day.eventCount }}
            </view>
          </view>
        </view>
      </view>
    </view>
    
    <!-- 选中日期信息 -->
    <view class="selected-info" v-if="selectedDate && showSelectedInfo">
      <view class="selected-date">
        <text class="selected-text">已选择：{{ formatSelectedDate }}</text>
        <button class="clear-btn" @click="handleClearSelection" v-if="allowClear">
          清除
        </button>
      </view>
      
      <!-- 选中日期的事件 -->
      <view class="selected-events" v-if="selectedDateEvents.length">
        <view class="events-title">当日事件</view>
        <view
          class="event-item"
          v-for="event in selectedDateEvents"
          :key="event.id"
          @click="handleEventClick(event)"
        >
          <view
            class="event-color"
            :style="{ backgroundColor: event.color }"
          />
          <view class="event-content">
            <text class="event-title">{{ event.title }}</text>
            <text class="event-time" v-if="event.time">{{ event.time }}</text>
          </view>
        </view>
      </view>
    </view>
    
    <!-- 日期选择器弹窗 -->
    <view class="date-picker-modal" v-if="showDatePicker" @click="handleDatePickerHide">
      <view class="date-picker-content" @click.stop>
        <view class="picker-header">
          <text class="picker-title">选择年月</text>
          <button class="picker-close" @click="handleDatePickerHide">✕</button>
        </view>
        
        <view class="picker-body">
          <picker-view
            class="picker-view"
            :value="pickerValue"
            @change="handlePickerChange"
          >
            <picker-view-column>
              <view
                class="picker-item"
                v-for="year in yearRange"
                :key="year"
              >
                {{ year }}年
              </view>
            </picker-view-column>
            
            <picker-view-column>
              <view
                class="picker-item"
                v-for="month in monthRange"
                :key="month"
              >
                {{ month }}月
              </view>
            </picker-view-column>
          </picker-view>
        </view>
        
        <view class="picker-actions">
          <button class="picker-btn cancel-btn" @click="handleDatePickerHide">
            取消
          </button>
          <button class="picker-btn confirm-btn" @click="handleDatePickerConfirm">
            确定
          </button>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
import { ref, reactive, computed, watch, onMounted } from 'vue'

export default {
  name: 'Calendar',
  props: {
    // 当前日期
    value: {
      type: [String, Date],
      default: null
    },
    // 最小日期
    minDate: {
      type: [String, Date],
      default: null
    },
    // 最大日期
    maxDate: {
      type: [String, Date],
      default: null
    },
    // 选择模式
    mode: {
      type: String,
      default: 'single', // single, multiple, range
      validator: (value) => ['single', 'multiple', 'range'].includes(value)
    },
    // 是否显示农历
    showLunar: {
      type: Boolean,
      default: false
    },
    // 是否显示今天按钮
    showTodayButton: {
      type: Boolean,
      default: true
    },
    // 是否显示选中信息
    showSelectedInfo: {
      type: Boolean,
      default: true
    },
    // 是否允许清除选择
    allowClear: {
      type: Boolean,
      default: true
    },
    // 事件数据
    events: {
      type: Array,
      default: () => []
    },
    // 标记数据
    marks: {
      type: Array,
      default: () => []
    },
    // 禁用日期函数
    disabledDate: {
      type: Function,
      default: null
    }
  },
  emits: ['update:value', 'change', 'dayClick', 'dayLongPress', 'eventClick'],
  setup(props, { emit }) {
    // 响应式数据
    const currentDate = ref(new Date())
    const selectedDate = ref(null)
    const selectedDates = ref([])
    const rangeStart = ref(null)
    const rangeEnd = ref(null)
    const showDatePicker = ref(false)
    const pickerValue = ref([0, 0])
    
    // 星期标题
    const weekdays = ['日', '一', '二', '三', '四', '五', '六']
    
    // 计算属性
    const currentYear = computed(() => currentDate.value.getFullYear())
    const currentMonth = computed(() => currentDate.value.getMonth() + 1)
    
    // 年份范围
    const yearRange = computed(() => {
      const currentYear = new Date().getFullYear()
      const years = []
      for (let i = currentYear - 50; i <= currentYear + 50; i++) {
        years.push(i)
      }
      return years
    })
    
    // 月份范围
    const monthRange = computed(() => {
      return Array.from({ length: 12 }, (_, i) => i + 1)
    })
    
    // 格式化选中日期
    const formatSelectedDate = computed(() => {
      if (!selectedDate.value) return ''
      
      const date = new Date(selectedDate.value)
      return `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日`
    })
    
    // 选中日期的事件
    const selectedDateEvents = computed(() => {
      if (!selectedDate.value) return []
      
      const dateStr = formatDate(selectedDate.value)
      return props.events.filter(event => event.date === dateStr)
    })
    
    // 日历周数据
    const calendarWeeks = computed(() => {
      const year = currentYear.value
      const month = currentMonth.value
      
      // 获取当月第一天和最后一天
      const firstDay = new Date(year, month - 1, 1)
      const lastDay = new Date(year, month, 0)
      
      // 获取第一周的开始日期（周日开始）
      const startDate = new Date(firstDay)
      startDate.setDate(startDate.getDate() - firstDay.getDay())
      
      const weeks = []
      const currentWeekDate = new Date(startDate)
      
      // 生成6周的日期
      for (let week = 0; week < 6; week++) {
        const weekDays = []
        
        for (let day = 0; day < 7; day++) {
          const dayData = createDayData(new Date(currentWeekDate))
          weekDays.push(dayData)
          currentWeekDate.setDate(currentWeekDate.getDate() + 1)
        }
        
        weeks.push(weekDays)
        
        // 如果最后一周都是下个月的日期，则停止生成
        if (week >= 4 && weekDays.every(day => !day.isCurrentMonth)) {
          break
        }
      }
      
      return weeks
    })
    
    // 创建日期数据
    const createDayData = (date) => {
      const year = currentYear.value
      const month = currentMonth.value
      const dateStr = formatDate(date)
      
      const dayData = {
        date: new Date(date),
        day: date.getDate(),
        dateStr,
        isCurrentMonth: date.getMonth() === month - 1,
        isToday: isToday(date),
        isSelected: isSelected(date),
        isDisabled: isDisabled(date),
        isInRange: isInRange(date),
        isRangeStart: isRangeStart(date),
        isRangeEnd: isRangeEnd(date),
        marks: getDateMarks(dateStr),
        eventCount: getDateEventCount(dateStr),
        lunar: props.showLunar ? getLunarDate(date) : null
      }
      
      return dayData
    }
    
    // 格式化日期
    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 isToday = (date) => {
      const today = new Date()
      return date.toDateString() === today.toDateString()
    }
    
    // 判断是否被选中
    const isSelected = (date) => {
      if (props.mode === 'single') {
        return selectedDate.value && 
               date.toDateString() === new Date(selectedDate.value).toDateString()
      } else if (props.mode === 'multiple') {
        return selectedDates.value.some(selectedDate => 
          date.toDateString() === new Date(selectedDate).toDateString()
        )
      }
      return false
    }
    
    // 判断是否被禁用
    const isDisabled = (date) => {
      if (props.disabledDate) {
        return props.disabledDate(date)
      }
      
      if (props.minDate && date < new Date(props.minDate)) {
        return true
      }
      
      if (props.maxDate && date > new Date(props.maxDate)) {
        return true
      }
      
      return false
    }
    
    // 判断是否在范围内
    const isInRange = (date) => {
      if (props.mode !== 'range' || !rangeStart.value || !rangeEnd.value) {
        return false
      }
      
      const start = new Date(rangeStart.value)
      const end = new Date(rangeEnd.value)
      return date >= start && date <= end
    }
    
    // 判断是否为范围开始
    const isRangeStart = (date) => {
      return props.mode === 'range' && rangeStart.value &&
             date.toDateString() === new Date(rangeStart.value).toDateString()
    }
    
    // 判断是否为范围结束
    const isRangeEnd = (date) => {
      return props.mode === 'range' && rangeEnd.value &&
             date.toDateString() === new Date(rangeEnd.value).toDateString()
    }
    
    // 获取日期标记
    const getDateMarks = (dateStr) => {
      return props.marks.filter(mark => mark.date === dateStr)
    }
    
    // 获取日期事件数量
    const getDateEventCount = (dateStr) => {
      return props.events.filter(event => event.date === dateStr).length
    }
    
    // 获取农历日期（简化版）
    const getLunarDate = (date) => {
      // 这里应该使用专业的农历转换库
      // 简化实现，仅作示例
      const day = date.getDate()
      if (day === 1) return '初一'
      if (day === 15) return '十五'
      return ''
    }
    
    // 获取日期样式类
    const getDayClass = (day) => {
      const classes = []
      
      if (!day.isCurrentMonth) classes.push('other-month')
      if (day.isToday) classes.push('today')
      if (day.isSelected) classes.push('selected')
      if (day.isDisabled) classes.push('disabled')
      if (day.isInRange) classes.push('in-range')
      if (day.isRangeStart) classes.push('range-start')
      if (day.isRangeEnd) classes.push('range-end')
      if (day.marks && day.marks.length) classes.push('has-marks')
      if (day.eventCount > 0) classes.push('has-events')
      
      return classes
    }
    
    // 事件处理
    const handlePrevMonth = () => {
      const newDate = new Date(currentDate.value)
      newDate.setMonth(newDate.getMonth() - 1)
      currentDate.value = newDate
    }
    
    const handleNextMonth = () => {
      const newDate = new Date(currentDate.value)
      newDate.setMonth(newDate.getMonth() + 1)
      currentDate.value = newDate
    }
    
    const handleToday = () => {
      currentDate.value = new Date()
      selectedDate.value = new Date()
      emit('update:value', formatDate(new Date()))
      emit('change', formatDate(new Date()))
    }
    
    const handleDayClick = (day) => {
      if (day.isDisabled) return
      
      emit('dayClick', day)
      
      if (props.mode === 'single') {
        selectedDate.value = day.date
        emit('update:value', day.dateStr)
        emit('change', day.dateStr)
      } else if (props.mode === 'multiple') {
        const index = selectedDates.value.findIndex(date => 
          new Date(date).toDateString() === day.date.toDateString()
        )
        
        if (index >= 0) {
          selectedDates.value.splice(index, 1)
        } else {
          selectedDates.value.push(day.dateStr)
        }
        
        emit('update:value', [...selectedDates.value])
        emit('change', [...selectedDates.value])
      } else if (props.mode === 'range') {
        if (!rangeStart.value || (rangeStart.value && rangeEnd.value)) {
          rangeStart.value = day.dateStr
          rangeEnd.value = null
        } else {
          if (new Date(day.dateStr) < new Date(rangeStart.value)) {
            rangeEnd.value = rangeStart.value
            rangeStart.value = day.dateStr
          } else {
            rangeEnd.value = day.dateStr
          }
          
          emit('update:value', [rangeStart.value, rangeEnd.value])
          emit('change', [rangeStart.value, rangeEnd.value])
        }
      }
    }
    
    const handleDayLongPress = (day) => {
      emit('dayLongPress', day)
    }
    
    const handleEventClick = (event) => {
      emit('eventClick', event)
    }
    
    const handleClearSelection = () => {
      selectedDate.value = null
      selectedDates.value = []
      rangeStart.value = null
      rangeEnd.value = null
      
      emit('update:value', null)
      emit('change', null)
    }
    
    const handleDatePickerShow = () => {
      const yearIndex = yearRange.value.indexOf(currentYear.value)
      const monthIndex = currentMonth.value - 1
      pickerValue.value = [yearIndex, monthIndex]
      showDatePicker.value = true
    }
    
    const handleDatePickerHide = () => {
      showDatePicker.value = false
    }
    
    const handlePickerChange = (e) => {
      pickerValue.value = e.detail.value
    }
    
    const handleDatePickerConfirm = () => {
      const [yearIndex, monthIndex] = pickerValue.value
      const year = yearRange.value[yearIndex]
      const month = monthIndex + 1
      
      currentDate.value = new Date(year, month - 1, 1)
      showDatePicker.value = false
    }
    
    // 初始化
    const initCalendar = () => {
      if (props.value) {
        if (props.mode === 'single') {
          selectedDate.value = new Date(props.value)
          currentDate.value = new Date(props.value)
        } else if (props.mode === 'multiple' && Array.isArray(props.value)) {
          selectedDates.value = [...props.value]
          if (props.value.length > 0) {
            currentDate.value = new Date(props.value[0])
          }
        } else if (props.mode === 'range' && Array.isArray(props.value)) {
          rangeStart.value = props.value[0]
          rangeEnd.value = props.value[1]
          if (props.value[0]) {
            currentDate.value = new Date(props.value[0])
          }
        }
      }
    }
    
    // 监听value变化
    watch(
      () => props.value,
      () => {
        initCalendar()
      },
      { immediate: true }
    )
    
    return {
      currentDate,
      selectedDate,
      selectedDates,
      rangeStart,
      rangeEnd,
      showDatePicker,
      pickerValue,
      weekdays,
      currentYear,
      currentMonth,
      yearRange,
      monthRange,
      formatSelectedDate,
      selectedDateEvents,
      calendarWeeks,
      getDayClass,
      handlePrevMonth,
      handleNextMonth,
      handleToday,
      handleDayClick,
      handleDayLongPress,
      handleEventClick,
      handleClearSelection,
      handleDatePickerShow,
      handleDatePickerHide,
      handlePickerChange,
      handleDatePickerConfirm
    }
  }
}
</script>

<style lang="scss" scoped>
.calendar-container {
  background-color: #fff;
  border-radius: 12rpx;
  overflow: hidden;
}

.calendar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 32rpx;
  background-color: #f8f9fa;
  border-bottom: 2rpx solid #e9ecef;
}

.header-controls {
  display: flex;
  align-items: center;
  gap: 32rpx;
}

.control-btn {
  width: 64rpx;
  height: 64rpx;
  border-radius: 50%;
  background-color: #fff;
  border: 2rpx solid #e9ecef;
  display: flex;
  align-items: center;
  justify-content: center;
  
  .control-icon {
    font-size: 32rpx;
    color: #666;
    font-weight: 600;
  }
  
  &:active {
    background-color: #f8f9fa;
  }
}

.current-date {
  display: flex;
  align-items: center;
  gap: 12rpx;
  padding: 16rpx 24rpx;
  background-color: #fff;
  border-radius: 8rpx;
  border: 2rpx solid #e9ecef;
  
  .year-month {
    font-size: 32rpx;
    font-weight: 600;
    color: #333;
  }
  
  .date-picker-icon {
    font-size: 20rpx;
    color: #666;
  }
  
  &:active {
    background-color: #f8f9fa;
  }
}

.today-btn {
  padding: 12rpx 24rpx;
  background-color: #2e8b57;
  color: #fff;
  border-radius: 6rpx;
  font-size: 24rpx;
  
  &:active {
    opacity: 0.8;
  }
}

.calendar-weekdays {
  display: flex;
  background-color: #f8f9fa;
  border-bottom: 2rpx solid #e9ecef;
}

.weekday-item {
  flex: 1;
  text-align: center;
  padding: 24rpx 0;
  font-size: 26rpx;
  color: #666;
  font-weight: 600;
}

.calendar-body {
  background-color: #fff;
}

.calendar-week {
  display: flex;
  border-bottom: 2rpx solid #f8f9fa;
  
  &:last-child {
    border-bottom: none;
  }
}

.calendar-day {
  flex: 1;
  position: relative;
  min-height: 120rpx;
  border-right: 2rpx solid #f8f9fa;
  
  &:last-child {
    border-right: none;
  }
  
  &.other-month {
    .day-number {
      color: #ccc;
    }
  }
  
  &.today {
    .day-number {
      background-color: #2e8b57;
      color: #fff;
    }
  }
  
  &.selected {
    background-color: #e6f7ff;
    
    .day-number {
      background-color: #1890ff;
      color: #fff;
    }
  }
  
  &.disabled {
    background-color: #f5f5f5;
    
    .day-number {
      color: #ccc;
    }
  }
  
  &.in-range {
    background-color: #e6f7ff;
  }
  
  &.range-start,
  &.range-end {
    .day-number {
      background-color: #1890ff;
      color: #fff;
    }
  }
  
  &.has-marks {
    .day-content::after {
      content: '';
      position: absolute;
      bottom: 8rpx;
      left: 50%;
      transform: translateX(-50%);
      width: 8rpx;
      height: 8rpx;
      background-color: #ff4757;
      border-radius: 50%;
    }
  }
  
  &:active:not(.disabled) {
    background-color: #f0f0f0;
  }
}

.day-content {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 16rpx 8rpx;
}

.day-number {
  width: 56rpx;
  height: 56rpx;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 28rpx;
  color: #333;
  font-weight: 500;
}

.lunar-text {
  font-size: 20rpx;
  color: #999;
  margin-top: 4rpx;
}

.day-marks {
  position: absolute;
  bottom: 12rpx;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 4rpx;
}

.mark-dot {
  width: 8rpx;
  height: 8rpx;
  border-radius: 50%;
}

.event-count {
  position: absolute;
  top: 8rpx;
  right: 8rpx;
  min-width: 32rpx;
  height: 32rpx;
  background-color: #ff4757;
  color: #fff;
  font-size: 20rpx;
  border-radius: 16rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 8rpx;
}

.selected-info {
  padding: 32rpx;
  background-color: #f8f9fa;
  border-top: 2rpx solid #e9ecef;
}

.selected-date {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 24rpx;
}

.selected-text {
  font-size: 28rpx;
  color: #333;
  font-weight: 500;
}

.clear-btn {
  padding: 8rpx 16rpx;
  background-color: #fff;
  color: #666;
  border: 2rpx solid #e9ecef;
  border-radius: 6rpx;
  font-size: 24rpx;
  
  &:active {
    background-color: #f8f9fa;
  }
}

.selected-events {
  .events-title {
    font-size: 26rpx;
    color: #666;
    margin-bottom: 16rpx;
  }
}

.event-item {
  display: flex;
  align-items: center;
  gap: 16rpx;
  padding: 16rpx;
  background-color: #fff;
  border-radius: 8rpx;
  margin-bottom: 12rpx;
  
  &:last-child {
    margin-bottom: 0;
  }
  
  &:active {
    background-color: #f8f9fa;
  }
}

.event-color {
  width: 16rpx;
  height: 16rpx;
  border-radius: 50%;
}

.event-content {
  flex: 1;
  
  .event-title {
    display: block;
    font-size: 28rpx;
    color: #333;
    margin-bottom: 4rpx;
  }
  
  .event-time {
    font-size: 24rpx;
    color: #666;
  }
}

.date-picker-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.date-picker-content {
  width: 80%;
  max-width: 600rpx;
  background-color: #fff;
  border-radius: 12rpx;
  overflow: hidden;
}

.picker-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 32rpx;
  background-color: #f8f9fa;
  border-bottom: 2rpx solid #e9ecef;
}

.picker-title {
  font-size: 32rpx;
  font-weight: 600;
  color: #333;
}

.picker-close {
  font-size: 32rpx;
  color: #666;
  padding: 8rpx;
}

.picker-body {
  height: 400rpx;
}

.picker-view {
  width: 100%;
  height: 100%;
}

.picker-item {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 80rpx;
  font-size: 28rpx;
  color: #333;
}

.picker-actions {
  display: flex;
  border-top: 2rpx solid #e9ecef;
}

.picker-btn {
  flex: 1;
  height: 88rpx;
  font-size: 28rpx;
  font-weight: 600;
  
  &.cancel-btn {
    background-color: #fff;
    color: #666;
    border-right: 2rpx solid #e9ecef;
  }
  
  &.confirm-btn {
    background-color: #2e8b57;
    color: #fff;
  }
  
  &:active {
    opacity: 0.8;
  }
}
</style>