package com.sckw.core.utils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * @author xucaiqin
 * @date 2026-01-08 16:04:06
 */
public class DateUtil {
    // 默认日期格式
    private static final String DEFAULT_PATTERN = "yyyy-MM-dd";

    /**
     * 获取当前时间往前推7天的日期字符串数组（包含今天）
     * 格式：yyyy-MM-dd
     *
     * @return 日期字符串数组，从最早日期到最新日期排序
     */
    public static String[] getLast7Days() {
        return getLast7Days(DEFAULT_PATTERN);
    }

    /**
     * 获取当前时间往前推7天的日期字符串数组（包含今天）
     *
     * @param pattern 日期格式，如："yyyy-MM-dd", "yyyy/MM/dd", "yyyy年MM月dd日"
     * @return 日期字符串数组，从最早日期到最新日期排序
     */
    public static String[] getLast7Days(String pattern) {
        return getLastNDays(7, pattern);
    }

    /**
     * 获取指定时间范围内的所有日期（包含开始和结束日期）
     *
     * @param startDate 开始日期，格式：yyyy-MM-dd
     * @param endDate   结束日期，格式：yyyy-MM-dd
     * @return 日期字符串列表
     */
    public static List<String> getDateRange(String startDate, String endDate) {
        return getDateRange(startDate, endDate, "yyyy-MM-dd");
    }

    /**
     * 获取指定时间范围内的所有日期（包含开始和结束日期）
     *
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @param pattern   日期格式
     * @return 日期字符串列表
     */
    public static List<String> getDateRange(String startDate, String endDate, String pattern) {
        List<String> dates = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);

        LocalDate start = LocalDate.parse(startDate, formatter);
        LocalDate end = LocalDate.parse(endDate, formatter);

        while (!start.isAfter(end)) {
            dates.add(start.format(formatter));
            start = start.plusDays(1);
        }

        return dates;
    }

    private static final DateTimeFormatter INPUT_FORMATTER =
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private static final DateTimeFormatter OUTPUT_FORMATTER =
            DateTimeFormatter.ofPattern("HH:mm");

    /**
     * 生成整点时间段数组（只按小时统计，忽略分钟和秒）
     *
     * @param startDateTime 开始时间，格式：2025-01-01 00:00:00
     * @param endDateTime   结束时间，格式：2025-01-01 12:00:59
     * @return 整点时间段列表，如 ["00:00-01:00", "01:00-02:00"]
     */
    public static List<String> generateHourRanges(
            String startDateTime,
            String endDateTime) {

        // 1. 解析输入的时间字符串
        LocalDateTime start = LocalDateTime.parse(startDateTime, INPUT_FORMATTER);
        LocalDateTime end = LocalDateTime.parse(endDateTime, INPUT_FORMATTER);

        // 2. 验证参数
        if (end.isBefore(start)) {
            throw new IllegalArgumentException("结束时间不能早于开始时间");
        }

        // 3. 生成时间段（按小时间隔）
        List<String> timeRanges = new ArrayList<>();

        // 从开始时间的小时开始
        LocalDateTime current = start.withMinute(0).withSecond(0);

        // 确保当前时间不大于结束时间
        while (!current.isAfter(end)) {
            LocalDateTime nextHour = current.plusHours(1);

            // 如果下一个小时已经超过了结束时间，停止生成
            if (nextHour.isAfter(end)) {
                break;
            }

            // 格式化为时间段：HH:mm-HH:mm
            String range = current.format(OUTPUT_FORMATTER) +
                    "-" +
                    nextHour.format(OUTPUT_FORMATTER);
            timeRanges.add(range);

            // 移动到下一个小时
            current = nextHour;
        }

        return timeRanges;
    }

    /**
     * 重载方法：生成整点时间段，可以指定是否包含边界小时
     *
     * @param startDateTime      开始时间
     * @param endDateTime        结束时间
     * @param includePartialHour 是否包含部分小时（即使分钟秒数不为0）
     * @return 时间段列表
     */
    public static List<String> generateHourRanges(
            String startDateTime,
            String endDateTime,
            boolean includePartialHour) {

        if (!includePartialHour) {
            return generateHourRanges(startDateTime, endDateTime);
        }

        // 如果包含部分小时，生成所有小时段，不考虑分钟和秒
        LocalDateTime start = LocalDateTime.parse(startDateTime, INPUT_FORMATTER);
        LocalDateTime end = LocalDateTime.parse(endDateTime, INPUT_FORMATTER);

        if (end.isBefore(start)) {
            throw new IllegalArgumentException("结束时间不能早于开始时间");
        }

        List<String> timeRanges = new ArrayList<>();
        LocalDateTime current = start.withMinute(0).withSecond(0);

        // 处理结束时间的小时
        int endHour = end.getHour();

        while (current.getHour() <= endHour && !current.isAfter(end)) {
            int currentHour = current.getHour();
            int nextHour = (currentHour + 1) % 24;

            // 判断是否是跨天的情况
            String nextHourStr = String.format("%02d:00", nextHour);
            if (nextHour == 0) {
                nextHourStr = "00:00";
            }

            String range = String.format("%02d:00-%s", currentHour, nextHourStr);
            timeRanges.add(range);

            current = current.plusHours(1);
        }

        return timeRanges;
    }

    /**
     * 获取当前时间往前推N天的日期字符串数组（包含今天）
     *
     * @param n       天数
     * @param pattern 日期格式
     * @return 日期字符串数组，从最早日期到最新日期排序
     */
    public static String[] getLastNDays(int n, String pattern) {
        if (n <= 0) {
            throw new IllegalArgumentException("天数必须大于0");
        }

        if (pattern == null || pattern.trim().isEmpty()) {
            pattern = DEFAULT_PATTERN;
        }

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        LocalDate today = LocalDate.now();
        List<String> dateList = new ArrayList<>();

        // 从6天前到今天，共7天
        for (int i = n - 1; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            dateList.add(date.format(formatter));
        }

        return dateList.toArray(new String[0]);
    }

    /**
     * 获取当前时间往前推7天的日期字符串数组（不包含今天）
     *
     * @param pattern 日期格式
     * @return 日期字符串数组，从最早日期到最新日期排序
     */
    public static String[] getLast7DaysExcludeToday(String pattern) {
        if (pattern == null || pattern.trim().isEmpty()) {
            pattern = DEFAULT_PATTERN;
        }

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        LocalDate today = LocalDate.now();
        List<String> dateList = new ArrayList<>();

        // 从7天前到昨天，共7天
        for (int i = 7; i >= 1; i--) {
            LocalDate date = today.minusDays(i);
            dateList.add(date.format(formatter));
        }

        return dateList.toArray(new String[0]);
    }

    /**
     * 获取当前时间往前推7天的日期对象数组
     *
     * @return LocalDate数组，从最早日期到最新日期排序
     */
    public static LocalDate[] getLast7DaysAsLocalDate() {
        return getLastNDaysAsLocalDate(7);
    }

    /**
     * 获取当前时间往前推N天的日期对象数组
     *
     * @param n 天数
     * @return LocalDate数组，从最早日期到最新日期排序
     */
    public static LocalDate[] getLastNDaysAsLocalDate(int n) {
        if (n <= 0) {
            throw new IllegalArgumentException("天数必须大于0");
        }

        LocalDate today = LocalDate.now();
        LocalDate[] dateArray = new LocalDate[n];

        for (int i = 0; i < n; i++) {
            dateArray[i] = today.minusDays(n - 1 - i);
        }

        return dateArray;
    }

    public static void main(String[] args) {
        // 测试1：完整的小时
        System.out.println("\n1. 完整小时段:");
        List<String> result1 = generateHourRanges("2025-01-01 00:00:00", "2025-01-01 12:00:00");
        System.out.println(result1);

        // 测试2：分钟秒数不为0的情况（应该忽略）
        System.out.println("\n2. 非整点时间:");
        List<String> result2 = generateHourRanges("2025-01-01 00:30:45", "2025-01-01 12:15:59");
        System.out.println(result2);

        // 测试3：开始和结束时间都不在整点
        System.out.println("\n3. 非整点开始和结束:");
        List<String> result3 = generateHourRanges("2025-01-01 01:15:30", "2025-01-01 04:45:20");
        System.out.println(result3);

        // 测试4：跨天情况
        System.out.println("\n4. 跨天情况:");
        List<String> result4 = generateHourRanges("2025-01-01 22:30:00", "2025-01-02 02:15:00");
        System.out.println(result4);

        // 测试5：包含部分小时的版本
        System.out.println("\n5. 包含部分小时:");
        List<String> result5 = generateHourRanges("2025-01-01 01:15:30", "2025-01-01 04:45:20", true);
        System.out.println(result5);
    }
}
