package com.sckw.core.utils;


import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;

/**
 * @description: 时间工具类
 * @author: xucaiqin
 * @copyright
 * @create: 2022-01-27 16:04
 **/
public class DateTimeUtil {
    public static final String YMD = "yyyy-MM-dd";
    public static final String YM = "yyyy-MM";
    public static final String HMS = "HH:mm:ss";
    public static final DateTimeFormatter YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern(YMD + " " + HMS);
    public static final DateTimeFormatter YYYYMMDDHHMMSS = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    public static final DateTimeFormatter YYYY_MM_DD = DateTimeFormatter.ofPattern(YMD);
    public static final DateTimeFormatter YYYY_MM = DateTimeFormatter.ofPattern(YM);
    public static final DateTimeFormatter HH_MM_SS = DateTimeFormatter.ofPattern(HMS);

    /**
     * 拼接 00:00:00
     *
     * @param localDate 日期
     * @return yyyy-MM-dd 00:00:00
     */
    public static LocalDateTime appendStart(LocalDate localDate) {
        return LocalDateTime.of(localDate, LocalTime.MIN);
    }

    /**
     * 拼接 23:59:59
     *
     * @param localDate 日期
     * @return yyyy-MM-dd 23:59:59
     */
    public static LocalDateTime appendEnd(LocalDate localDate) {
        return LocalDateTime.of(localDate, LocalTime.MAX);
    }

    public static LocalDateTime parse(String date) {
        return LocalDateTime.parse(date, YYYY_MM_DD_HH_MM_SS);
    }

    public static LocalDate parseYMD(String date) {
        return LocalDate.parse(date, YYYY_MM_DD);
    }
    /*格式化*/

    /**
     * 当前时间的前一个星期
     *
     * @return
     */
    public static String format(LocalDateTime localDateTime) {
        return YYYY_MM_DD_HH_MM_SS.format(localDateTime);
    }

    public static String formatYM(LocalDate localDate) {
        return YYYY_MM.format(localDate);
    }

    public static String formatYMD(LocalDate localDate) {
        return YYYY_MM_DD.format(localDate);
    }

    public static String formatYMD(LocalDateTime localDateTime) {
        return YYYY_MM_DD.format(localDateTime);
    }
    /*月差计算*/

    /**
     * 从当前日期计算月数差
     *
     * @param months 加或减的月数
     * @return LocalDate
     */
    public static LocalDate getComputeMonth(long months) {
        return getComputeMonth(LocalDate.now(), months);
    }

    /**
     * 从当前日期计算月数差
     *
     * @param months 加或减的月数
     * @return yyyy-MM-dd
     */
    public static String getComputeMonthStr(long months) {
        return formatYMD(getComputeMonth(months));
    }

    /**
     * 从给定的日期计算月数差
     *
     * @param months    加或减的月数
     * @param localDate 给定的日期
     * @return LocalDate
     */
    public static LocalDate getComputeMonth(LocalDate localDate, long months) {
        return localDate.plusMonths(months);
    }

    /**
     * 从给定的日期时间计算月数差
     *
     * @param months        加或减的月数
     * @param localDateTime 给定的日期时间
     * @return LocalDate
     */
    public static LocalDateTime getComputeMonth(LocalDateTime localDateTime, long months) {
        return localDateTime.plusMonths(months);
    }

    /**
     * 从当前日期计算月数差,并取当月的第一天
     *
     * @param months 加或减的月数
     * @return LocalDateTime，时间最小值
     */
    public static LocalDate getComputeMonthStartDay(long months) {
        return getComputeMonth(months).with(TemporalAdjusters.firstDayOfMonth());
    }

    /**
     * 获取传入日期的当月第一天
     *
     * @param date 日期（不能包含时分秒）
     * @return
     */
    public static String getComputeMonthStartDayStr(String date) {
        return formatYMD(parseYMD(date).with(TemporalAdjusters.firstDayOfMonth()));
    }

    public static String getComputeMonthStartDayStr(long months) {
        return formatYMD(getComputeMonth(months).with(TemporalAdjusters.firstDayOfMonth()));
    }

    /**
     * 从当前日期计算月数差,时间取最小值 00:00:00
     *
     * @param months 加或减的月数
     * @param offset 偏移的天数 ±1
     * @return LocalDateTime，时间最小值
     */
    public static LocalDateTime getComputeMonthStart(long months, long offset) {
        return LocalDateTime.of(getComputeMonth(months), LocalTime.MIN).plusDays(offset);
    }

    /**
     * 从当前日期计算月数差,时间取最大值 23:59:59
     *
     * @param months 加或减的月数
     * @param offset 偏移的天数 ±1
     * @return LocalDateTime，时间最大值
     */
    public static LocalDateTime getComputeMonthEnd(long months, long offset) {
        return LocalDateTime.of(getComputeMonth(months), LocalTime.MAX).plusDays(offset);
    }

    /**
     * 获取传入日期的当月最后一天
     *
     * @param date
     * @return
     */
    public static String getComputeMonthEndDayStr(String date) {
        return formatYMD(parseYMD(date).with(TemporalAdjusters.lastDayOfMonth()));
    }

    public static String getComputeMonthEndDayStr(long months) {
        return formatYMD(getComputeMonth(months).with(TemporalAdjusters.lastDayOfMonth()));
    }

    /**
     * 从当前日期计算月数差,并取当月的最后一天
     *
     * @param months 加或减的月数
     * @return LocalDateTime，时间最小值
     */
    public static LocalDate getComputeMonthEndDay(long months) {
        return getComputeMonth(months).with(TemporalAdjusters.lastDayOfMonth());
    }
    /*天差计算*/

    /**
     * 从当前时间，计算天数差
     *
     * @param days 加或减的天数
     * @return yyyy-MM-dd
     */
    public static String getComputeDaysStr(long days) {
        return formatYMD(getComputeDays(days));
    }

    /**
     * 从当前时间，计算天数差
     *
     * @param days 加或减的天数
     * @return LocalDate
     */
    public static LocalDate getComputeDays(long days) {
        return getComputeDays(LocalDate.now(), days);
    }

    /**
     * 从给定的日期计算天数差
     *
     * @param days      加或减的天数
     * @param localDate 给定的日期
     * @return LocalDate
     */
    public static LocalDate getComputeDays(LocalDate localDate, long days) {
        return localDate.plusDays(days);
    }

    /**
     * 从给定日期时间计算天数差
     *
     * @param days          加或减的天数
     * @param localDateTime 给定的日期时间
     * @return LocalDate
     */
    public static LocalDateTime getComputeDays(LocalDateTime localDateTime, long days) {
        return localDateTime.plusDays(days);
    }


    /**
     * 从当前时间，计算天数差
     *
     * @param days 加或减的天数
     * @return LocalDateTime，时间最小值
     */
    public static LocalDateTime getComputeDaysStart(long days) {
        return LocalDateTime.of(getComputeDays(days), LocalTime.MIN);
    }

    /**
     * 从当前时间，计算天数差
     *
     * @param days 加或减的天数
     * @return LocalDateTime，时间最大值
     */
    public static LocalDateTime getComputeDaysEnd(long days) {
        return LocalDateTime.of(getComputeDays(days), LocalTime.MAX);
    }

    /**
     * 今天开始时间
     *
     * @return LocalDateTime yyyy-MM-dd 00:00:00
     */
    public static LocalDateTime todayStart() {
        return LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
    }

    /**
     * 今天结束时间
     *
     * @return LocalDateTime yyyy-MM-dd 23:59:59
     */
    public static LocalDateTime todayEnd() {
        return LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
    }


    public static List<String> generateDateRange(LocalDate startDate, LocalDate endDate) {
        List<String> dateRange = new ArrayList<>();
        LocalDate currentDate = startDate;

        while (!currentDate.isAfter(endDate)) {
            dateRange.add(formatYMD(currentDate));
            currentDate = currentDate.plus(1, ChronoUnit.DAYS); // 增加一天
        }
        return dateRange;
    }

    /**
     * 根据开始时间结束时间 格式化时间范围内的时间
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static List<String> generateMonthRange(LocalDate startDate, LocalDate endDate) {
        List<String> dateRange = new ArrayList<>();
        LocalDate currentDate = startDate;

        while (!currentDate.isAfter(endDate)) {
            dateRange.add(formatYM(currentDate));
            currentDate = currentDate.plus(1, ChronoUnit.MONTHS);
        }
        return dateRange;
    }

    /**
     * 获取当前时间到次日00:00剩余多少秒
     *
     * @return
     */
    public static long getTime() {
        // 当前时间
        LocalDateTime now = LocalDateTime.now();
        // 次日 00:00
        LocalDateTime nextMidnight = now.plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
        // 转换为毫秒数并计算差值
        return (nextMidnight.toInstant(ZoneOffset.of("+8")).toEpochMilli()
                - now.toInstant(ZoneOffset.of("+8")).toEpochMilli()) / 1000;
    }

    public static void main(String[] args) {

        System.out.println(parse("2023-12-11"));
        System.out.println(getComputeMonthEndDayStr(0));
    }
}
