<script setup lang="ts">
import dayjs from 'dayjs/esm/index'
import {
  DatePicker as VanDatePicker,
  Field as VanField,
  PickerGroup as VanPickerGroup,
  Popup as VanPopup,
  TimePicker as VanTimePicker,
} from 'vant'
import { computed, ref } from 'vue'

interface Props {
  attr: any
  form?: any
  mode?: string
  readonly?: boolean
  placeholder?: string
  labelData?: string
  labelAlign?: string
  inputAlign?: string
  required?: boolean
  showLabel?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  mode: '查询',
  readonly: false,
  showLabel: true,
})

const emits = defineEmits(['update:modelValue', 'change'])

// 双向绑定
const modelData = defineModel<string | number | boolean | any[] | Record<string, any>>()

// 日期时间选择数据
const dateTimePickerValue = ref<any>({})
const showDatePicker = ref(false)

// 配置的表单值格式（仅针对 datePicker 生效）
// 作用：统一控制日期值的格式化输入/输出与选择器展示粒度
// 可选：'YYYY' | 'YYYY-MM' | 'YYYY-MM-DD' | 'YYYY-MM-DD HH' | 'YYYY-MM-DD HH:mm' | 'YYYY-MM-DD HH:mm:ss'
const formValueFormat = computed(() => {
  // 默认全格式
  return (props.attr && (props.attr as any).formValueFormat) || 'YYYY-MM-DD HH:mm:ss'
})

// 根据 formValueFormat 动态计算日期列类型（决定 VanDatePicker 展示年/月/日）
// 例如：YYYY 只显示年；YYYY-MM 显示年、月；YYYY-MM-DD 显示年、月、日
const dateColumnsType = computed(() => {
  const format = formValueFormat.value
  const columns: string[] = ['year']
  if (format.includes('MM'))
    columns.push('month')
  if (format.includes('DD'))
    columns.push('day')
  return columns as any
})

// 是否包含时间（决定是否展示时间页签与 VanTimePicker）
const hasTime = computed(() => formValueFormat.value.includes('HH'))

// 根据 formValueFormat 动态计算时间列类型（决定时/分/秒的展示）
// 例如：包含 HH 显示小时；包含 mm 显示分钟；包含 ss 显示秒
const timeColumnsType = computed(() => {
  const format = formValueFormat.value
  const columns: string[] = []
  if (format.includes('HH'))
    columns.push('hour')
  if (format.includes('mm'))
    columns.push('minute')
  if (format.includes('ss'))
    columns.push('second')
  return columns as any
})

// 根据 attr.dateRangeOption 计算 VanDatePicker/VanCalendar 的可选范围
// attr.dateRangeOption 结构示例：
// { type: 'beforeToday' | 'afterToday' | 'custom', beforeDays?: number, afterDays?: number }
// 语义说明：
// - beforeToday: 只能选择今天之前（不包含今天），无下限
// - afterToday: 只能选择今天之后（不包含今天），无上限
// - custom: 使用 beforeDays/afterDays 相对于今天进行偏移计算
//   beforeDays: 往前多少天（正数表示往前，负数表示往后）
//   afterDays: 往后多少天（正数表示往后，负数表示往前）
const datePickerMinDate = computed(() => {
  const opt = (props.attr as any).dateRangeOption
  if (!opt || !opt.type || props.mode === '查询')
    return undefined
  // beforeToday 不限制最小日期
  if (opt.type === 'beforeToday') {
    return undefined
  }
  // afterToday 从今天开始（包含今天）
  if (opt.type === 'afterToday') {
    return dayjs().startOf('day').toDate()
  }
  // custom 使用 beforeDays 进行计算（beforeDays 表示往前多少天，所以要减去）
  if (opt.type === 'custom') {
    if (typeof opt.beforeDays === 'number') {
      // beforeDays 为正数表示往前多少天，为负数表示往后多少天
      return dayjs().subtract(Math.abs(opt.beforeDays), 'day').startOf('day').toDate()
    }
    return undefined
  }
  return undefined
})

const datePickerMaxDate = computed(() => {
  const opt = (props.attr as any).dateRangeOption
  if (!opt || !opt.type || props.mode === '查询')
    return undefined
  // beforeToday 最多到今天结束（包含今天）
  if (opt.type === 'beforeToday') {
    return dayjs().endOf('day').toDate()
  }
  // afterToday 默认不限制上限；只有 custom 类型会依据 afterDays 计算上限
  if (opt.type === 'afterToday') {
    return undefined
  }
  // custom 使用 afterDays 进行计算（afterDays 表示往后多少天，所以要加上）
  if (opt.type === 'custom') {
    if (typeof opt.afterDays === 'number') {
      // afterDays 为正数表示往后多少天，为负数表示往前多少天
      return dayjs().add(Math.abs(opt.afterDays), 'day').endOf('day').toDate()
    }
    return undefined
  }
  return undefined
})

// 根据 attr.dateRangeOption 限制时间选择器的列选项
// 如果 type 为 'afterToday'，则根据选择的日期决定小时起始值
const timePickerColumns = computed(() => {
  const opt = (props.attr as any).dateRangeOption
  if (!opt || opt.type !== 'afterToday' || props.mode === '查询')
    return undefined

  const columns: any[] = []
  const pad = (n: number) => n.toString().padStart(2, '0')
  const now = dayjs()

  // 获取用户选择的日期
  const selectedDate = dateTimePickerValue.value.date
  let startHour = 0 // 默认从00:00开始

  // 如果选择的日期是今天，才限制从当前小时+1开始
  if (selectedDate && selectedDate.length >= 3) {
    const selectedYear = Number.parseInt(selectedDate[0])
    const selectedMonth = Number.parseInt(selectedDate[1])
    const selectedDay = Number.parseInt(selectedDate[2] || '1')

    const selectedDateTime = dayjs().year(selectedYear).month(selectedMonth - 1).date(selectedDay).startOf('day')
    const today = now.startOf('day')

    // 如果选择的是今天，才从当前小时+1开始
    if (selectedDateTime.isSame(today, 'day')) {
      startHour = now.hour() + 1
    }
  }
  else {
    // 如果没有选择日期，默认为今天，限制时间
    startHour = now.hour() + 1
  }

  // 小时列从计算出的起始小时开始到23
  const hourOptions = []
  for (let h = startHour; h < 24; h++) {
    hourOptions.push({ text: pad(h), value: pad(h) })
  }
  // 如果没有可选小时（例如当前为23），允许选择23
  if (hourOptions.length === 0) {
    hourOptions.push({ text: pad(23), value: pad(23) })
  }
  columns.push(hourOptions)

  // 分钟列（如果需要）
  if (timeColumnsType.value.includes('minute')) {
    const minutes = Array.from({ length: 60 }, (_, i) => ({ text: i.toString().padStart(2, '0'), value: i.toString().padStart(2, '0') }))
    columns.push(minutes)
  }
  // 秒列（如果需要）
  if (timeColumnsType.value.includes('second')) {
    const seconds = Array.from({ length: 60 }, (_, i) => ({ text: i.toString().padStart(2, '0'), value: i.toString().padStart(2, '0') }))
  }

  return columns
})

// 展示日期时间选择器：根据 formValueFormat 初始化 VanDatePicker/VanTimePicker 的当前值
// 规则：
// - 若已有字符串值，按 formValueFormat 解析并拆分为日期/时间数组
// - 若无值，按当前时间生成匹配格式的默认数组
function showDataTimePicker() {
  if (modelData.value && typeof modelData.value === 'string') {
    const base = dayjs(modelData.value as string, formValueFormat.value)
    const dateArr: string[] = []
    dateArr.push(base.format('YYYY'))
    if (dateColumnsType.value.includes('month'))
      dateArr.push(base.format('MM'))
    if (dateColumnsType.value.includes('day'))
      dateArr.push(base.format('DD'))
    const timeArr: string[] = []
    if (hasTime.value) {
      if (timeColumnsType.value.includes('hour'))
        timeArr.push(base.format('HH'))
      if (timeColumnsType.value.includes('minute'))
        timeArr.push(base.format('mm'))
      if (timeColumnsType.value.includes('second'))
        timeArr.push(base.format('ss'))
    }
    dateTimePickerValue.value = {
      date: dateArr,
      time: timeArr.length ? timeArr : ['00', '00', '00'].slice(0, timeColumnsType.value.length),
    }
  }
  else {
    const now = dayjs()
    const dateArr: string[] = []
    dateArr.push(now.format('YYYY'))
    if (dateColumnsType.value.includes('month'))
      dateArr.push(now.format('MM'))
    if (dateColumnsType.value.includes('day'))
      dateArr.push(now.format('DD'))
    const timeArr: string[] = []
    if (hasTime.value) {
      if (timeColumnsType.value.includes('hour'))
        timeArr.push(now.format('HH'))
      if (timeColumnsType.value.includes('minute'))
        timeArr.push(now.format('mm'))
      if (timeColumnsType.value.includes('second'))
        timeArr.push(now.format('ss'))
    }
    dateTimePickerValue.value = {
      date: dateArr,
      time: timeArr.length ? timeArr : ['00', '00', '00'].slice(0, timeColumnsType.value.length),
    }
  }
  showDatePicker.value = true
}

// 日期时间选择确认：将选择的年月日(+时分秒)拼装后，最终使用 formValueFormat 输出到 v-model
function onDateTimePickerConfirm() {
  showDatePicker.value = false
  const dateParts = dateTimePickerValue.value.date as string[]
  const timeParts = (dateTimePickerValue.value.time as string[]) || []
  const year = dateParts[0]
  const month = dateParts[1] || '01'
  const day = dateParts[2] || '01'
  const hour = hasTime.value && timeParts[0] ? timeParts[0] : '00'
  const minute = hasTime.value && timeParts[1] ? timeParts[1] : '00'
  const second = hasTime.value && timeParts[2] ? timeParts[2] : '00'
  const full = `${year}-${month}-${day} ${hour}:${minute}:${second}`
  modelData.value = dayjs(full, 'YYYY-MM-DD HH:mm:ss').format(formValueFormat.value)
  emits('change')
}

function onPickerCancel() {
  showDatePicker.value = false
}
</script>

<template>
  <div>
    <!-- 日期选择-非查询 -->
    <VanField
      v-if="mode !== '查询'"
      v-model="(modelData as string | number)"
      name="datePicker"
      :label="labelData"
      v-bind="{
        'label-align': labelAlign,
        'input-align': inputAlign,
      }"
      readonly
      :is-link="true"
      :placeholder="placeholder"
      :rules="[{ required, message: `请选择${attr.name}` }]"
      :required="required"
      @click="readonly ? null : showDataTimePicker()"
    />

    <!-- 日期选择-查询 -->
    <VanField
      v-if="mode === '查询'"
      v-model="(modelData as string | number)"
      name="datePicker"
      :label="labelData"
      v-bind="{
        'label-align': labelAlign,
        'input-align': inputAlign,
      }"
      readonly
      :is-link="true"
      :placeholder="placeholder"
      :rules="[{ required, message: `请选择${attr.name}` }]"
      @click="readonly ? null : showDataTimePicker()"
    />

    <VanPopup
      v-model:show="showDatePicker"
      position="bottom"
      teleport="body"
      overlay-class="date-picker-overlay"
    >
      <VanPickerGroup
        :title="attr.name"
        :tabs="hasTime ? ['选择日期', '选择时间'] : ['选择日期']"
        next-step-text="下一步"
        :confirm-button-text="attr.confirmButtonText ? attr.confirmButtonText : '确认'"
        :cancel-button-text="attr.cancelButtonText ? attr.cancelButtonText : '取消'"
        @confirm="onDateTimePickerConfirm"
        @cancel="onPickerCancel"
      >
        <VanDatePicker
          v-model="dateTimePickerValue.date"
          :columns-type="attr.dateColumnsType || dateColumnsType"
          :min-date="datePickerMinDate"
          :max-date="datePickerMaxDate"
        />
        <VanTimePicker
          v-if="hasTime"
          v-model="dateTimePickerValue.time"
          :columns-type="attr.timeColumnsType || timeColumnsType"
          v-bind="timePickerColumns ? { columns: timePickerColumns } : {}"
          :min-time="attr.minTime ? attr.minTime : '00:00:00'"
          :max-time="attr.maxTime ? attr.maxTime : '23:59:59'"
        />
      </VanPickerGroup>
    </VanPopup>
  </div>
</template>

<style scoped>
.date-picker-overlay {
  background-color: rgba(0, 0, 0, 0.2); /* 设置为半透明的黑色 */
}
</style>
