package com.sckw.core.utils;

import cn.hutool.core.date.DateUtil;
import com.sckw.core.exception.BusinessException;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;


/**
 * 日期处理
 *
 * @author
 */
public class DateUtils extends DateUtil {
    /**
     * 时间格式(yyyy-MM-dd)
     */
    public final static String DATE_PATTERN = "yyyy-MM-dd";
    /**
     * 时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    public static String FORMAT2 = "yyyy-MM-dd HH:mm:ss";

    public static String FORMAT3 = "yyyyMMddHHmmss";

    public static String FORMAT4 = "yyMMddHHmmss";

    public static String FORMAT5 = "yyMMddHHmmssSSS";

    public static String FORMAT6 = "yyyyMMdd";

    public static String FORMAT7 = "yyyy-MM-dd HH:mm";

    public static String FORMAT8 = "yyMMdd";

    public static String FORMAT9 = "yyyy/MM/dd";

    public static String FORMAT10 = "yyyy-MM";

    public static int THIRTEEN = 13;

    /**
     * 获取时间
     *
     * @return 返回当前时间
     */
    public static Date getDate() {
        return new Date();
    }

    public static String getCurrentTime() {
        Date day = new Date();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(df.format(day));
        return df.format(day);
    }

    public static String getCurrentTime(String format) {
        Date day = new Date();
        SimpleDateFormat df = new SimpleDateFormat(format);
        System.out.println(df.format(day));
        return df.format(day);
    }

    /**
     * 获取时间
     *
     * @param timeStamp 时间戳
     * @return Date
     */
    public static Date getDate(Long timeStamp) {
        if (timeStamp == null || timeStamp <= 0) {
            return null;
        }
        return new Date(timeStamp);
    }

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date 日期
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd HH:mm:ss
     *
     * @param date 日期
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String formatV1(Date date) {
        return format(date, DATE_TIME_PATTERN);
    }

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date    日期
     * @param pattern 格式，如：DateUtils.DATE_TIME_PATTERN
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String format(Date date, String pattern) {
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }


    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date 日期
     * @return 返回yyMMdd格式日期
     */
    public static Date formatDate(String date) {
        try {
            if (date != null) {
                SimpleDateFormat df = new SimpleDateFormat(DATE_TIME_PATTERN);
                return df.parse(date);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date 日期
     * @return 返回yyMMdd格式日期
     */
    public static String formatDate(Date date) {
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(FORMAT8);
            return df.format(date);
        }
        return null;
    }


    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param expireDate 日期
     * @return 返回yyMMdd格式日期
     */
    public static String formatDateToYYMMDD(Date expireDate) {
        if (expireDate != null) {
            String str = new SimpleDateFormat("yyMMdd").format(expireDate);
            return str;
        }
        return null;
    }

    /**
     * @param date
     * @return String    返回类型
     * @Title: getYear
     * @Description: TODO(获取YYYY格式)
     */
    public static String getYear(Date date) {
        return format(date, "yyyy");
    }

    /**
     * @param date
     * @return String    返回类型
     * @Title: getMonth
     * @Description: 获取月(获取MM格式)
     */
    public static String getMonth(Date date) {
        return format(date, "MM");
    }

    /**
     * @param date
     * @return String    返回类型
     * @Title: getTheDay
     * @Description: 获取日期的天(dd格式)
     */
    public static String getTheDay(Date date) {
        return format(date, "dd");
    }

    /**
     * 方法描述：将时间转换为制定格式的日期时间字符串
     *
     * @param date
     * @return
     */
    public static String dateToString(Date date, String pattern) {
        SimpleDateFormat df;
        String returnValue = "";

        if (date != null) {
            df = new SimpleDateFormat(pattern);
            returnValue = df.format(date);
        }
        return (returnValue);
    }

    /**
     * @param beginDateStr
     * @param endDateStr
     * @return long    返回类型
     * @Title: getDaySub
     * @Description: TODO(功能描述 ： 时间相减得到天数)
     */
    public static long getDaySub(String beginDateStr, String endDateStr) {
        long day = 0;
        SimpleDateFormat format = new SimpleDateFormat(
                "yyyy-MM-dd");
        Date beginDate = null;
        Date endDate = null;

        try {
            beginDate = format.parse(beginDateStr);
            endDate = format.parse(endDateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        day = (endDate.getTime() - beginDate.getTime()) / (24 * 60 * 60 * 1000);
        // System.out.println("相隔的天数="+day);

        return day;
    }

    /**
     * 10位13位时间戳转String 格式（2018-10-15 16:03:27） 日期
     *
     * @param timestamp
     * @param simpleDateFormatType 时间戳类型（"yyyy-MM-dd HH:mm:ss"）
     * @return
     */
    public static String numberDateFormat(String timestamp, String simpleDateFormatType) {
        //要转换的时间格式
        SimpleDateFormat sdf = new SimpleDateFormat(simpleDateFormatType);
        String date = null;
        if (timestamp.length() == THIRTEEN) {
            date = sdf.format(Long.parseLong(timestamp));
        } else {
            date = sdf.format(Long.parseLong(timestamp) * 1000);
        }
        return date;
    }

    /**
     * 10位13位时间戳转Date
     *
     * @param timestamp            参数时间戳
     * @param simpleDateFormatType 时间戳类型（"yyyy-MM-dd HH:mm:ss"）
     * @return
     */
    public static Date numberDateFormatToDate(String timestamp, String simpleDateFormatType) {
        //要转换的时间格式
        SimpleDateFormat sdf = new SimpleDateFormat(simpleDateFormatType);
        Date date = null;
        try {
            if (timestamp.length() == THIRTEEN) {
                date = sdf.parse(sdf.format(Long.parseLong(timestamp)));
            } else {
                date = sdf.parse(sdf.format(Long.parseLong(timestamp) * 1000));
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * Date转10位13位时间戳
     *
     * @param date 参数date
     * @param n    需要转换成几位时间戳
     * @return
     */
    public static String numberDateFormatToDate(Date date, int n) {
        String result = null;
        if (n == THIRTEEN) {
            result = String.valueOf(date.getTime());
        } else {
            result = String.valueOf(date.getTime() / 1000);
        }
        return result;
    }

    /**
     * @Author:Bernie
     * @Params: seconds 秒数
     * @Description: 通过秒数转换为时分秒
     * @Date: 2019/7/18 0018 16:46
     */
    public static String getTimeBySecond(long seconds) {
        //转换天数
        long days = seconds / 86400;
        //剩余秒数
        seconds = seconds % 86400;
        //转换小时数
        long hours = seconds / 3600;
        //剩余秒数
        seconds = seconds % 3600;
        //转换分钟
        long minutes = seconds / 60;
        //剩余秒数
        seconds = seconds % 60;
        if (0 < days) {
            return days + "天，" + hours + "小时，" + minutes + "分，" + seconds + "秒";
        } else {
            return (hours == 0 ? "00" : (hours >= 10 ? hours : "0" + hours)) + ":" + (minutes == 0 ? "00" : (minutes >= 10 ? minutes : "0" + minutes)) + ":" + (seconds == 0 ? "00" : (seconds >= 10 ? seconds : "0" + seconds)) + "秒";
        }

    }

    /**
     * @return java.lang.String
     * @Description 转换iso格式
     * @Author CHENJUN
     * @Date 2020/7/10 14:49
     * @params [isoDate]
     */
    public static long getDateFromISO(String isoDate) {
        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
//        DateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return sdf.parse(isoDate).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
            return 0;
        }
    }

    public static long getDateFromDate(String date) {
        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        DateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return sdf.parse(date).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
            return 0;
        }
    }

    public static int getDifference(String start, String end) {
        SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd");
        /*天数差*/
        Date fromDate1 = null, toDate1 = null;
        try {
            fromDate1 = simpleFormat.parse(start);
            toDate1 = simpleFormat.parse(end);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        long from1 = fromDate1.getTime();
        long to1 = toDate1.getTime();
        int days = (int) ((to1 - from1) / (1000 * 60 * 60 * 24));
        System.out.println("两个时间之间的天数差为：" + days);
        return days;
    }

    /**
     * @return 以小数格式显示的小时
     * @Description 将毫秒转换成以小数格式显示的小时
     * @Author SuiYingying
     * @Date 2021/12/24 14:49
     * @params time 毫秒格式的时间
     */
    public static String getHoursForLong(Long time) {
        float newTime;
        time = time / 1000;
        newTime = (float) time % (1000 * 60 * 60 * 24) / (1000 * 60 * 60);
        newTime = newTime * 1000;
        return String.format("%.5f", newTime);
    }

    /**
     * 获取当天剩余秒数
     *
     * @return
     */
    public static Long getSecondsDay() {
        LocalDateTime nextDay = LocalDate.now().plusDays(1).atStartOfDay();
        LocalDateTime now = LocalDateTime.now();
        return Duration.between(now, nextDay).getSeconds();
    }

    /**
     * 对日期的【秒】进行加/减
     *
     * @param date    日期
     * @param seconds 秒数，负数为减
     * @return 加/减几秒后的日期
     */
    public static Date addDateSeconds(Date date, int seconds) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE, seconds);
        return cal.getTime();
    }

    /**
     * 对日期的【分钟】进行加/减
     *
     * @param date    日期
     * @param minutes 分钟数，负数为减
     * @return 加/减几分钟后的日期
     */
    public static Date addDateMinutes(Date date, int minutes) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE, minutes);
        return cal.getTime();
    }

    /**
     * 对日期的【小时】进行加/减
     *
     * @param date  日期
     * @param hours 小时数，负数为减
     * @return 加/减几小时后的日期
     */
    public static Date addDateHours(Date date, int hours) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.HOUR, hours);
        return cal.getTime();
    }

    /**
     * 对日期的【天】进行加/减
     *
     * @param date 日期
     * @param days 天数，负数为减
     * @return 加/减几天后的日期
     */
    public static Date addDateDays(Date date, int days) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, days);
        return cal.getTime();
    }

    /**
     * 对日期的【周】进行加/减
     *
     * @param date  日期
     * @param weeks 周数，负数为减
     * @return 加/减几周后的日期
     */
    public static Date addDateWeeks(Date date, int weeks) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, weeks * 7);
        return cal.getTime();
    }

    /**
     * 对日期的【月】进行加/减
     *
     * @param date   日期
     * @param months 月数，负数为减
     * @return 加/减几月后的日期
     */
    public static Date addDateMonths(Date date, int months) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, months);
        return cal.getTime();
    }

    /**
     * 对日期的【年】进行加/减
     *
     * @param date  日期
     * @param years 年数，负数为减
     * @return 加/减几年后的日期
     */
    public static Date addDateYears(Date date, int years) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.YEAR, years);
        return cal.getTime();
    }

    /**
     * 时间比较大小
     *
     * @param date1 日期
     * @param date2 年数，负数为减
     * @return -1 date1小于date2、0 date1等于date2、1 date1大于date2
     */
    public static int compareTo(Date date1, Date date2) {
        return date1.compareTo(date2);
    }

    public static void main(String[] ager) throws InterruptedException {
        System.out.println(getEndOfDay(new Date()));
    }

    /**
     * ltf 获取
     * 获取指定日期所在周的周一
     *
     * @param date
     * @return
     */
    public static Date getFirstDayOfWeek(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        if (c.get(Calendar.DAY_OF_WEEK) == 1) {
            c.add(Calendar.DAY_OF_MONTH, -1);
        }
        c.add(Calendar.DATE, c.getFirstDayOfWeek() - c.get(Calendar.DAY_OF_WEEK) + 1);
        return c.getTime();
    }

    /**
     * 获取startDate日期后month月的日期
     *
     * @param startDate 开始日期
     * @param month     几个月后
     * @return
     * @author wenzhang
     */
    public static Date getMonthDate(Date startDate, int month) {
        LocalDateTime localDateTime = startDate.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime().plusMonths(month);
        Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
        return date;
    }

    /**
     * @param days
     * @return
     * @author wenzhang
     */
    public static Date getDateAdd(int days) {
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.add(Calendar.DAY_OF_MONTH, days);
        return c.getTime();

    }

    /**
     * 计算两个日期的月数
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static int getMonthSpace(String startDate, String endDate) throws Exception {
        int monthCount = 0;
        Calendar startCalendar = Calendar.getInstance();
        Calendar endCalendar = Calendar.getInstance();
        startCalendar.setTime(new SimpleDateFormat("yyyy-MM-dd").parse(startDate));
        endCalendar.setTime(new SimpleDateFormat("yyyy-MM-dd").parse(endDate));

        int year = endCalendar.get(Calendar.YEAR) - startCalendar.get(Calendar.YEAR);
        int month = endCalendar.get(Calendar.MONTH) - startCalendar.get(Calendar.MONTH);
        int day = Math.abs(endCalendar.get(Calendar.DATE) - startCalendar.get(Calendar.DATE));

        if (year == 0 && month == 0) {
            startCalendar.set(Calendar.DATE, 1);
            endCalendar.set(Calendar.DATE, 1);
            endCalendar.roll(Calendar.DATE, -1);
            if (day == (endCalendar.get(Calendar.DATE) - startCalendar.get(Calendar.DATE))) {
                // 两日期间满一个月
                monthCount = 1;
            } else {
                // 两日期间不足一个月
                monthCount = 0;
            }
            // 年份不同月份相同
        } else if (year != 0 && month == 0) {
            // 两日期间的天数，小于等于当月
            if (startCalendar.get(Calendar.DATE) < endCalendar.get(Calendar.DATE)) {
                monthCount = 1;
            }
            monthCount += year * 12 + month;
        } else {
            // 起始日期DATE 大于等于结束日期DATE
            if (startCalendar.get(Calendar.DATE) >= endCalendar.get(Calendar.DATE)) {
                monthCount = year * 12 + month;
            } else {
                monthCount = year * 12 + month + 1;
            }
        }

        return monthCount;
    }

    /**
     * @desc: 获取指定时间的1日/2周/3月/4年开始时间
     * @author: yzc
     * @date: 2023-09-12 10:20
     * @Param dateType:
     * @Param time:
     * @return: java.util.Date
     */
    public static Date getStartTime(Integer dateType, LocalDateTime time) {
        LocalDateTime startTime;
        if (Objects.equals(dateType, 1)) {
            startTime = LocalDateTime.of(time.toLocalDate(), LocalTime.MIN);
        } else if (Objects.equals(dateType, 2)) {
            startTime = LocalDateTime.of(time.toLocalDate().minusDays(6), LocalTime.MIN);
        } else if (Objects.equals(dateType, 3)) {
            startTime = LocalDateTime.of(time.toLocalDate().minusMonths(1).plusDays(1), LocalTime.MIN);
        } else {
            startTime = LocalDateTime.of(time.toLocalDate().minusYears(1).plusDays(1), LocalTime.MIN);
        }
        return formatDate(startTime);
    }

    /**
     * @desc: 获取上1日/2周/3月/4年结束时间
     * @author: yzc
     * @date: 2023-09-12 10:21
     * @Param dateType:
     * @return: java.util.Date
     */
    public static Date getLastEndTime(Integer dateType) {
        LocalDateTime endTime;
        if (Objects.equals(dateType, 1)) {
            endTime = LocalDateTime.of(LocalDate.now().minusDays(1), LocalTime.MAX);
        } else if (Objects.equals(dateType, 2)) {
            endTime = LocalDateTime.of(LocalDate.now().minusDays(7), LocalTime.MAX);
        } else if (Objects.equals(dateType, 3)) {
            endTime = LocalDateTime.of(LocalDate.now().minusMonths(1), LocalTime.MAX);
        } else {
            endTime = LocalDateTime.of(LocalDate.now().minusYears(1), LocalTime.MAX);
        }
        return formatDate(endTime);
    }

    /**
     * @desc: 获取当前时间倒推一年开始时间
     * @author: yzc
     * @date: 2023-09-13 10:29
     * @return: java.util.Date
     */
    public static Date getYearStartTime() {
        //当前时间减去11个月
        LocalDate localDate = LocalDate.now().minusMonths(11);
        //获取localDate当月第一天
        LocalDate date = LocalDate.of(localDate.getYear(), localDate.getMonth(), 1);
        return formatDate(date.atStartOfDay());
    }

    /**
     * @desc: 获取日期转换格式
     * @author: yzc
     * @date: 2023-09-13 9:32
     * @Param dateType:  1日/3月/4年
     * @return: java.lang.String
     */
    public static String getDateFormat(Integer dateType) {
        String dateFormat;
        switch (dateType) {
            case 1 -> dateFormat = "%Y-%m-%d";
            case 3 -> dateFormat = "%Y-%m";
            case 4 -> dateFormat = "%Y";
            default -> throw new BusinessException("Invalid dateType");
        }
        return dateFormat;
    }

    /**
     * @desc: LocalDateTime转换为Date
     * @author: yzc
     * @date: 2023-09-11 16:42
     * @Param time:
     * @return: java.util.Date
     */
    public static Date formatDate(LocalDateTime time) {
        if (Objects.isNull(time)) {
            return null;
        }
        return Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * @desc: date转换为LocalDate
     * @author: yzc
     * @date: 2023-09-13 15:14
     * @Param date:
     * @return: java.time.LocalDate
     */
    public static LocalDate dateToLocalDate(Date date) {
        if (Objects.isNull(date)) {
            return null;
        }
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    /**
     * @desc: localDate转换为String
     * @author: yzc
     * @date: 2023-09-13 15:21
     * @Param date:
     * @Param pattern:
     * @return: java.lang.String
     */
    public static String localDateToString(LocalDate date, String pattern) {
        if (Objects.isNull(date)) {
            return null;
        }
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern);
        return date.format(fmt);
    }

    /**
     * @desc: localDate转换为date 开始时间
     * @author: yzc
     * @date: 2023-09-27 9:52
     * @Param localDate:
     * @return: java.util.Date
     */
    public static Date localDateToDateStart(LocalDate localDate) {
        if (Objects.isNull(localDate)) {
            return null;
        }
        LocalDateTime time = LocalDateTime.of(localDate, LocalTime.MIN);
        return formatDate(time);
    }

    /**
     * @desc: 一天的开始时间
     * @author: yzc
     * @date: 2023-09-27 9:52
     */
    public static Date getStartOfDay(Date date) {
        String dateStr = format(date, DATE_PATTERN);
        return parse(dateStr, DATE_PATTERN);
    }

    /**
     * @desc: 一天的开始时间
     * @author: yzc
     * @date: 2023-09-27 9:52
     */
    public static Date getStartOfDay(Date date, String format) {
        if (Objects.isNull(date)) {
            return null;
        }
        String dateStr = format(date, format);
        return parse(dateStr, format);
    }

    /**
     * @desc: 一天的结束时间
     * @author: yzc
     * @date: 2023-09-27 9:52
     */
    public static Date getEndOfDay(Date date) {
        if (Objects.isNull(date)) {
            return null;
        }
        String dateStr = format(date, DATE_PATTERN);
        return parse(dateStr + " 23:59:59", DATE_TIME_PATTERN);
    }



    /**
     * @desc: localDate转换为date 结束时间
     * @author: yzc
     * @date: 2023-09-27 9:52
     * @Param localDate:
     * @return: java.util.Date
     */
    public static Date localDateToDateEnd(LocalDate localDate) {
        if (Objects.isNull(localDate)) {
            return null;
        }
        LocalDateTime time = LocalDateTime.of(localDate, LocalTime.MAX).withNano(0);
        return formatDate(time);
    }
}
