<template>
    <view>
        <u-popup :show="show" mode="bottom" @close="close" round="16" :closeable="false">
            <div class="picker-container">

                <div class="header">
                    <text class="title">选择服务时间</text>
                    <div class="close-icon" @click="close">
                        <u-icon name="close" color="#999" size="18"></u-icon>
                    </div>
                </div>

                <div class="date-bar">
                    <div class="tabs-wrapper">
                        <u-tabs :list="dateList" :current="currentDateIndex" @click="handleDateChange"
                            lineColor="#00B8B0" :activeStyle="{ color: '#00B8B0', fontWeight: 'bold' }"
                            itemStyle="height: 44px; padding: 0 13px;"></u-tabs>
                    </div>
                    <div class="line"></div>
                    <div class="calendar-btn" @click="showCalendar = true">
                        <u-icon name="calendar" size="22" color="#333"></u-icon>
                        <text class="cal-text">日历</text>
                    </div>
                </div>

                <scroll-view scroll-y class="time-scroll">
                    <div class="time-grid">
                        <div v-for="(item, index) in timeSlots" :key="index" class="time-item" :class="{
                            'active': activeTime === item.value,
                            'disabled': item.disabled
                        }" @click="selectTime(item)">
                            <text class="time-text">{{ item.label }}</text>
                            <text class="status-text" v-if="item.disabled && item.disabledReason">{{ item.disabledReason }}</text>
                        </div>

                        <div v-if="timeSlots.length === 0" class="empty-tips">
                            <text>该日期无可预约时间</text>
                        </div>
                    </div>
                </scroll-view>

                <div class="footer-bar">
                    <div class="footer-info">
                        <text class="label">时长 {{ duration }}分钟</text>
                        <text class="result" v-if="resultText">
                            预计 {{ resultText }} 结束
                        </text>
                    </div>
                    <u-button color="#00B8B0" shape="circle" text="确认预约" :disabled="!activeTime" @click="confirm"
                        customStyle="width: 140px; height: 40px; margin: 0;"
                    ></u-button>
                </div>
            </div>
        </u-popup>

        <u-calendar :show="showCalendar" mode="single" color="#2979ff" :minDate="minCalendarDate"
            @confirm="onCalendarConfirm" @close="showCalendar = false"></u-calendar>
    </view>
</template>

<script>
/**
 * ServiceTimePicker 服务时间选择器
 * @property {Number} duration 服务时长（分钟），默认120
 * @property {String} startHour 营业开始时间（例如 '09:00'）
 * @property {String} endHour 营业结束时间（例如 '22:00'）
 * @property {Number} timeStep 时间步长（分钟），默认30
 * @property {Number} bookedTimes 已被占用的时间段数组，格式：[{ start: '2026-01-02 18:00', end: '2026-01-02 20:00' }]
 */
export default {
    props: {
        duration: { type: Number, default: 120 }, 
        startHour: { type: String, default: '08:00' },
        endHour: { type: String, default: '22:00' },
        timeStep: { type: Number, default: 30 },
        bookedTimes: { type: Array, default: () => [] }
    },
    data() {
        return {
            show: false,
            dateList: [],
            currentDateIndex: 0,
            activeTime: '',
            resultText: '',
            showCalendar: false,
            minCalendarDate: '', // 限制日历只能选今天之后
            baseDate: new Date() // 当前Tab生成的基准日期，默认为今天
        };
    },
    computed: {
        // 根据当前选中的日期，计算可用时间槽
        timeSlots() {
            const selectedTab = this.dateList[this.currentDateIndex];
            if (!selectedTab) return [];

            const targetDateStr = selectedTab.dateStr; // 目标日期
            const now = new Date();

            // 缓冲时间：当前时间 + 30分钟
            const bufferTimestamp = now.getTime() + 30 * 60 * 1000;

            const slots = [];
            const [startH, startM] = this.startHour.split(':').map(Number);
            const [endH, endM] = this.endHour.split(':').map(Number);

            // 构造当天的开始时间
            let current = new Date(targetDateStr.replace(/-/g, '/'));
            current.setHours(startH, startM, 0, 0);
            // 结束时间
            const endLimit = new Date(targetDateStr.replace(/-/g, '/'));
            endLimit.setHours(endH, endM, 0, 0);
            
            while (current <= endLimit) {
                const timeStr = `${current.getHours().toString().padStart(2, '0')}:${current.getMinutes().toString().padStart(2, '0')}`;
                const slotStartTimestamp = current.getTime();
                // 计算这个Slot如果被选中，服务结束的时间戳
                const slotEndTimestamp = slotStartTimestamp + this.duration * 60 * 1000;
                
                let isDisabled = false, reason = '';

                // 1. 校验是否过期(如果是今天)
                if (slotStartTimestamp < bufferTimestamp) {
                    isDisabled = true;
                    // 已过的时间通常不需要文字提示，或者显示“已过”
                    // reason = '已过';
                }
                // 2. 判断是否“超出营业时间”
                // 如果服务结束时间 > 营业结束时间
                // else if (slotEndTimestamp > endLimit) {
                //     isDisabled = true;
                //     reason = '时长不足'; // 或者 "超营业期"
                // }
                // 3. 判断与“已预约订单”的冲突
                else if (this.bookedTimes.length > 0) {
                    for (let book of this.bookedTimes) {
                        const bookStart = new Date(book.start.replace(/-/g, '/')).getTime();
                        const bookEnd = new Date(book.end.replace(/-/g, '/')).getTime();

                        // 判断是否有交集
                        // 公式：(SlotStart < BookEnd) && (SlotEnd > BookStart)
                        if (slotStartTimestamp < bookEnd && slotEndTimestamp > bookStart) {
                            isDisabled = true;
                            
                            // 情况A：当前格子的“起点”本身就在别人订单里
                            // 例如：别人约了14:00-16:00，我看15:00的格子
                            if (slotStartTimestamp >= bookStart && slotStartTimestamp < bookEnd) {
                                reason = '已约';
                            } 
                            // 情况B：当前格子起点是空的，但服务时长太长，撞到了后面的订单
                            // 例如：别人约了17:00开始。我看15:30的格子(服务2小时)，15:30是空的，但17:30才结束，撞了。
                            else {
                                reason = '时长不足';
                            }
                            
                            // 只要找到一个冲突就跳出循环
                            break;
                        }
                    }
                }

                slots.push({
                    label: timeStr,
                    value: timeStr,
                    disabled: isDisabled,
                    disabledReason: reason
                });

                current.setMinutes(current.getMinutes() + this.timeStep);
            }
            return slots;
        }
    },
    created() {
        const today = new Date();
        this.minCalendarDate = this.formatDate(today); // 初始化日历最小日期
        this.initDates(today);
    },
    methods: {
        // 生成从 startDate 开始的7天
        initDates(startDate) {
            const arr = [];
            const days = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];

            for (let i = 0; i < 7; i++) {
                const d = new Date(startDate);
                d.setDate(d.getDate() + i);

                const mon = (d.getMonth() + 1).toString().padStart(2, '0');
                const day = d.getDate().toString().padStart(2, '0');
                const week = days[d.getDay()];

                // 需求：格式 MM-DD
                const nameStr = i === 0 && this.isSameDay(d, new Date()) ? '今天' : `${mon}-${day}`;

                arr.push({
                    name: `${nameStr} ${week}`, // 显示如 "01-02 周五"
                    dateStr: this.formatDate(d),
                });
            }
            this.dateList = arr;
            this.currentDateIndex = 0; // 重置选中第一个
            this.activeTime = '';
            this.resultText = '';
        },
        // 日历确认回调
        onCalendarConfirm(e) {
            this.showCalendar = false;
            // e 可能是数组也可能是对象，取决于mode，single模式通常是 e[0]
            const selectedDateStr = e[0];
            if (selectedDateStr) {
                this.initDates(new Date(selectedDateStr.replace(/-/g, '/')));
            }
        },
        handleDateChange(item) {
            this.currentDateIndex = item.index;
            this.activeTime = '';
            this.resultText = '';
        },
        selectTime(item) {
            if (item.disabled) return;
            this.activeTime = item.value;
            this.calculateDisplayTime();
        },

        // 辅助计算显示用的结束时间
        calculateDisplayTime() {
            if (!this.activeTime) return;
            const dateStr = this.dateList[this.currentDateIndex].dateStr;
            const startStr = `${dateStr} ${this.activeTime}:00`;
            const startTs = new Date(startStr.replace(/-/g, '/')).getTime();
            const endTs = startTs + this.duration * 60 * 1000;
            const endObj = new Date(endTs);
            const h = endObj.getHours().toString().padStart(2, '0');
            const m = endObj.getMinutes().toString().padStart(2, '0');
            this.resultText = `${h}:${m}`;
        },
        confirm() {
            if (!this.activeTime) return;
            const dateStr = this.dateList[this.currentDateIndex].dateStr;
            const startStr = `${dateStr} ${this.activeTime}`; // 注意这里没有秒，有的后端需要补 :00

            const startTs = new Date(startStr.replace(/-/g, '/')).getTime();
            const endTs = startTs + this.duration * 60 * 1000;
            const endObj = new Date(endTs);

            const endStr = `${this.formatDate(endObj)} ${endObj.getHours().toString().padStart(2, '0')}:${endObj.getMinutes().toString().padStart(2, '0')}`;

            this.$emit('confirm', [startStr, endStr]);
            this.close();
        },
        close() {
            this.show = false;
        },
        formatDate(date) {
            const y = date.getFullYear();
            const m = (date.getMonth() + 1).toString().padStart(2, '0');
            const d = date.getDate().toString().padStart(2, '0');
            return `${y}-${m}-${d}`;
        },

        isSameDay(d1, d2) {
            return d1.getFullYear() === d2.getFullYear() &&
                d1.getMonth() === d2.getMonth() &&
                d1.getDate() === d2.getDate();
        }
    }
};
</script>

<style lang="scss" scoped>
.picker-container {
    height: 65vh;
    display: flex;
    flex-direction: column;
    background-color: #fff;

    .header {
        padding: 16px 20px;
        display: flex;
        justify-content: space-between;
        align-items: center;

        .title {
            font-size: 16px;
            font-weight: bold;
        }
    }

    .date-bar {
        display: flex;
        align-items: center;
        border-bottom: 1px solid #f5f5f5;
        background: #fff;

        .tabs-wrapper {
            flex: 1;
            overflow: hidden;
        }

        .line {
            width: 1px;
            height: 20px;
            background: #eee;
        }

        .calendar-btn {
            width: 60px;
            height: 44px;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            flex-shrink: 0;

            .cal-text {
                font-size: 10px;
                color: #666;
                margin-top: 2px;
            }

            &:active {
                background-color: #f9f9f9;
            }
        }
    }

    .time-scroll {
        flex: 1;
        height: 0;
        padding: 30rpx;
        box-sizing: border-box;
    }

    .time-grid {
        gap: 20rpx;
        display: flex;
        flex-wrap: wrap;

        .time-item {
            width: calc(24% - 15rpx);
            height: 88rpx;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            background-color: #F8F9FD;
            border-radius: 16rpx;
            border: 1rpx solid transparent;
            position: relative;

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

            .status-text {
                font-size: 20rpx;
                color: #999;
                position: absolute;
                top: 0;
                left: 0;
                background: pink;
                padding: 2rpx 16rpx;
                border-radius: 16rpx 0;
            }

            &.active {
                background-color: rgba(41, 121, 255, 0.1);
                border-color: #2979ff;

                .time-text {
                    color: #2979ff;
                }

                .status-text {
                    color: #2979ff;
                }
            }

            &.disabled { 
                display: none;
                // opacity: 0.6;
                background-color: #E4E9EF;

                .time-text {
                    color: #ccc;
                }

                .status-text {
                    color: #ff6b6b;
                }
            }
        }

        .empty-tips {
            width: 100%;
            text-align: center;
            padding: 40px 0;
            color: #999;
        }
    }
}

.footer-bar {
    position: relative;

    .footer-info {
        display: flex;
        flex-direction: column;

        .label {
            font-size: 12px;
            color: #999;
        }

        .result {
            font-size: 14px;
            font-weight: bold;
            margin-top: 2px;
        }
    }
}
</style>