<template>
    <!-- 当 mode 为 date 时，使用原生 picker 组件 -->
    <picker v-if="mode === 'date'" mode="date" :fields="dateFields" :value="dateValue" :start="minDateStr" :end="maxDateStr" @change="onPickerChange">
        <view class="ut-datetime-picker" :class="{ 'ut-datetime-picker--border': border }">
            <slot></slot>
        </view>
    </picker>

    <!-- 其他模式使用 uview-plus 的 up-datetime-picker -->
    <template v-else>
        <view @click.stop="showTime = true" class="ut-datetime-picker" :class="{ 'ut-datetime-picker--border': border }">
            <slot></slot>
        </view>
        <up-datetime-picker
            v-model:show="showTime"
            :minDate="minDateTs"
            :maxDate="maxDateTs"
            ref="datetimePickerRef"
            :title="title"
            v-model="form.startTime"
            :mode="mode"
            @cancel="cancel"
            confirmColor="#2a6d52"
            @confirm="confirm"
        ></up-datetime-picker>
    </template>
</template>
<script setup lang="ts">
import { parseTime } from '@/utils/ruoyi';

type DateTimeMode = 'time' | 'datetime' | 'date' | 'year-month';

interface Props {
    title: string;
    modelValue: string | number;
    mode: DateTimeMode;
    border: boolean;
    hasInput: boolean;
    minDate: number | string | Date;
    maxDate: number | string | Date;
    dateFields?: 'year' | 'month' | 'day';
    dateFormat?: string;
}

const props = withDefaults(defineProps<Props>(), {
    title: '选择时间',
    modelValue: '',
    mode: 'datetime' as DateTimeMode,
    border: false,
    hasInput: false,
    minDate: new Date(2000, 0, 1).getTime(),
    maxDate: new Date(2050, 0, 1).getTime(),
    dateFields: 'day',
    // 留空以便按粒度自动输出：year→{y}，month→{y}-{m}，day→{y}-{m}-{d}
    dateFormat: ''
});

const emit = defineEmits<{
    'update:modelValue': [value: string | null];
    change: [value: string | null];
}>();

const showTime = ref(false);
const datetimePickerRef = ref(null);

// 统一转换为时间戳
const toTs = (v: number | string | Date | undefined | null): number => {
    if (v === undefined || v === null) return Date.now();
    if (typeof v === 'number') return v;
    if (typeof v === 'string') return new Date(v).getTime();
    return (v as Date).getTime();
};

const form = ref({
    startTime: toTs(props.modelValue as any)
});

// 当使用原生 picker 的 date 模式时，格式化绑定和边界值（随粒度变化）
const fieldsToFormat = (f: 'year' | 'month' | 'day') => {
    if (f === 'year') return '{y}';
    if (f === 'month') return '{y}-{m}';
    return '{y}-{m}-{d}';
};
const dateValue = computed(() => {
    const v = form.value.startTime as unknown as number | string | Date;
    if (!v) return '';
    const ts = toTs(v);
    return parseTime(ts, fieldsToFormat(props.dateFields!));
});
const minDateTs = computed(() => toTs(props.minDate));
const maxDateTs = computed(() => toTs(props.maxDate));
const minDateStr = computed(() => parseTime(minDateTs.value, fieldsToFormat(props.dateFields!)));
const maxDateStr = computed(() => parseTime(maxDateTs.value, fieldsToFormat(props.dateFields!)));

const confirm = (value?: any) => {
    const timestamp = value?.value ?? Date.now();
    const startTime = parseTime(timestamp, '{y}-{m}-{d} {h}:{i}');
    showTime.value = false;
    emit('update:modelValue', startTime);
    emit('change', startTime);
};

// 原生 picker 的变更事件（返回 YYYY / YYYY-MM / YYYY-MM-DD），按传入格式输出
const onPickerChange = (e: any) => {
    const val = e?.detail?.value ?? '';
    if (!val) {
        emit('update:modelValue', '');
        emit('change', '');
        return;
    }

    let d: Date;
    if (props.dateFields === 'year') {
        const y = Number(val);
        d = new Date(y, 0, 1);
    } else if (props.dateFields === 'month') {
        const [yStr, mStr] = String(val).split('-');
        const y = Number(yStr);
        const m = Number(mStr) - 1;
        d = new Date(y, m, 1);
    } else {
        d = new Date(val);
    }

    const out = parseTime(d.getTime(), props.dateFormat || fieldsToFormat(props.dateFields!));
    emit('update:modelValue', out);
    emit('change', out);
};

const cancel = () => {
    showTime.value = false;
};
</script>