<template>
    <uni-popup ref="picker" type="bottom" :safe-area="false">
        <view class="date_picker">
            <view class="title">选择时间</view>
            <!-- 日期 -->
            <template v-if="active === 0">
                <picker-view
                    :value="val"
                    class="picker-view"
                    indicator-style="height:56px;"
                    indicator-class="active"
                    immediate-change
                    @change="changeDate"
                >
                    <picker-view-column>
                        <view
                            v-for="(item, index) in years"
                            :key="index"
                            :class="{ item: true, active_item: val[0] === index }"
                            >{{ item }}</view
                        >
                    </picker-view-column>
                    <picker-view-column>
                        <view
                            v-for="(item, index) in months"
                            :key="index"
                            :class="{ item: true, active_item: val[1] === index }"
                        >
                            {{ item.toString().padStart(2, '0') }}
                        </view>
                    </picker-view-column>
                    <picker-view-column>
                        <view
                            v-for="(item, index) in days"
                            :key="index"
                            :class="{ item: true, active_item: val[2] === index }"
                        >
                            {{ item.toString().padStart(2, '0') }}
                        </view>
                    </picker-view-column>
                </picker-view>
            </template>
            <!-- 时分 -->
            <template v-if="active === 1">
                <picker-view
                    :value="val1"
                    indicator-style="height:52px"
                    indicator-class="active"
                    class="picker-view picker_time"
                    immediate-change
                    @change="changeTime"
                >
                    <picker-view-column>
                        <view
                            v-for="(item, index) in hours"
                            :key="index"
                            :class="{ item: true, active_item: val1[0] === index }"
                        >
                            {{ item.toString().padStart(2, '0') }}
                        </view>
                    </picker-view-column>
                    <picker-view-column>
                        <view
                            v-for="(item, index) in minutes"
                            :key="index"
                            :class="{ item: true, active_item: val1[1] === index }"
                        >
                            {{ item.toString().padStart(2, '0') }}
                        </view>
                    </picker-view-column>
                </picker-view>
            </template>
            <view class="operation">
                <button class="cancel_btn" @tap="cancel">取消</button>
                <button class="confirm_btn" @tap="confirm">确定</button>
            </view>
        </view>
    </uni-popup>
</template>

<script setup lang="ts">
import { nextTick, onMounted, ref } from 'vue';

const props = withDefaults(
    defineProps<{
        modelValue: string;
        disabled?: boolean;
    }>(),
    {
        disabled: false,
    },
);
const emits = defineEmits(['update:modelValue', 'confirm']);

const active = ref(0); // 0 日期 1 时间
const sendTime = ref(''); // 日期时间
const chooseDate = ref(''); // 日期
const chooseTime = ref(''); // 时间
const picker = ref();

const val = ref<number[]>([0, 0, 0]);
const val1 = ref<number[]>([0, 0]);

const date = new Date();
const now_year = date.getFullYear();
const now_month = date.getMonth() + 1;
const now_day = date.getDate();

let now_hours = ref<number>();
let now_minutes = ref<number>();

const years = ref<number[]>([]);
const months = ref<number[]>([]);
const days = ref<number[]>([]);
const hours = ref<number[]>([]);
const minutes = ref<number[]>([]);
let sameYear = ref(false);
let sameMonth = ref(false);
let sameDay = ref(false);

// 时
const setHours = (minHours: number) => {
    hours.value = [];
    for (let i = minHours; i <= 23; i++) {
        hours.value.push(i);
    }
};
// 分
const setMinutes = (minMinutes: number) => {
    minutes.value = [];
    for (let i = minMinutes; i <= 59; i++) {
        minutes.value.push(i);
    }
};
// 年
const setYears = () => {
    for (let i = now_year; i <= 2054; i++) {
        years.value.push(i);
    }
};
// 月
const setMonths = (mixMonth?: number) => {
    months.value = [];
    for (let i = mixMonth; i <= 12; i++) {
        months.value.push(i);
    }
};
// 日
const setDays = (...args: number[]) => {
    days.value = [];
    let total = 30;
    if ([1, 3, 5, 7, 8, 10, 12].includes(args[0])) {
        total = 31;
    } else if ([4, 6, 9, 11].includes(args[0])) {
        total = 30;
    } else {
        total = (args[1] % 4 === 0 && args[1] % 100 !== 0) || args[1] % 400 === 0 ? 29 : 28;
    }
    if (args.length === 3) {
        for (let i = args[2]; i <= total; i++) {
            days.value.push(i);
        }
    } else {
        for (let i = 1; i <= total; i++) {
            days.value.push(i);
        }
    }
};
// 有选中值时
const setVal = async (time: string) => {
    const t = new Date(time);
    if (t.getFullYear() === now_year) {
        setMonths(now_month);
        t.getMonth() + 1 === now_month
            ? setDays(now_month, t.getFullYear(), now_day)
            : setDays(t.getMonth() + 1, t.getFullYear());
    } else {
        setMonths(1);
        setDays(t.getMonth() + 1, t.getFullYear());
    }
    if (t.getFullYear() === now_year && t.getMonth() + 1 === now_month && t.getDate() === now_day) {
        setHours(now_hours.value);
        t.getHours() === now_hours.value ? setMinutes(now_minutes.value) : setMinutes(0);
    } else {
        setHours(0);
        setMinutes(0);
    }
    const yidx = years.value.indexOf(t.getFullYear());
    const hidx = hours.value.indexOf(t.getHours());
    const minidx = minutes.value.indexOf(t.getMinutes());
    const midx = months.value.indexOf(t.getMonth() + 1);
    const didx = days.value.indexOf(t.getDate());

    val.value = [yidx, midx, didx];
    val1.value = [hidx, minidx];
    await nextTick();
};

async function changeDate({ detail: { value } }: any) {
    const y = years.value[value[0]];
    let m = months.value[value[1]];
    let d = days.value[value[2]];
    let monthsIdx = 0;
    let daysIdx = 0;
    if (y === now_year) {
        setMonths(now_month);
        setDays(m, now_year, now_day);
        if (m === now_month) {
            setDays(now_month, now_year, now_day);
        } else {
            if (m < now_month) {
                setDays(m, now_year, now_day);
            } else {
                setDays(m, now_year);
            }
        }
        monthsIdx = months.value.findIndex((item: number) => item === m);
        value[1] = monthsIdx === -1 ? 0 : monthsIdx;
        daysIdx = days.value.findIndex((item: number) => item === d);
        value[2] = daysIdx === -1 ? 0 : daysIdx;
    } else {
        setMonths(1);
        setDays(m, y);
        value[1] = months.value.findIndex((item: number) => item === m);
        value[2] = days.value.findIndex((item: number) => item === d);
        await nextTick();
    }
    val.value = value;
    val1.value = [0, 0]; // 修改年月日
    chooseDate.value = `${years.value[val.value[0]]}/${months.value[val.value[1]]
        .toString()
        .padStart(2, '0')}/${days.value[val.value[2]].toString().padStart(2, '0')}`;
}

async function changeTime({ detail: { value } }: any) {
    const h = hours.value[value[0]];
    const m = minutes.value[value[1]];
    if (sameYear.value && sameMonth.value && sameDay.value) {
        if (h === now_hours.value) {
            setMinutes(now_minutes.value);
        } else {
            setMinutes(0);
        }
        value[1] =
            minutes.value.findIndex((item: number) => item === m) === -1
                ? 0
                : minutes.value.findIndex((item: number) => item === m);
        await nextTick();
    }
    val1.value = value;
    chooseTime.value = `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}`;
}
// 取消
function cancel() {
    if (active.value === 1) {
        active.value = 0;
        return;
    }
    picker.value.close();
}
// 确认
async function confirm() {
    if (active.value === 0) {
        if (!chooseDate.value) {
            chooseDate.value = `${years.value[val.value[0]]}/${months.value[val.value[1]]
                .toString()
                .padStart(2, '0')}/${days.value[val.value[2]].toString().padStart(2, '0')}`;
        }
        now_minutes.value = date.getMinutes();
        now_hours.value = date.getHours();
        // 判断是否今日
        sameYear.value = new Date(chooseDate.value).getFullYear() === now_year;
        sameMonth.value = new Date(chooseDate.value).getMonth() + 1 === now_month;
        sameDay.value = new Date(chooseDate.value).getDate() === now_day;
        if (sameYear.value && sameMonth.value && sameDay.value) {
            setHours(now_hours.value);
            setMinutes(now_minutes.value);
            if (chooseTime.value) {
                if (now_hours.value === parseInt(chooseTime.value.split(':')[0], 10)) {
                    setMinutes(now_minutes.value);
                } else {
                    setMinutes(0);
                }
            }
        } else {
            setHours(0);
            setMinutes(0);
        }
        active.value = 1;
        await nextTick();
        return;
    }
    if (!chooseTime.value) {
        chooseTime.value = `${hours.value[val1.value[0]]
            .toString()
            .padStart(2, '0')}:${minutes.value[val1.value[1]].toString().padStart(2, '0')}`;
    }
    sendTime.value = `${chooseDate.value} ${chooseTime.value}`;
    picker.value.close();
    emits('confirm', sendTime.value);
    emits('update:modelValue', sendTime.value);
}
function open() {
    picker.value.open();
    active.value = 0;
    sendTime.value = props.modelValue;
    setYears();
    setMonths(now_month);
    setDays(now_month, now_year, now_day);

    now_minutes.value = date.getMinutes();
    now_hours.value = date.getHours();
    setHours(now_hours.value);
    setMinutes(now_minutes.value);

    if (sendTime.value) {
        setVal(sendTime.value);
    }
}
defineExpose({
    open,
});
</script>

<style lang="scss" scoped>
.date_picker {
    position: relative;
    height: 576rpx;
    width: 750rpx;
    background-color: #fff;
    border-radius: 20rpx 20rpx 0rpx 0rpx;
    padding: 105rpx 0 0 0;
    box-sizing: border-box;

    .title {
        position: absolute;
        top: 30rpx;
        left: 30rpx;
        z-index: 99;
        color: #333;
        font-weight: 500;
        font-size: 32rpx;
    }

    .operation {
        display: flex;
        justify-content: center;
        position: absolute;
        padding-top: 16rpx;
        bottom: 60rpx;
        left: 4rpx;
        width: 100%;
        box-sizing: border-box;

        button::after {
            border: none;
        }

        .cancel_btn {
            width: 230rpx;
            height: 90rpx;
            color: #615dff;
            background-color: #ececff;
        }

        .confirm_btn {
            margin-left: 20rpx;
            height: 90rpx;
            width: 440rpx;
            color: #fff;
            background-color: #615dff;
        }
    }
}

.picker-view {
    height: 280rpx;
    width: calc(100vw - 340rpx);
    margin: 30rpx 140rpx;
    padding: 0 30rpx;
    margin: auto;

    .item {
        line-height: 56px;
        text-align: center;
        margin: 0 5rpx;
        font-size: 40rpx;
        color: #666666;
    }

    .active_item {
        color: #333;
        font-weight: 500;
        font-size: 48rpx;
    }
}

.picker_time {
    width: calc(100vw - 572rpx);
}

:deep(.active) {
    border-top: 1px solid #eee;
    border-bottom: 1px solid #eee;
    color: #333;
    font-size: 48rpx;
    font-weight: 500;
}
</style>
