package thyyxxk.webserver.utils;

import cn.hutool.core.date.DateTime;
import lombok.extern.slf4j.Slf4j;
import thyyxxk.webserver.constants.GetDateFormat;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author dj
 */
@Slf4j
public class DateUtil extends cn.hutool.core.date.DateUtil {
    public static final String DEFAULT_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE = "yyyy-MM-dd";

    public static String formatPriceTime(String priceTime) {
        return null == priceTime ? "" : priceTime.split("\\.")[0].replace("T", " ");
    }

    public static String formatDate(Date date) {
        return formatDate(date, DATE);
    }

    public static String formatDate(Date date, DateFormat sdf) {
        if (null == date) {
            return "";
        }
        return sdf.format(date);
    }

    public static String formatDate(Date date, String pattern) {
        if (null == date) {
            return "";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(date);
    }

    public static String formatDatetime(Date date, String pattern) {
        if (null == date) {
            return "";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(null == pattern ? DEFAULT_PATTERN : pattern);
        return sdf.format(date);
    }

    public static String formatDatetime(Date date) {
        if (null == date) {
            return "";
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }

    public static Date parse(String source) {
        if (StringUtil.isBlank(source)) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return sdf.parse(source);
        } catch (ParseException e) {
            log.error("将字符串转换成日期出错", e);
        }
        return new Date();
    }

    public static Date parseWithDefaultNowTime(String source) {
        if (StringUtil.isBlank(source)) {
            return new Date();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return sdf.parse(source);
        } catch (ParseException e) {
            log.error("将字符串转换成日期出错", e);
        }
        return new Date();
    }

    public static Date parse(String source, String pattern) {
        if (StringUtil.isBlank(source)) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        try {
            return sdf.parse(source);
        } catch (ParseException e) {
            log.error("将字符串转换成日期出错", e);
        }
        return new Date();
    }

    public static long getTimestamp(String datetime) throws ParseException {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.parse(datetime).getTime();
    }

    public static String getOffsetDate(int offset) {
        DateFormat da = new SimpleDateFormat("yyyy-MM-dd");
        Calendar now = Calendar.getInstance();
        now.set(Calendar.DATE, now.get(Calendar.DATE) + offset);
        return da.format(now.getTime());
    }

    public static String getTodayEndTime() {
        SimpleDateFormat smdate = new SimpleDateFormat("yyyy-MM-dd");
        String date = smdate.format(new Date());
        return date + " 23:59:59.999";
    }

    public static String getDayStartTime(Date date) {
        SimpleDateFormat smdate = new SimpleDateFormat("yyyy-MM-dd");
        return smdate.format(date) + " 00:00:00.000";
    }

    public static String getDayEndTime(Date date) {
        SimpleDateFormat smdate = new SimpleDateFormat("yyyy-MM-dd");
        return smdate.format(date) + " 23:59:59.999";
    }

    public static String getMonthEndtime(String day) {
        String[] split = day.split("-");
        int year = Integer.parseInt(split[0]);
        int month = Integer.parseInt(split[1]);
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month - 1);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String enddate = df.format(cal.getTime());
        return enddate + " 23:59:59.999";
    }

    public static int daysBetween(Date later, Date earlier) {
        if (null == later || null == earlier) {
            return -1;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String d1 = sdf.format(later);
        String d2 = sdf.format(earlier);
        try {
            later = sdf.parse(d1);
            earlier = sdf.parse(d2);
            int days = (int) ((later.getTime() - earlier.getTime()) / (1000L * 3600L * 24L));
            return days == 0 ? 1 : days;
        } catch (Exception e) {
            log.error("将字符串转换成日期出错", e);
            return -1;
        }
    }

    public static Date addOneSecond(Date begntime) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(begntime);
        cal.add(Calendar.SECOND, 1);
        return cal.getTime();
    }

    public static String getYesterday() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.add(Calendar.DATE, -1);
        Date yesterday = cal.getTime();
        DateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
        return df.format(yesterday);
    }


    public static Date timeAddOrMinusDays(Date date, int day) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, day);
        return cal.getTime();
    }

    public static String calculateAgeWithUnit(String birthDate) {
        if (birthDate == null) {
            return "0";
        }
        try {
            LocalDate dob = LocalDate.parse(birthDate);
            LocalDate today = LocalDate.now();
            Period period = Period.between(dob, today);
            if (period.getYears() > 0) {
                return period.getYears() + "岁";
            } else if (period.getMonths() > 0) {
                return period.getMonths() + "个月";
            } else if (period.getDays() > 0) {
                return period.getDays() + "天";
            } else {
                long hours = ChronoUnit.HOURS.between(LocalDateTime.of(today, LocalTime.from(today.atStartOfDay())), LocalDateTime.now());
                return hours + "小时";
            }
        } catch (Exception e) {
            return "0";
        }
    }

    public static Integer calculateAge(String birthDate) {
        if (birthDate == null) {
            return null;
        }
        try {
            LocalDate dob = LocalDate.parse(birthDate);
            LocalDate today = LocalDate.now();
            Period period = Period.between(dob, today);
            return period.getYears();
        } catch (DateTimeParseException e) {
            System.err.println("Invalid date format: " + birthDate);
            return null;
        }
    }

    public static Integer calculateAge(Date birthDate, Date admdate) {
        if (null == birthDate) {
            return null;
        }
        int age;
        Calendar cal = Calendar.getInstance();
        if (null != admdate) {
            cal.setTime(admdate);
        }
        if (cal.before(birthDate)) {
            throw new IllegalArgumentException("出生日期晚于当前时间，无法计算!");
        }
        int yearNow = cal.get(Calendar.YEAR);
        int monthNow = cal.get(Calendar.MONTH);
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
        cal.setTime(birthDate);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        age = yearNow - yearBirth;
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) {
                    // 当前日期在生日之前，年龄减一
                    age--;
                }
            } else {
                // 当前月份在生日之前，年龄减一
                age--;
            }
        }
        return age;
    }

    public static Integer calculateNewBornAge(Date birthDate, Date admdate) {
        if (null == birthDate || admdate == null) {
            return null;
        }
        if (admdate.before(birthDate)) {
            throw new IllegalArgumentException("出生日期晚于当前时间，无法计算!");
        }
        return (int) ((admdate.getTime() - birthDate.getTime()) / (1000L * 3600L * 24L));
    }

    public static String now() {
        LocalDateTime time = LocalDateTime.now();
        return time.format(DateTimeFormatter.ofPattern(DEFAULT_PATTERN));
    }

    public static Boolean shiJianDaXiao(Date startTime, Date endTime, String yunSuanFu) {
        if (startTime == null || endTime == null) return false;
        switch (yunSuanFu) {
            case ">":
                return startTime.compareTo(endTime) > 0;
            case ">=":
                return startTime.compareTo(endTime) >= 0;
            case "<":
                return startTime.compareTo(endTime) < 0;
            case "<=":
                return startTime.compareTo(endTime) <= 0;
            case "=":
                return startTime.compareTo(endTime) == 0;
            default:
                return false;
        }
    }

    public static Boolean shiJianDaXiao(String startTime, String endTime, String yunSuanFu) {
        if (dateStrIsValid(startTime, GetDateFormat.DATE_TIME) && dateStrIsValid(endTime, GetDateFormat.DATE_TIME)) {
            return shiJianDaXiao(parse(startTime), parse(endTime), yunSuanFu);
        } else if (dateStrIsValid(startTime, GetDateFormat.TIME) && dateStrIsValid(endTime, GetDateFormat.TIME)) {
            return shiJianDaXiao(parse(startTime, GetDateFormat.TIME), parse(endTime, GetDateFormat.TIME), yunSuanFu);
        } else if (dateStrIsValid(startTime, GetDateFormat.DATE) && dateStrIsValid(endTime, GetDateFormat.DATE)) {
            return shiJianDaXiao(parse(startTime, GetDateFormat.DATE), parse(endTime, GetDateFormat.DATE), yunSuanFu);
        } else {
            return false;
        }
    }

    /**
     * 验证字符串是否为指定日期格式
     *
     * @param rawDateStr 待验证字符串
     * @param pattern    日期字符串格式, 例如 "yyyy-MM-dd"
     * @return 有效性结果, true 为正确, false 为错误
     */
    public static boolean dateStrIsValid(String rawDateStr, String pattern) {
        if (StringUtil.isBlank(rawDateStr)) {
            return false;
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        Date date;
        try {
            // 转化为 Date类型测试判断
            dateFormat.setLenient(false);
            date = dateFormat.parse(rawDateStr);
            return rawDateStr.equals(dateFormat.format(date));
        } catch (ParseException e) {
            return false;
        }

    }

    /**
     * @param nowTime   当前时间
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return boolean
     * @author sunran   判断当前时间在时间区间内
     */
    public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
        return startTime.getTime() <= nowTime.getTime() && endTime.getTime() >= nowTime.getTime();
    }

    /**
     * 判断时间是否在时间段内
     */
    public static boolean belongCalendar(Date nowTime, Date beginTime, Date endTime) {
        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);

        Calendar begin = Calendar.getInstance();
        begin.setTime(beginTime);

        Calendar end = Calendar.getInstance();
        end.setTime(endTime);

        return date.after(begin) && date.before(end);
    }

    public static Date timePlusSecond(Date date, int second) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.SECOND, second);
        return cal.getTime();
    }

    public static boolean moreThanHours(Date date, int hours) {
        long l = System.currentTimeMillis();
        long mills = l - date.getTime();
        int requiredHours = (int) (mills / 1000 / 3600);
        return requiredHours >= hours;
    }

    /**
     * 判断相差几个小时
     *
     * @param endDate   结束时间
     * @param startDate 开始时间
     * @return 返回int
     */
    public static long theDifferenceIsHours(Date endDate, Date startDate) {
        try {
            long diff = endDate.getTime() - startDate.getTime();
            return diff / (1000 * 60 * 60);
        } catch (Exception e) {
            return -1;
        }
    }

    public static String getLastYearDate(String time, String pattern) {
        if (StringUtil.isBlank(time)) {
            return "";
        }
        if (StringUtil.isBlank(pattern)) {
            pattern = "yyyy-MM-dd HH:mm:ss";
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            Date dt = sdf.parse(time);
            Calendar rightNow = Calendar.getInstance();
            rightNow.setTime(dt);
            // 日期减1年
            rightNow.add(Calendar.YEAR, -1);
            return sdf.format(rightNow.getTime());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }


    public static String secondsToTime(int seconds) {
        //小时
        int h = seconds / 3600;
        //分钟
        int m = (seconds % 3600) / 60;
        //秒
        int s = (seconds % 3600) % 60;
        if (h > 0) {
            return h + "小时" + m + "分钟" + s + "秒";
        }
        if (m > 0) {
            return m + "分钟" + s + "秒";
        }
        return s + "秒";
    }

    /**
     * @description: 获取某月的每一天
     * @author: hsh
     * @date: 2022/10/19 14:59
     * @param: [yyyymm]
     * @return: List<String>
     **/
    public static List<String> getDayListOfMonth(String yyyymm) {

        if (yyyymm.length() != 6) {
            return null;
        }

        List<String> list = new ArrayList<>();
        String ystr = yyyymm.substring(0, 4);
        String mstr = yyyymm.substring(4, 6);

        Calendar a = Calendar.getInstance();
        //年份
        a.set(Calendar.YEAR, Integer.parseInt(ystr));
        //月份
        a.set(Calendar.MONTH, Integer.parseInt(mstr) - 1);
        a.set(Calendar.DATE, 1);
        a.roll(Calendar.DATE, -1);

        int maxDate = a.get(Calendar.DATE);

        for (int i = 0; i < maxDate; i++) {
            int d = i + 1;
            String dStr = "";
            if (d < 10) {
                dStr = "0" + d;
            } else {
                dStr = String.valueOf(d);
            }
            String day = ystr + mstr + dStr;
            list.add(day);
        }
        return list;
    }

    public static String calculateBirthDateFromIdNumber(String idNumber) {
        if (!IdCardUtil.isValidatedIdCard(idNumber)) {
            return null;
        }
        return idNumber.substring(6, 10) + "-" + idNumber.substring(10, 12) +
               "-" + idNumber.substring(12, 14);
    }

    public static String calculateAgeLabelByDays(Integer ageDays) {
        // 判断ageDays是否为空
        if (null == ageDays) {
            return "";
        }
        // 判断ageDays是否为0
        if (ageDays == 0) {
            return "1天";
        }
        // 计算ageDays对应的年数
        int ageYear = ageDays / 365;
        // 判断年数是否大于0
        if (ageYear > 0) {
            return ageYear + "岁";
        }
        // 计算ageDays对应的月数
        int ageMonth = ageDays / 30;
        // 判断月数是否大于0
        if (ageMonth > 0) {
            return ageMonth + "月";
        }
        // 返回ageDays对应的天数
        return ageDays + "天";
    }

    /**
     * printExample("2025-05-21 13:00:00", 3); // 2025-05-23 23:59:59
     * // 更多示例
     * printExample("2025-05-21 00:00:01", 1); // 当天结束
     * printExample("2025-05-21 23:59:59", 2); // 2025-05-22 23:59:59
     * printExample("2025-12-31 12:00:00", 1); // 2025-12-31 23:59:59
     * printExample("2025-12-31 12:00:00", 2); // 2026-01-01 23:59:59
     *
     * @param date 开始的时间
     * @param days 加几天
     * @return 返回日期
     */
    public static Date addNaturalDays(Date date, int days) {
        // 如果开始时间为空，则返回空
        if (date == null) {
            return null;
        }
        // 计算加上指定天数后的日期
        Date addedDate = DateUtil.offsetDay(date, days - 1);
        // 返回加上指定天数后的日期的当天的结束时间
        return DateUtil.endOfDay(addedDate);
    }


    public static Date addNaturalDays(String dateStr, int days) {
        // 将字符串类型的日期转换为Date类型
        Date date = DateUtil.parse(dateStr);
        // 调用addNaturalDays方法，传入Date类型日期和天数，返回新的日期
        return addNaturalDays(date, days);
    }

    public static boolean isInTimeRange(String startTimeStr, String endTimeStr, String currentTimeStr) {
        // 1. 将时间字符串转换为今天的日期对象（Hutool 自动补全年月日）
        DateTime startTime = DateUtil.parseTimeToday(startTimeStr);
        DateTime endTime = DateUtil.parseTimeToday(endTimeStr);
        DateTime currentTime = DateUtil.parseTimeToday(currentTimeStr);

        // 2. 判断时间范围（支持跨天场景，如 22:00:00 - 02:00:00）
        if (endTime.isBeforeOrEquals(startTime)) {
            // 结束时间 <= 开始时间，说明跨天（通宵时段）
            return currentTime.isAfterOrEquals(startTime) || currentTime.isBeforeOrEquals(endTime);
        } else {
            // 普通时段
            return currentTime.isAfterOrEquals(startTime) && currentTime.isBeforeOrEquals(endTime);
        }
    }

}

