package com.zcloud.safetyDutyList.domain.util;

import java.time.LocalDate;
import java.time.LocalDateTime;

/**
 * 反馈周期工具类
 * <p>
 * 提供反馈周期相关的计算功能，包括：
 *   1. 根据周期标识解析对应的起止时间
 *   2. 根据反馈周期类型生成当前周期标识
 *   3. 根据反馈周期类型生成上一阶段周期标识（用于异常检测）
 *   4. 判断是否为当前周期
 * <p>
 * 周期标识格式说明：
 *   每月：   "2026-05"  （年-月）
 *   每季度： "2026-Q1"  （年-季度，Q1=1-3月，Q2=4-6月，Q3=7-9月，Q4=10-12月）
 *   每半年： "2026-H1"  （年-半年，H1=1-6月，H2=7-12月）
 *   每年：   "2026-Y"   （年-Y）
 */
public class FeedbackCycleUtil {

    /**
     * 根据周期标识获取对应的起止时间
     * <p>
     * 根据周期标识的格式自动识别周期类型，返回该周期的起始时间和结束时间。
     * 起始时间为该周期第一天的00:00:00，结束时间为该周期最后一天的23:59:59。
     *
     * @param periodFlag 周期标识（如"2026-05"、"2026-Q1"、"2026-H1"、"2026-Y"）
     * @return 长度为2的LocalDateTime数组，[0]=起始时间，[1]=结束时间；若无法识别则返回null
     */
    public static LocalDateTime[] getPeriodTime(String periodFlag) {
        if (periodFlag == null || periodFlag.isEmpty()) {
            return null;
        }
        if (periodFlag.contains("-Q")) {
            return getQuarterPeriod(periodFlag);
        } else if (periodFlag.contains("-H")) {
            return getHalfYearPeriod(periodFlag);
        } else if (periodFlag.contains("-Y")) {
            return getYearPeriod(periodFlag);
        } else if (periodFlag.contains("-") && periodFlag.length() == 7) {
            return getMonthPeriod(periodFlag);
        }
        return null;
    }

    /**
     * 解析月度周期的起止时间
     * <p>
     * 例如："2026-05" -> [2026-05-01 00:00:00, 2026-05-31 23:59:59]
     *
     * @param periodFlag 月度周期标识（格式："yyyy-MM"）
     * @return 起止时间数组
     */
    private static LocalDateTime[] getMonthPeriod(String periodFlag) {
        String[] parts = periodFlag.split("-");
        int year = Integer.parseInt(parts[0]);
        int month = Integer.parseInt(parts[1]);
        LocalDateTime start = LocalDateTime.of(year, month, 1, 0, 0, 0);
        LocalDateTime end = LocalDateTime.of(year, month, LocalDate.of(year, month, 1).lengthOfMonth(), 23, 59, 59);
        return new LocalDateTime[]{start, end};
    }

    /**
     * 解析季度周期的起止时间
     * <p>
     * 季度与自然月的对应关系：
     *   Q1 = 1-3月，Q2 = 4-6月，Q3 = 7-9月，Q4 = 10-12月
     * <p>
     * 例如："2026-Q2" -> [2026-04-01 00:00:00, 2026-06-30 23:59:59]
     *
     * @param periodFlag 季度周期标识（格式："yyyy-Qn"）
     * @return 起止时间数组
     */
    private static LocalDateTime[] getQuarterPeriod(String periodFlag) {
        String[] parts = periodFlag.split("-Q");
        int year = Integer.parseInt(parts[0]);
        int quarter = Integer.parseInt(parts[1]);
        int startMonth = (quarter - 1) * 3 + 1;
        int endMonth = startMonth + 2;
        LocalDateTime start = LocalDateTime.of(year, startMonth, 1, 0, 0, 0);
        LocalDateTime end = LocalDateTime.of(year, endMonth, LocalDate.of(year, endMonth, 1).lengthOfMonth(), 23, 59, 59);
        return new LocalDateTime[]{start, end};
    }

    /**
     * 解析半年周期的起止时间
     * <p>
     * 半年与自然月的对应关系：
     *   H1 = 1-6月（上半年），H2 = 7-12月（下半年）
     * <p>
     * 例如："2026-H1" -> [2026-01-01 00:00:00, 2026-06-30 23:59:59]
     *
     * @param periodFlag 半年周期标识（格式："yyyy-Hn"）
     * @return 起止时间数组
     */
    private static LocalDateTime[] getHalfYearPeriod(String periodFlag) {
        String[] parts = periodFlag.split("-H");
        int year = Integer.parseInt(parts[0]);
        int half = Integer.parseInt(parts[1]);
        int startMonth = (half - 1) * 6 + 1;
        int endMonth = startMonth + 5;
        LocalDateTime start = LocalDateTime.of(year, startMonth, 1, 0, 0, 0);
        LocalDateTime end = LocalDateTime.of(year, endMonth, LocalDate.of(year, endMonth, 1).lengthOfMonth(), 23, 59, 59);
        return new LocalDateTime[]{start, end};
    }

    /**
     * 解析年度周期的起止时间
     * <p>
     * 例如："2026-Y" -> [2026-01-01 00:00:00, 2026-12-31 23:59:59]
     *
     * @param periodFlag 年度周期标识（格式："yyyy-Y"）
     * @return 起止时间数组
     */
    private static LocalDateTime[] getYearPeriod(String periodFlag) {
        String yearStr = periodFlag.replace("-Y", "");
        int year = Integer.parseInt(yearStr);
        LocalDateTime start = LocalDateTime.of(year, 1, 1, 0, 0, 0);
        LocalDateTime end = LocalDateTime.of(year, 12, 31, 23, 59, 59);
        return new LocalDateTime[]{start, end};
    }

    /**
     * 根据反馈周期类型生成当前周期标识
     * <p>
     * 周期标识格式：
     *   feedbackCycle=1（每月）：   "2026-05"
     *   feedbackCycle=2（每季度）： "2026-Q1"
     *   feedbackCycle=3（每半年）： "2026-H1"
     *   feedbackCycle=4（每年）：   "2026-Y"
     *
     * @param feedbackCycle 反馈周期类型（1-每月，2-每季度，3-每半年，4-每年）
     * @param time          参考时间，若为null则使用当前时间
     * @return 当前周期标识，若周期类型不合法则返回null
     */
    public static String generatePeriodFlag(Integer feedbackCycle, LocalDateTime time) {
        if (time == null) {
            time = LocalDateTime.now();
        }
        int year = time.getYear();
        switch (feedbackCycle) {
            case 1:
                return String.format("%d-%02d", year, time.getMonthValue());
            case 2:
                int quarter = (time.getMonthValue() - 1) / 3 + 1;
                return String.format("%d-Q%d", year, quarter);
            case 3:
                int half = time.getMonthValue() <= 6 ? 1 : 2;
                return String.format("%d-H%d", year, half);
            case 4:
                return String.format("%d-Y", year);
            default:
                return null;
        }
    }

    /**
     * 根据反馈周期类型生成上一阶段周期标识
     * <p>
     * 用于反馈异常检测，在每月1日执行定时任务时，需要判断上一个阶段是否有反馈。
     * <p>
     * 各周期类型的"上一阶段"计算规则：
     *   feedbackCycle=1（每月）：   上个月，如当前2026-05则返回"2026-04"
     *   feedbackCycle=2（每季度）： 上个季度，如当前Q1则返回上年Q4，当前Q2则返回当年Q1
     *   feedbackCycle=3（每半年）： 上个半年，如当前H1则返回上年H2，当前H2则返回当年H1
     *   feedbackCycle=4（每年）：   去年，如当前2026-Y则返回"2025-Y"
     *
     * @param feedbackCycle 反馈周期类型（1-每月，2-每季度，3-每半年，4-每年）
     * @return 上一阶段周期标识，若周期类型不合法则返回null
     */
    public static String generatePreviousPeriodFlag(Integer feedbackCycle) {
        LocalDateTime now = LocalDateTime.now();
        switch (feedbackCycle) {
            case 1:
                LocalDateTime lastMonth = now.minusMonths(1);
                return String.format("%d-%02d", lastMonth.getYear(), lastMonth.getMonthValue());
            case 2:
                int currentQuarter = (now.getMonthValue() - 1) / 3 + 1;
                if (currentQuarter == 1) {
                    return String.format("%d-Q4", now.getYear() - 1);
                } else {
                    return String.format("%d-Q%d", now.getYear(), currentQuarter - 1);
                }
            case 3:
                int currentHalf = now.getMonthValue() <= 6 ? 1 : 2;
                if (currentHalf == 1) {
                    return String.format("%d-H2", now.getYear() - 1);
                } else {
                    return String.format("%d-H1", now.getYear());
                }
            case 4:
                return String.format("%d-Y", now.getYear() - 1);
            default:
                return null;
        }
    }

    /**
     * 判断当前时间是否仍处于清单的首个反馈周期内
     * <p>
     * 用于反馈异常检测定时任务，判断是否应该检查上一周期的反馈情况。
     * 如果当前时间仍处于清单的首个反馈周期内，说明该周期尚未结束，不应检测异常；
     * 只有当首个反馈周期已结束，进入第二个或之后的周期时，才需要检测上一周期。
     * <p>
     * 判断方式：根据清单周期起始时间生成"首周期标识"，根据当前时间生成"当前周期标识"，
     * 若两者相同则说明仍在首周期内，应跳过检测。
     * <p>
     * 示例（清单周期起始时间为2026年7月，当前时间为2026年7月12日）：
     *   每月→首周期=2026-07，当前=2026-07 → 相同 → 跳过
     *   每季度→首周期=2026-Q3，当前=2026-Q3 → 相同 → 跳过
     *   每半年→首周期=2026-H2，当前=2026-H2 → 相同 → 跳过
     *   每年→首周期=2026-Y，当前=2026-Y → 相同 → 跳过
     * <p>
     * 示例（清单周期起始时间为2026年7月，当前时间为2026年8月1日）：
     *   每月→首周期=2026-07，当前=2026-08 → 不同 → 检查2026-07
     *   每季度→首周期=2026-Q3，当前=2026-Q3 → 相同 → 跳过
     *   每半年→首周期=2026-H2，当前=2026-H2 → 相同 → 跳过
     *   每年→首周期=2026-Y，当前=2026-Y → 相同 → 跳过
     *
     * @param feedbackCycle   反馈周期类型（1-每月，2-每季度，3-每半年，4-每年）
     * @param periodStartTime 清单周期起始时间
     * @return true-仍在首周期内应跳过检测，false-首周期已结束应检测上一周期
     */
    public static boolean isFirstCycle(Integer feedbackCycle, LocalDateTime periodStartTime) {
        if (periodStartTime == null) {
            return true;
        }
        String firstCycleFlag = generatePeriodFlag(feedbackCycle, periodStartTime);
        String currentCycleFlag = generatePeriodFlag(feedbackCycle, LocalDateTime.now());
        return firstCycleFlag != null && firstCycleFlag.equals(currentCycleFlag);
    }

    /**
     * 判断给定周期标识是否为当前周期
     * <p>
     * 通过生成当前周期标识与传入的周期标识进行比较。
     *
     * @param feedbackCycle 反馈周期类型（1-每月，2-每季度，3-每半年，4-每年）
     * @param periodFlag    待判断的周期标识
     * @return true-为当前周期，false-不是当前周期
     */
    public static boolean isCurrentPeriod(Integer feedbackCycle, String periodFlag) {
        String currentFlag = generatePeriodFlag(feedbackCycle, LocalDateTime.now());
        return currentFlag != null && currentFlag.equals(periodFlag);
    }
}
