package com.corewing.app.util;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;

public class DateUtils {

    public static void main(String[] args) {
        //2026-02-24 08:40:90
        System.out.println(isAfter(parseToLocalDateTime("2026-02-22 08:40:30")));
    }

    //==================== 字符串格式化方法 ====================

    /**
     * 将字符串格式化为LocalDateTime
     * @param dateTimeStr 日期时间字符串
     * @param pattern 格式模式，如：yyyy-MM-dd HH:mm:ss
     * @return LocalDateTime对象
     */
    public static LocalDateTime parseToLocalDateTime(String dateTimeStr, String pattern) {
        if (dateTimeStr == null || dateTimeStr.isEmpty() || pattern == null || pattern.isEmpty()) {
            return null;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return LocalDateTime.parse(dateTimeStr, formatter);
    }

    /**
     * 将字符串格式化为LocalDate
     * @param dateStr 日期字符串
     * @param pattern 格式模式，如：yyyy-MM-dd
     * @return LocalDate对象
     */
    public static LocalDate parseToLocalDate(String dateStr, String pattern) {
        if (dateStr == null || dateStr.isEmpty() || pattern == null || pattern.isEmpty()) {
            return null;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return LocalDate.parse(dateStr, formatter);
    }

    /**
     * 将字符串格式化为LocalTime
     * @param timeStr 时间字符串
     * @param pattern 格式模式，如：HH:mm:ss
     * @return LocalTime对象
     */
    public static LocalTime parseToLocalTime(String timeStr, String pattern) {
        if (timeStr == null || timeStr.isEmpty() || pattern == null || pattern.isEmpty()) {
            return null;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return LocalTime.parse(timeStr, formatter);
    }

    /**
     * 将字符串格式化为Date
     * @param dateTimeStr 日期时间字符串
     * @param pattern 格式模式，如：yyyy-MM-dd HH:mm:ss
     * @return Date对象
     */
    public static Date parseToDate(String dateTimeStr, String pattern) {
        if (dateTimeStr == null || dateTimeStr.isEmpty() || pattern == null || pattern.isEmpty()) {
            return null;
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            return sdf.parse(dateTimeStr);
        } catch (Exception e) {
            throw new IllegalArgumentException("日期解析失败: " + dateTimeStr, e);
        }
    }

    //==================== 常用格式的快捷方法 ====================

    /**
     * 将字符串格式化为LocalDateTime（默认格式：yyyy-MM-dd HH:mm:ss）
     */
    public static LocalDateTime parseToLocalDateTime(String dateTimeStr) {
        return parseToLocalDateTime(dateTimeStr, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 将字符串格式化为LocalDate（默认格式：yyyy-MM-dd）
     */
    public static LocalDate parseToLocalDate(String dateStr) {
        return parseToLocalDate(dateStr, "yyyy-MM-dd");
    }

    /**
     * 将字符串格式化为LocalTime（默认格式：HH:mm:ss）
     */
    public static LocalTime parseToLocalTime(String timeStr) {
        return parseToLocalTime(timeStr, "HH:mm:ss");
    }

    /**
     * 将字符串格式化为Date（默认格式：yyyy-MM-dd HH:mm:ss）
     */
    public static Date parseToDate(String dateTimeStr) {
        return parseToDate(dateTimeStr, "yyyy-MM-dd HH:mm:ss");
    }

    //==================== 智能解析方法 ====================

    /**
     * 智能解析字符串为LocalDateTime（自动识别常见格式）
     * 支持格式：
     * - yyyy-MM-dd HH:mm:ss
     * - yyyy/MM/dd HH:mm:ss
     * - yyyy-MM-dd'T'HH:mm:ss
     * - yyyy-MM-dd HH:mm
     * - yyyy-MM-dd
     * - yyyy/MM/dd
     */
    public static LocalDateTime smartParseToLocalDateTime(String dateTimeStr) {
        if (dateTimeStr == null || dateTimeStr.isEmpty()) {
            return null;
        }

        String str = dateTimeStr.trim();

        // 尝试各种格式
        try {
            // 格式1: yyyy-MM-dd HH:mm:ss
            return LocalDateTime.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        } catch (Exception e1) {
            try {
                // 格式2: yyyy/MM/dd HH:mm:ss
                return LocalDateTime.parse(str, DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"));
            } catch (Exception e2) {
                try {
                    // 格式3: yyyy-MM-dd'T'HH:mm:ss
                    return LocalDateTime.parse(str, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
                } catch (Exception e3) {
                    try {
                        // 格式4: yyyy-MM-dd HH:mm
                        return LocalDateTime.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
                    } catch (Exception e4) {
                        try {
                            // 格式5: yyyy-MM-dd (转为当天开始时间)
                            LocalDate date = LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                            return date.atStartOfDay();
                        } catch (Exception e5) {
                            try {
                                // 格式6: yyyy/MM/dd
                                LocalDate date = LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy/MM/dd"));
                                return date.atStartOfDay();
                            } catch (Exception e6) {
                                throw new IllegalArgumentException("无法解析的日期时间字符串: " + str);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 智能解析字符串为LocalDate（自动识别常见格式）
     * 支持格式：
     * - yyyy-MM-dd
     * - yyyy/MM/dd
     * - yyyyMMdd
     * - dd/MM/yyyy
     */
    public static LocalDate smartParseToLocalDate(String dateStr) {
        if (dateStr == null || dateStr.isEmpty()) {
            return null;
        }

        String str = dateStr.trim();

        try {
            return LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } catch (Exception e1) {
            try {
                return LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy/MM/dd"));
            } catch (Exception e2) {
                try {
                    return LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyyMMdd"));
                } catch (Exception e3) {
                    try {
                        return LocalDate.parse(str, DateTimeFormatter.ofPattern("dd/MM/yyyy"));
                    } catch (Exception e4) {
                        throw new IllegalArgumentException("无法解析的日期字符串: " + str);
                    }
                }
            }
        }
    }

    //==================== 格式化输出方法 ====================

    /**
     * 将LocalDateTime格式化为字符串
     * @param dateTime LocalDateTime对象
     * @param pattern 格式模式
     * @return 格式化后的字符串
     */
    public static String format(LocalDateTime dateTime, String pattern) {
        if (dateTime == null || pattern == null || pattern.isEmpty()) {
            return "";
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return dateTime.format(formatter);
    }

    /**
     * 将LocalDate格式化为字符串
     */
    public static String format(LocalDate date, String pattern) {
        if (date == null || pattern == null || pattern.isEmpty()) {
            return "";
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return date.format(formatter);
    }

    /**
     * 将LocalTime格式化为字符串
     */
    public static String format(LocalTime time, String pattern) {
        if (time == null || pattern == null || pattern.isEmpty()) {
            return "";
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return time.format(formatter);
    }

    /**
     * 将Date格式化为字符串
     */
    public static String format(Date time, String pattern) {
        if (time == null || pattern == null || pattern.isEmpty()) {
            return "";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(time);
    }

    /**
     * 将LocalDateTime格式化为默认格式：yyyy-MM-dd HH:mm:ss
     */
    public static String formatDateTime(LocalDateTime dateTime) {
        return format(dateTime, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 将LocalDate格式化为默认格式：yyyy-MM-dd
     */
    public static String formatDate(LocalDate date) {
        return format(date, "yyyy-MM-dd");
    }

    /**
     * 将LocalTime格式化为默认格式：HH:mm:ss
     */
    public static String formatTime(LocalTime time) {
        return format(time, "HH:mm:ss");
    }

    /**
     * 将Date格式化为默认格式：yyyy-MM-dd HH:mm:ss
     */
    public static String formatDateTime(Date date) {
        return format(date, "yyyy-MM-dd HH:mm:ss");
    }

    //==================== 判断方法 ====================

    /**
     * 判断传入时间是否大于当前时间
     * @param time 支持：Date, LocalDateTime, LocalDate, String
     */
    public static boolean isAfter(Object time) {
        LocalDateTime dateTime = convertToLocalDateTime(time);
        return dateTime.isAfter(LocalDateTime.now());
    }

    /**
     * 判断传入时间是否小于当前时间
     * @param time 支持：Date, LocalDateTime, LocalDate, String
     */
    public static boolean isBefore(Object time) {
        LocalDateTime dateTime = convertToLocalDateTime(time);
        return dateTime.isBefore(LocalDateTime.now());
    }

    /**
     * 判断传入时间是否等于当前时间（近似到分钟）
     * @param time 支持：Date, LocalDateTime, LocalDate, String
     */
    public static boolean isEqual(Object time) {
        LocalDateTime dateTime = convertToLocalDateTime(time);
        LocalDateTime now = LocalDateTime.now().withSecond(0).withNano(0);
        return dateTime.withSecond(0).withNano(0).isEqual(now);
    }

    //==================== 日期时间专用判断 ====================

    /**
     * 判断传入时间是否大于等于当前时间
     */
    public static boolean isAfterOrEqual(Object time) {
        LocalDateTime dateTime = convertToLocalDateTime(time);
        return !dateTime.isBefore(LocalDateTime.now());
    }

    /**
     * 判断传入时间是否小于等于当前时间
     */
    public static boolean isBeforeOrEqual(Object time) {
        LocalDateTime dateTime = convertToLocalDateTime(time);
        return !dateTime.isAfter(LocalDateTime.now());
    }

    /**
     * 判断传入时间是否大于等于指定时间
     * @param time 要判断的时间
     * @param targetTime 目标时间
     */
    public static boolean isAfterOrEqual(Object time, Object targetTime) {
        LocalDateTime dateTime = convertToLocalDateTime(time);
        LocalDateTime target = convertToLocalDateTime(targetTime);
        return !dateTime.isBefore(target);
    }

    /**
     * 判断传入时间是否小于等于指定时间
     * @param time 要判断的时间
     * @param targetTime 目标时间
     */
    public static boolean isBeforeOrEqual(Object time, Object targetTime) {
        LocalDateTime dateTime = convertToLocalDateTime(time);
        LocalDateTime target = convertToLocalDateTime(targetTime);
        return !dateTime.isAfter(target);
    }

    /**
     * 判断传入时间是否在指定时间范围内（包含边界）
     * @param time 要判断的时间
     * @param start 开始时间
     * @param end 结束时间
     */
    public static boolean isBetween(Object time, Object start, Object end) {
        LocalDateTime dateTime = convertToLocalDateTime(time);
        LocalDateTime startTime = convertToLocalDateTime(start);
        LocalDateTime endTime = convertToLocalDateTime(end);
        return !dateTime.isBefore(startTime) && !dateTime.isAfter(endTime);
    }

    /**
     * 判断传入时间是否在指定时间范围内（不包含边界）
     * @param time 要判断的时间
     * @param start 开始时间
     * @param end 结束时间
     */
    public static boolean isBetweenExclusive(Object time, Object start, Object end) {
        LocalDateTime dateTime = convertToLocalDateTime(time);
        LocalDateTime startTime = convertToLocalDateTime(start);
        LocalDateTime endTime = convertToLocalDateTime(end);
        return dateTime.isAfter(startTime) && dateTime.isBefore(endTime);
    }

    //==================== 两个时间比较 ====================

    /**
     * 判断time1是否大于time2
     */
    public static boolean isAfter(Object time1, Object time2) {
        LocalDateTime dt1 = convertToLocalDateTime(time1);
        LocalDateTime dt2 = convertToLocalDateTime(time2);
        return dt1.isAfter(dt2);
    }

    /**
     * 判断time1是否小于time2
     */
    public static boolean isBefore(Object time1, Object time2) {
        LocalDateTime dt1 = convertToLocalDateTime(time1);
        LocalDateTime dt2 = convertToLocalDateTime(time2);
        return dt1.isBefore(dt2);
    }

    /**
     * 判断两个时间是否相等
     */
    public static boolean isEqual(Object time1, Object time2) {
        LocalDateTime dt1 = convertToLocalDateTime(time1);
        LocalDateTime dt2 = convertToLocalDateTime(time2);
        return dt1.isEqual(dt2);
    }

    //==================== 日期专用判断 ====================

    /**
     * 判断传入日期是否大于今天（只比较年月日）
     */
    public static boolean isAfterDate(Object date) {
        LocalDate localDate = convertToLocalDate(date);
        return localDate.isAfter(LocalDate.now());
    }

    /**
     * 判断传入日期是否小于今天（只比较年月日）
     */
    public static boolean isBeforeDate(Object date) {
        LocalDate localDate = convertToLocalDate(date);
        return localDate.isBefore(LocalDate.now());
    }

    /**
     * 判断传入日期是否等于今天
     */
    public static boolean isToday(Object date) {
        LocalDate localDate = convertToLocalDate(date);
        return localDate.isEqual(LocalDate.now());
    }

    /**
     * 判断传入日期是否大于等于今天（只比较年月日）
     */
    public static boolean isAfterOrEqualDate(Object date) {
        LocalDate localDate = convertToLocalDate(date);
        return !localDate.isBefore(LocalDate.now());
    }

    /**
     * 判断传入日期是否小于等于今天（只比较年月日）
     */
    public static boolean isBeforeOrEqualDate(Object date) {
        LocalDate localDate = convertToLocalDate(date);
        return !localDate.isAfter(LocalDate.now());
    }

    //==================== 私有转换方法 ====================

    /**
     * 将各种类型转换为LocalDateTime
     */
    private static LocalDateTime convertToLocalDateTime(Object time) {
        if (time == null) {
            throw new IllegalArgumentException("时间不能为null");
        }

        // 1. LocalDateTime
        if (time instanceof LocalDateTime) {
            return (LocalDateTime) time;
        }

        // 2. LocalDate
        if (time instanceof LocalDate) {
            return ((LocalDate) time).atStartOfDay();
        }

        // 3. Date
        if (time instanceof Date) {
            return ((Date) time).toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
        }

        // 4. String
        if (time instanceof String) {
            return smartParseToLocalDateTime((String) time);
        }

        // 5. Long (时间戳)
        if (time instanceof Long) {
            return LocalDateTime.ofInstant(
                    java.time.Instant.ofEpochMilli((Long) time),
                    ZoneId.systemDefault()
            );
        }

        throw new IllegalArgumentException("不支持的时间类型: " + time.getClass().getName());
    }

    /**
     * 将各种类型转换为LocalDate
     */
    private static LocalDate convertToLocalDate(Object date) {
        if (date == null) {
            throw new IllegalArgumentException("日期不能为null");
        }

        // 1. LocalDate
        if (date instanceof LocalDate) {
            return (LocalDate) date;
        }

        // 2. LocalDateTime
        if (date instanceof LocalDateTime) {
            return ((LocalDateTime) date).toLocalDate();
        }

        // 3. Date
        if (date instanceof Date) {
            return ((Date) date).toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate();
        }

        // 4. String
        if (date instanceof String) {
            return smartParseToLocalDate((String) date);
        }

        // 5. Long (时间戳)
        if (date instanceof Long) {
            return LocalDateTime.ofInstant(
                    java.time.Instant.ofEpochMilli((Long) date),
                    ZoneId.systemDefault()
            ).toLocalDate();
        }

        throw new IllegalArgumentException("不支持的日期类型: " + date.getClass().getName());
    }
}