package com.ruoyi.common.utils;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.util.Locale;

/**
 * 周期时间范围工具类
 * 支持：每天/每周/半月/每月 的开始&结束时间计算，格式固定为 yyyy-MM-dd HH:mm:ss
 */
public class TimeCycleUtil {
    // 时间格式化器（全局复用，线程安全）
    private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    // 定义周的起始（中国标准：周一为一周第一天）
    private static final WeekFields WEEK_FIELDS = WeekFields.of(Locale.CHINA);

    /**
     * 周期类型枚举（规范输入，避免硬编码）
     */
    public enum CycleType {
        DAILY("每天"),
        WEEKLY("每周"),
        HALF_MONTH("半月"),
        MONTHLY("每月");

        private final String desc;

        CycleType(String desc) {
            this.desc = desc;
        }

        // 根据输入字符串匹配枚举（忽略大小写）
        public static CycleType match(String input) {
            if (input == null || input.trim().isEmpty()) {
                throw new IllegalArgumentException("周期类型不能为空");
            }
            String trimInput = input.trim();
            for (CycleType type : CycleType.values()) {
                if (type.desc.equals(trimInput) || type.name().equalsIgnoreCase(trimInput)) {
                    return type;
                }
            }
            throw new IllegalArgumentException("不支持的周期类型：" + input + "，仅支持：每天、每周、半月、每月");
        }
    }

    /**
     * 时间范围返回结果
     */
    public static class TimeRange {
        private String startTime; // 开始时间（yyyy-MM-dd HH:mm:ss）
        private String endTime;   // 结束时间（yyyy-MM-dd HH:mm:ss）

        public TimeRange(String startTime, String endTime) {
            this.startTime = startTime;
            this.endTime = endTime;
        }

        // getter & setter
        public String getStartTime() {
            return startTime;
        }

        public void setStartTime(String startTime) {
            this.startTime = startTime;
        }

        public String getEndTime() {
            return endTime;
        }

        public void setEndTime(String endTime) {
            this.endTime = endTime;
        }

        @Override
        public String toString() {
            return "TimeRange{" +
                    "开始时间='" + startTime + '\'' +
                    ", 结束时间='" + endTime + '\'' +
                    '}';
        }
    }

    /**
     * 核心方法：根据周期类型获取对应的时间范围
     * @param cycle 周期类型（支持：每天/每周/半月/每月，大小写不敏感）
     * @return 时间范围（startTime + endTime）
     */
    public static TimeRange getCycleTimeRange(String cycle) {
        CycleType cycleType = CycleType.match(cycle);
        LocalDate today = LocalDate.now(); // 当前日期（系统默认时区）
        LocalDateTime startTime;
        LocalDateTime endTime;

        switch (cycleType) {
            case DAILY:
                // 每天：当前日期 00:00:00 到 23:59:59
                startTime = today.atStartOfDay();
                endTime = today.atTime(23, 59, 59);
                break;

            case WEEKLY:
                // 每周：向前推1周 → 前一周的周一00:00:00 到 前一周的周日23:59:59
                // 步骤1：当前日期往前推7天，得到前一周的同天日期
                LocalDate lastWeekSameDay = today.minusWeeks(1);
                // 步骤2：找到该日期所在周的周一（中国周：周一为第一天）
                LocalDate lastWeekMonday = lastWeekSameDay.with(TemporalAdjusters.previousOrSame(WEEK_FIELDS.getFirstDayOfWeek()));
                // 步骤3：前一周的周日 = 周一 + 6天
                LocalDate lastWeekSunday = lastWeekMonday.plusDays(6);
                startTime = lastWeekMonday.atStartOfDay();
                endTime = lastWeekSunday.atTime(23, 59, 59);
                break;

            case HALF_MONTH:
                // 半月：向前推1个半月周期 → 规则：
                // 1. 当前日期≤15号（上半月）→ 前一个半月是「上个月的16号 ~ 上个月最后一天」
                // 2. 当前日期>15号（下半月）→ 前一个半月是「本月的1号 ~ 本月15号」
                int currentDay = today.getDayOfMonth();
                if (currentDay <= 15) {
                    // 场景1：当前是上半月（如2026-02-10）→ 前半月=2026-01-16 ~ 2026-01-31
                    LocalDate lastMonth = today.minusMonths(1);
                    startTime = lastMonth.withDayOfMonth(16).atStartOfDay();
                    LocalDate lastMonthLastDay = lastMonth.with(TemporalAdjusters.lastDayOfMonth());
                    endTime = lastMonthLastDay.atTime(23, 59, 59);
                } else {
                    // 场景2：当前是下半月（如2026-02-18）→ 前半月=2026-02-01 ~ 2026-02-15
                    startTime = today.withDayOfMonth(1).atStartOfDay();
                    endTime = today.withDayOfMonth(15).atTime(23, 59, 59);
                }
                break;

            case MONTHLY:
                // 每月：向前推1个月 → 上个月的第一天00:00:00 到 上个月最后一天23:59:59
                LocalDate lastMonth = today.minusMonths(1);
                LocalDate lastMonthFirstDay = lastMonth.with(TemporalAdjusters.firstDayOfMonth());
                LocalDate lastMonthLastDay = lastMonth.with(TemporalAdjusters.lastDayOfMonth());
                startTime = lastMonthFirstDay.atStartOfDay();
                endTime = lastMonthLastDay.atTime(23, 59, 59);
                break;

            default:
                throw new IllegalArgumentException("未实现的周期类型：" + cycleType);
        }

        // 格式化时间为指定格式
        return new TimeRange(
                startTime.format(DATETIME_FORMATTER),
                endTime.format(DATETIME_FORMATTER)
        );
    }

    /**
     * 重载方法：支持指定时区（解决跨时区场景）
     * @param cycle 周期类型
     * @param zoneId 时区（如：ZoneId.of("Asia/Shanghai")）
     * @return 时间范围
     */
    public static TimeRange getCycleTimeRange(String cycle, ZoneId zoneId) {
        LocalDate today = LocalDate.now(zoneId);
        LocalDateTime startTime;
        LocalDateTime endTime;
        CycleType cycleType = CycleType.match(cycle);

        switch (cycleType) {
            case DAILY:
                startTime = today.atStartOfDay();
                endTime = today.atTime(23, 59, 59);
                break;
            case WEEKLY:
                LocalDate monday = today.with(TemporalAdjusters.previousOrSame(WEEK_FIELDS.getFirstDayOfWeek()));
                LocalDate sunday = monday.plusDays(6);
                startTime = monday.atStartOfDay();
                endTime = sunday.atTime(23, 59, 59);
                break;
            case HALF_MONTH:
                int dayOfMonth = today.getDayOfMonth();
                if (dayOfMonth <= 15) {
                    startTime = today.withDayOfMonth(1).atStartOfDay();
                    endTime = today.withDayOfMonth(15).atTime(23, 59, 59);
                } else {
                    startTime = today.withDayOfMonth(16).atStartOfDay();
                    LocalDate lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
                    endTime = lastDayOfMonth.atTime(23, 59, 59);
                }
                break;
            case MONTHLY:
                LocalDate firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth());
                LocalDate lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
                startTime = firstDayOfMonth.atStartOfDay();
                endTime = lastDayOfMonth.atTime(23, 59, 59);
                break;
            default:
                throw new IllegalArgumentException("未实现的周期类型：" + cycleType);
        }

        return new TimeRange(
                startTime.format(DATETIME_FORMATTER),
                endTime.format(DATETIME_FORMATTER)
        );
    }

    // 测试示例
//    public static void main(String[] args) {
//        // 测试1：每天（当前日期：2026-02-10）
//        TimeRange dailyRange = getCycleTimeRange("每天");
//        System.out.println("每天：" + dailyRange); // 输出：开始时间='2026-02-10 00:00:00', 结束时间='2026-02-10 23:59:59'
//
//        // 测试2：每周（假设今天是2026-02-10，周二 → 本周一2026-02-09 到 周日2026-02-15）
//        TimeRange weeklyRange = getCycleTimeRange("每周");
//        System.out.println("每周：" + weeklyRange);
//
//        // 测试3：半月（2026-02-10 属于上半月 → 2026-02-01 到 2026-02-15）
//        TimeRange halfMonthRange = getCycleTimeRange("半月");
//        System.out.println("半月：" + halfMonthRange);
//
//        // 测试4：每月（2026-02月 → 2026-02-01 到 2026-02-28）
//        TimeRange monthlyRange = getCycleTimeRange("每月");
//        System.out.println("每月：" + monthlyRange);
//
//        // 测试5：指定时区（上海时区）
//        TimeRange shanghaiRange = getCycleTimeRange("每天", ZoneId.of("Asia/Shanghai"));
//        System.out.println("每天（上海时区）：" + shanghaiRange);
//    }
}
