package org.dromara.payment.util;

import cn.hutool.core.lang.Assert;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 */
public class DateTimeUtil {

    public static final DateTimeFormatter YYYY_MM_DD_HH_MM_SS_SSS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS");

    public static final DateTimeFormatter YYYY_MM_DD_HH_MM_SS2 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");


    public static final DateTimeFormatter YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static final DateTimeFormatter YYYYMMDDHHMMSS = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    public static final DateTimeFormatter YYYYMMDDHH = DateTimeFormatter.ofPattern("yyyyMMddHH");

    public static final DateTimeFormatter YYYYMMDD = DateTimeFormatter.ofPattern("yyyyMMdd");

    public static final DateTimeFormatter YYYY_MM_DD_HH = DateTimeFormatter.ofPattern("yyyy-MM-dd HH");
    public static final DateTimeFormatter YYYY_MM_DD = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter MM_DD = DateTimeFormatter.ofPattern("MM月dd日");
    public static final DateTimeFormatter YYYY = DateTimeFormatter.ofPattern("yyyy");
    public static final DateTimeFormatter MM = DateTimeFormatter.ofPattern("MM");
    public static final DateTimeFormatter HH = DateTimeFormatter.ofPattern("HH");
    public static final DateTimeFormatter YYYY_MM = DateTimeFormatter.ofPattern("yyyy年MM月");

    /**
     * Date转换为LocalDateTime
     *
     * @param date 日期
     * @return LocalDateTime
     */
    public static LocalDateTime toLocalDateTime(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    /**
     * LocalDateTime转换为Date
     *
     * @param dateTime 日期时间
     * @return Date
     */
    public static Date toDate(LocalDateTime dateTime) {
        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取指定格式的指定时间
     *
     * @param dateTime 日期时间
     * @param pattern  指定格式
     * @return 指定格式的日期时间字符串
     */
    public static String formatTime(LocalDateTime dateTime, String pattern) {
        return dateTime.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 获取指定格式的当前时间
     *
     * @param pattern 指定格式
     * @return 指定格式的当前时间日期字符串
     */
    public static String formatNow(String pattern) {
        return formatTime(LocalDateTime.now(), pattern);
    }

    /**
     * 判断dateTime1是否早于dateTime2
     *
     * @param dateTime1 日期时间1
     * @param dateTime2 日期时间2
     * @return 判断结果
     */
    public static boolean isBefore(LocalDateTime dateTime1, LocalDateTime dateTime2) {
        return dateTime1.isBefore(dateTime2);
    }

    /**
     * 判断dateTime1与dateTime2是否是同一时间
     *
     * @param dateTime1 日期时间1
     * @param dateTime2 日期时间2
     * @return 判断结果
     */
    public static boolean isEqual(LocalDateTime dateTime1, LocalDateTime dateTime2) {
        return dateTime1.isEqual(dateTime2);
    }

    /**
     * 判断dateTime1是否晚于dateTime2
     *
     * @param dateTime1 日期时间1
     * @param dateTime2 日期时间2
     * @return 判断结果
     */
    public static boolean isAfter(LocalDateTime dateTime1, LocalDateTime dateTime2) {
        return dateTime1.isAfter(dateTime2);
    }

    /**
     * 获取指定日期的毫秒
     *
     * @param dateTime 日期时间
     * @return 毫秒
     */
    public static Long getMilliByTime(LocalDateTime dateTime) {
        return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 获取指定日期的秒
     *
     * @param dateTime 日期时间
     * @return 秒
     */
    public static Long getSecondsByTime(LocalDateTime dateTime) {
        return dateTime.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
    }

    /**
     * 日期加上一个数，根据field不同加不同值
     *
     * @param dateTime 日期时间
     * @param number   数值
     * @param field    单位
     * @return 已添加数值后的日期时间
     */
    public static LocalDateTime plus(LocalDateTime dateTime, long number, ChronoUnit field) {
        return dateTime.plus(number, field);
    }

    /**
     * 日期减去一个数，根据field不同减不同值
     *
     * @param dateTime 日期时间
     * @param number   数值
     * @param field    单位
     * @return 已减少数值后的日期时间
     */
    public static LocalDateTime minus(LocalDateTime dateTime, long number, ChronoUnit field) {
        return dateTime.minus(number, field);
    }

    /**
     * 获取两个日期的差
     *
     * @param startDateTime 开始时间
     * @param endDateTime   结束时间
     * @param field         单位
     * @return 两个日期之间的差值
     */
    public static long between(LocalDateTime startDateTime, LocalDateTime endDateTime, ChronoUnit field) {
        Period period = Period.between(LocalDate.from(startDateTime), LocalDate.from(endDateTime));
        if (field == ChronoUnit.YEARS) return  ChronoUnit.YEARS.between(startDateTime.toLocalDate(), endDateTime.toLocalDate());
        if (field == ChronoUnit.MONTHS) return  ChronoUnit.MONTHS.between(startDateTime.toLocalDate(), endDateTime.toLocalDate());
        if (field == ChronoUnit.DAYS) return  ChronoUnit.DAYS.between(startDateTime.toLocalDate(), endDateTime.toLocalDate());
        if (field == ChronoUnit.HOURS) return Duration.between(startDateTime, endDateTime).toHours();
        return field.between(startDateTime, endDateTime);
    }

    /**
     * 获取某天的开始时间，例如：yyyy,MM,dd 00:00
     *
     * @param dateTime 某天的日期时间
     * @return 某天的开始时间
     */
    public static LocalDateTime getDayStart(LocalDateTime dateTime) {
        return dateTime.withHour(1)
                .withMinute(0)
                .withSecond(0)
                .withNano(0);
    }

    /**
     * 获取某天的开始时间，例如：yyyy,MM,dd 00:00
     *
     * @return 某天的开始时间
     */
    public static LocalDateTime getNOwDayStart() {
        return LocalDateTime.now().withHour(0)
                .withMinute(0)
                .withSecond(0)
                .withNano(0);
    }

    /**
     * 获取某天的结束时间，例如：yyy,MM,dd 23:59:59
     *
     * @param dateTime 某天的日期时间
     * @return 某天的结束时间
     */
    public static LocalDateTime getDayEnd(LocalDateTime dateTime) {
        return dateTime.withHour(23)
                .withMinute(59)
                .withSecond(59);
    }

    /**
     * 将字符串转日期成Long类型的时间戳，格式为：yyyy-MM-dd HH:mm:ss
     */
    public static Long timeToLong(String time) {
        Assert.notNull(time, "time is null");
        DateTimeFormatter formatString = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime parse = LocalDateTime.parse(time, formatString);
        return LocalDateTime.from(parse).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 将字符串转日期成Long类型的时间戳，格式为：yyyy-MM-dd HH:mm:ss
     */
    public static String zonedDateTimeToString(ZonedDateTime zonedDateTime) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return zonedDateTime.format(formatter);
    }


    /**
     * 获取时间段内的时间列表
     *
     * @param startTime
     * @param endTime
     * @param dataType
     * @return
     */
    public static List<String> getDateList(String startTime, String endTime, Integer dataType, DateTimeFormatter dateTimeFormatter) {
        List<String> result = new LinkedList<>();
        while (endTime.compareTo(startTime) >= 0) {
            LocalDateTime localDateStartTime = LocalDateTime.parse(startTime, YYYY_MM_DD_HH_MM_SS);
            result.add(localDateStartTime.format(dateTimeFormatter));
            if (dataType == 4) {
                localDateStartTime = localDateStartTime.plusHours(1);
            } else if (dataType == 3) {
                localDateStartTime = localDateStartTime.plusDays(1);
            } else if (dataType == 2) {
                localDateStartTime = localDateStartTime.plusMonths(1);
            } else if (dataType == 1) {
                localDateStartTime = localDateStartTime.plusYears(1);
            }
            startTime = localDateStartTime.format(YYYY_MM_DD_HH_MM_SS);
        }
        return result;
    }

    public static String getPreviousMonthSameTime(String dateString) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime dateTime = LocalDateTime.parse(dateString, formatter);
        LocalDate date = dateTime.toLocalDate();
        int year = date.getYear();
        int month = date.getMonthValue() - 1;
        if (month == 0) {
            year--;
            month = 12; // December
        }
        int day = date.getDayOfMonth();
        int hour = dateTime.getHour();
        int minute = dateTime.getMinute();
        int second = dateTime.getSecond();
        LocalDateTime prevMonthSameTime = LocalDateTime.of(year, month, day, hour, minute, second);
        String formattedString = prevMonthSameTime.format(formatter);
        return formattedString;
    }


    /**
     * 获取时间段内的时间列表
     *
     * @param startTime
     * @param endTime
     * @param dataType
     * @return
     */
    public static List<String> getDateList(LocalDateTime startTime, LocalDateTime endTime, Integer dataType, DateTimeFormatter dateTimeFormatter) {
        List<String> result = new LinkedList<>();
        while (endTime.compareTo(startTime) >= 0) {
            result.add(startTime.format(dateTimeFormatter));
            if (dataType == 4) {
                startTime = startTime.plusHours(1);
            } else if (dataType == 3) {
                startTime = startTime.plusDays(1);
            } else if (dataType == 2) {
                startTime = startTime.plusMonths(1);
            } else if (dataType == 1) {
                startTime = startTime.plusYears(1);
            }
        }
        return result;
    }

    /**
     * 获取季度
     *
     * @param dataTime
     * @return
     */
    public static String getQuarter(LocalDateTime dataTime) {
        int year = dataTime.getYear();
        int quarter = (dataTime.getMonthValue() - 1) / 3 + 1;
        if (quarter == 1) {
            return "第一季度";
        } else if (quarter == 2) {
            return "第二季度";
        } else if (quarter == 3) {
            return "第三季度";
        } else if (quarter == 4) {
            return "第四季度";
        }
        return null;
    }
}
