package com.sckw.excel.utils;


import com.sckw.core.utils.StringUtils;

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.GregorianCalendar;

/**
 * @description: 时间工具类
 * @author: LengFaQiang
 * @copyright
 * @create: 2022-01-27 16:04
 **/
public class DateUtil {
    public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String DEF_DATE_FORMAT = "yyyy-MM-dd";
    public static final DateTimeFormatter YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static final DateTimeFormatter YYYY_MM_DD = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter HH_MM_SS = DateTimeFormatter.ofPattern("HH:mm:ss");

    public DateUtil() {
    }

    public static long getSystemTimeMillis() {
        Clock clock = Clock.systemDefaultZone();
        return clock.millis();
    }

    public static String getDateTime(String pattern) {
        if (StringUtils.isEmpty(pattern)) {
            pattern = "yyyy-MM-dd HH:mm:ss";
        }

        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(pattern));
    }

    public static String getDateTime(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    public static String dateToStr(LocalDate date) {
        return dateToStr(date, "yyyy-MM-dd");
    }

    public static String dateToStr(LocalDate date, String pattern) {
        String dateStr = date.format(DateTimeFormatter.ofPattern(pattern));
        return dateStr;
    }

    public static String timeToStr(LocalDateTime date) {
        return timeToStr(date, "yyyy-MM-dd HH:mm:ss");
    }

    public static String timeToStr(LocalDateTime date, String pattern) {
        String dateStr = date.format(DateTimeFormatter.ofPattern(pattern));
        return dateStr;
    }

    public static LocalDateTime strToTime(String str) {
        return LocalDateTime.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * yyyy-MM-dd 转换成 LocalDate
     *
     * @param str
     * @return
     */
    public static LocalDate strToDate(String str) {
        return LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }

    /**
     * yyyy-MM-dd 转换成 LocalDateTime
     *
     * @param str
     * @return
     */
    public static LocalDateTime strToDateTime(String str) {
        LocalDate localDate = LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        LocalDateTime localDateTime = localDate.atStartOfDay();
        String format = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime parse = LocalDateTime.parse(format, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        return parse;
    }

    /**
     * yyyyMMdd 转换成 LocalDate
     *
     * @param str
     * @return
     */
    public static LocalDate stringToDate(String str) {
        return LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyyMMdd"));
    }

    /**
     * 日期字符串转换为LocalDateTime方法
     *
     * @param dateString 日期字符串，格式：yyyyMMdd
     * @return
     */
    public static LocalDateTime handleDateTimeString(String dateString) {
        //日期字符串的长度
        Integer dateLength = 10;
        if (org.apache.commons.lang3.StringUtils.isNotBlank(dateString) && dateString.length() == dateLength) {
            StringBuilder sb = new StringBuilder(dateString);
            return LocalDateTime.parse(sb.toString() + "T00:00:00");
        }
        return null;
    }

    /**
     * 日期字符串转换为LocalDateTime方法
     *
     * @param dateString 日期字符串，格式：yyyyMMdd
     * @return
     */
    public static LocalDateTime handleDateString(String dateString) {
        //日期字符串的长度
        Integer dateLength = 8;
        if (org.apache.commons.lang3.StringUtils.isNotBlank(dateString) && dateString.length() == dateLength) {
            StringBuilder sb = new StringBuilder(dateString);
            sb.insert(4, "-");
            sb.insert(7, "-");
            return LocalDateTime.parse(sb.toString() + "T00:00:00");
        }
        return null;
    }

    public static String date() {
        return LocalDate.now().format(YYYY_MM_DD);
    }

    public static int year() {
        return LocalDate.now().getYear();
    }

    public static int month() {
        return LocalDate.now().getMonthValue();
    }

    public static int dayOfMonth() {
        return LocalDate.now().getDayOfMonth();
    }

    public static int dayOfYear() {
        return LocalDate.now().getDayOfYear();
    }

    public static int dayOfWeek() {
        return LocalDate.now().getDayOfWeek().getValue();
    }

    public static String newDate(int year, int month, int day) {
        return LocalDate.of(year, month, day).toString();
    }

    public static String newDate(int year, int dayNum) {
        return LocalDate.ofYearDay(year, dayNum).toString();
    }

    public static String time() {
        return LocalTime.now().format(HH_MM_SS);
    }

    public static int hour() {
        return LocalTime.now().getHour();
    }

    public static int minute() {
        return LocalTime.now().getMinute();
    }

    public static int second() {
        return LocalTime.now().getSecond();
    }

    public static String dateTime() {
        return LocalDateTime.now().format(YYYY_MM_DD_HH_MM_SS);
    }

    public static LocalDateTime parseDateTime(long time) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault());
    }

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

    public static LocalDate parseDate(long time) {
        return LocalDate.from(parseDateTime(time));
    }

    public static LocalDate parseDate(String time) {
        return LocalDate.parse(time, YYYY_MM_DD);
    }

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

    public static String format(LocalDateTime dateTime) {
        return dateTime.format(YYYY_MM_DD_HH_MM_SS);
    }

    public static long millis(LocalDate date) {
        return millis(date.atStartOfDay());
    }

    public static long millis(LocalDateTime dateTime) {
        return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    public static String getDateString(Date date, String pattern) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        return localDateTime.format(DateTimeFormatter.ofPattern(pattern));
    }

    public static long getBetweenDays(Date startDate, Date endDate) {
        return betweenDate(startDate, endDate).toDays();
    }

    public static long getBetweenHours(Date startDate, Date endDate) {
        return betweenDate(startDate, endDate).toHours();
    }

    public static long getBetweenMinutes(Date startDate, Date endDate) {
        return betweenDate(startDate, endDate).toMinutes();
    }

    private static Duration betweenDate(Date startDate, Date endDate) {
        ZoneId zoneId = ZoneId.systemDefault();
        Instant startDateInstant = startDate.toInstant();
        LocalDateTime startDateLocalDateTime = startDateInstant.atZone(zoneId).toLocalDateTime();
        Instant endDateInstant = endDate.toInstant();
        LocalDateTime endDateLocalDateTime = endDateInstant.atZone(zoneId).toLocalDateTime();
        return Duration.between(startDateLocalDateTime, endDateLocalDateTime);
    }

    public static Date strToDate(String dateStr, String pattern) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat();
        if (pattern != null && !pattern.isEmpty()) {
            dateFormat.applyPattern(pattern);
        }

        Date date = dateFormat.parse(dateStr);
        return date;
    }

    public static int getCurrentMonthDays() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(5, 1);
        calendar.roll(5, -1);
        int days = calendar.get(5);
        return days;
    }

    public static int getMonthDays(int year, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(1, year);
        calendar.set(2, month - 1);
        calendar.set(5, 1);
        calendar.roll(5, -1);
        int days = calendar.get(5);
        return days;
    }

    public static Date subtractionOneDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(5, -1);
        Date startDate = calendar.getTime();
        return startDate;
    }

    public static Date getDay(int offset, Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(5, offset);
        return calendar.getTime();
    }

    public static Date getDelay(int offset, Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(1, offset);
        return calendar.getTime();
    }

    public static Date offsetDay(Date date, int offset) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, offset);
        return calendar.getTime();
    }

    public static String getWeekOfDate(Date date, Lanagues language) {
        String name = "";
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int weekIndex = calendar.get(7) - 1;
        if (weekIndex < 0) {
            weekIndex = 0;
        }

        switch (language) {
            case CHINESE:
                name = Week.getName(weekIndex);
                break;
            case ENGLISH:
                name = Week.getEnName(weekIndex);
        }

        return name;
    }

    public static Date LocalDateTimeToDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static enum Week {
        SUNDAY("星期日", "Sunday", 0),
        MONDAY("星期一", "Monday", 1),
        TUESDAY("星期二", "Tuesday", 2),
        WEDNESDAY("星期三", "Sunday", 3),
        THURSDAY("星期四", "Thursday", 4),
        FRIDAY("星期五", "Friday ", 5),
        SATURDAY("星期六", "Saturday", 6);

        private String name;
        private String enName;
        private int index;

        public static String getName(int index) {
            String name = null;
            Week[] var2 = values();
            int var3 = var2.length;

            for (int var4 = 0; var4 < var3; ++var4) {
                Week week = var2[var4];
                if (week.getIndex() == index) {
                    name = week.getName();
                }
            }

            return name;
        }

        public static String getEnName(int index) {
            String name = null;
            Week[] var2 = values();
            int var3 = var2.length;

            for (int var4 = 0; var4 < var3; ++var4) {
                Week week = var2[var4];
                if (week.getIndex() == index) {
                    name = week.getEnName();
                }
            }

            return name;
        }

        public String getName() {
            return this.name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getEnName() {
            return this.enName;
        }

        public void setEnName(String enName) {
            this.enName = enName;
        }

        public int getIndex() {
            return this.index;
        }

        public void setIndex(int index) {
            this.index = index;
        }

        private Week(String name, String enName, int index) {
            this.name = name;
            this.enName = enName;
            this.index = index;
        }

        @Override
        public String toString() {
            return "Week [name=" + this.name + ", enName=" + this.enName + ", index=" + this.index + "]";
        }
    }

    public static enum Lanagues {
        CHINESE,
        ENGLISH;

        private Lanagues() {
        }
    }
}
