<template>
    <div class="time-period-search">
        <el-select class="time-period-search__unit" :model-value="unit" @update:model-value="handleUnitChange">
            <el-option
                v-for="item in visibleTimePeriodUnitOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
            />
        </el-select>

        <el-button
            v-if="!isCustomUnit"
            class="time-period-search__button"
            :icon="ArrowLeft"
            :title="`上一个${unitLabel}`"
            @click="shiftPeriod(-1)"
        />

        <el-date-picker
            v-if="!isCustomUnit"
            class="time-period-search__picker"
            :model-value="baseDate"
            :type="getTimePeriodPickerType(props.unit)"
            :format="getTimePeriodPickerFormat(props.unit)"
            :clearable="false"
            :editable="false"
            :placeholder="`选择${unitLabel}`"
            @update:model-value="handleDateChange"
        />

        <el-date-picker
            v-else
            class="time-period-search__range-picker"
            :model-value="rangeValue"
            type="datetimerange"
            format="YYYY-MM-DD HH:mm:ss"
            value-format="YYYY-MM-DD HH:mm:ss.SSS"
            range-separator="至"
            start-placeholder="开始时间"
            end-placeholder="结束时间"
            :clearable="false"
            :editable="false"
            @update:model-value="handleRangeChange"
        />

        <el-button
            v-if="!isCustomUnit"
            class="time-period-search__button"
            :icon="ArrowRight"
            :title="`下一个${unitLabel}`"
            @click="shiftPeriod(1)"
        />

        <el-button
            v-if="!isCustomUnit"
            class="time-period-search__button"
            :icon="Clock"
            :title="`当前${unitLabel}`"
            @click="setCurrentPeriod"
        />
    </div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { ArrowLeft, ArrowRight, Clock } from '@element-plus/icons-vue'
import {
    getTimePeriodPickerFormat,
    getTimePeriodPickerType,
    resolveTimePeriodUnitLabel,
    shiftTimePeriod,
    timePeriodUnitOptions,
    type TimePeriodUnit
} from './timePeriod'

defineOptions({
    name: 'TimePeriodSearch'
})

const props = defineProps<{
    unit: TimePeriodUnit
    modelValue: Date | string | number
    rangeValue?: string[]
    visibleUnits?: TimePeriodUnit[]
}>()

const emit = defineEmits<{
    'update:unit': [value: TimePeriodUnit]
    'update:modelValue': [value: Date]
    'update:rangeValue': [value: string[]]
}>()

const baseDate = computed(() => new Date(props.modelValue))
const unitLabel = computed(() => resolveTimePeriodUnitLabel(props.unit))
const isCustomUnit = computed(() => props.unit === 'custom')
const visibleTimePeriodUnitOptions = computed(() => {
    if (!props.visibleUnits?.length) return timePeriodUnitOptions

    return timePeriodUnitOptions.filter(item => props.visibleUnits?.includes(item.value))
})
const rangeValue = computed(() => props.rangeValue || [])

const handleUnitChange = (value: TimePeriodUnit) => {
    emit('update:unit', value)
}

const handleDateChange = (value: Date | string | number | null) => {
    if (!value) return
    emit('update:modelValue', new Date(value))
}

const handleRangeChange = (value: string[] | null) => {
    if (!value?.length) return
    emit('update:rangeValue', value)
}

const shiftPeriod = (offset: number) => {
    emit('update:modelValue', shiftTimePeriod(props.unit, baseDate.value, offset))
}

const setCurrentPeriod = () => {
    emit('update:modelValue', new Date())
}
</script>

<style scoped lang="scss">
.time-period-search {
    display: flex;
    width: 100%;
    align-items: center;
    gap: 4px;
}

.time-period-search__unit {
    width: 56px;
    flex: 0 0 56px;
}

.time-period-search__picker {
    width: 112px;
    flex: 0 0 112px;
}

.time-period-search__range-picker {
    width: 360px;
    flex: 1 1 360px;
    min-width: 280px;
}

.time-period-search__button {
    width: 28px;
    flex: 0 0 28px;
    padding: 8px 6px;
}
</style>
