package com.ruoyi.common.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;

public class TimeWayUtil {

    // 使用ThreadLocal确保每个线程有自己的SimpleDateFormat实例，避免并发问题
    private static final ThreadLocal<SimpleDateFormat> sdfYTDHMS = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    private static final ThreadLocal<SimpleDateFormat> sdfYTD = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
    private static final ThreadLocal<SimpleDateFormat> sdfUnsignedYTDHM = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMddHHmm"));
    private static final ThreadLocal<SimpleDateFormat> sdfHolder = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SS"));
    private static final ThreadLocal<SimpleDateFormat> sdfHm = ThreadLocal.withInitial(() -> new SimpleDateFormat("HH:mm"));

    /**
     * 格式化时间戳为字符串，支持四种格式：yyyy-MM-dd HH:mm:ss、yyyy-MM-dd、yyyyMMddHHmm、yyyy-MM-dd HH:mm:ss:SS。
     *
     * @param patternType 1 表示 yyyy-MM-dd HH:mm:ss，2 表示 yyyy-MM-dd，3 表示 yyyyMMddHHmm，4 表示 yyyy-MM-dd HH:mm:ss:SS
     * @param time        时间戳
     * @return 格式化后的时间字符串
     * @throws IllegalArgumentException 当patternType不在1至4的范围内时抛出异常
     */
    public static String timestampToStrTime(int patternType, long time) throws IllegalArgumentException {
        SimpleDateFormat formatter;
        switch (patternType) {
            case 1:
                formatter = sdfYTDHMS.get();
                break;
            case 2:
                formatter = sdfYTD.get();
                break;
            case 3:
                formatter = sdfUnsignedYTDHM.get();
                break;
            case 4:
                formatter = sdfHolder.get();
                break;
            case 5:
                formatter = sdfHm.get();
                break;
            default:
                throw new IllegalArgumentException("Invalid patternType. Must be between 1 and 4.");
        }
        return formatter.format(new Date(time));
    }

    /**
     * string时间->时间戳
     *
     * @param time
     * @return
     */
    public static long transitionType(String time) {
        Date parse = null;
        try {
            parse = sdfYTDHMS.get().parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return parse.getTime();
    }

    /**
     * 加时
     *
     * @param date         时间
     * @param calendarType 加时类型 Calendar.MINUTE：分钟
     * @param time         加多少
     * @return 返回
     */
    public static Calendar extraTime(Date date, int calendarType, int time) {
        Calendar nowTime = Calendar.getInstance();
        nowTime.setTime(date);
        nowTime.add(calendarType, time);
        return nowTime;
    }

    /**
     * 判断是否是当天
     *
     * @param time 时间戳
     * @return 返回
     */
    public static Boolean isCurrentTime(long time) {
        String param = timestampToStrTime(2, time);//参数时间
        String now = timestampToStrTime(2, System.currentTimeMillis());//当前时间
        if (param.equals(now)) {
            return true;
        }
        return false;
    }

    /**
     * 是否是上个月
     *
     * @param timestamp
     * @return true 是  false 否
     */
    public static boolean isTimestampFromLastMonth(long timestamp) {
        // 将时间戳转换为ZonedDateTime（或LocalDate，如果你不需要时区信息）
        ZonedDateTime dateTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
        LocalDate dateToCheck = dateTime.toLocalDate();

        // 获取当前日期
        LocalDate currentDate = LocalDate.now();

        // 获取上个月的第一天和最后一天
        LocalDate startOfLastMonth = currentDate.minus(1, ChronoUnit.MONTHS).withDayOfMonth(1);
        LocalDate endOfLastMonth = startOfLastMonth.plusMonths(1).minusDays(1);

        // 判断给定日期是否在上个月范围内
        return !dateToCheck.isAfter(endOfLastMonth) && !dateToCheck.isBefore(startOfLastMonth);
    }

    /**
     * 是否是上个月或更早的
     *
     * @param timestamp
     * @return true 是  false 否
     */
    public static boolean isTimestampFromLastMonthOrBefore(long timestamp) {
        // 将时间戳转换为LocalDate
        LocalDate dateToCheck = Instant.ofEpochMilli(timestamp).atZone(ZoneId.systemDefault()).toLocalDate();

        // 获取当前日期
        LocalDate now = LocalDate.now();

        // 获取上个月的第一天和最后一天
        LocalDate startOfLastMonth = now.minus(1, ChronoUnit.MONTHS).withDayOfMonth(1);
        LocalDate endOfLastMonth = startOfLastMonth.plusMonths(1).minusDays(1);

        // 判断给定日期是否在上个月或更早
        return dateToCheck.isBefore(now) && (dateToCheck.isAfter(startOfLastMonth) || dateToCheck.isEqual(startOfLastMonth)) ||
                dateToCheck.isBefore(startOfLastMonth);
    }

    /**
     * 时间差 （分钟数）
     *
     * @param str 最新的活动时间
     * @return 返回值
     */
    public static long LeadTime(String str) {
        Date now_time = null; // 用户最新的活动时间
        try {
            now_time = sdfYTDHMS.get().parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Instant instant = now_time.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime(); //date转LocalDateTime
        //时间格式
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        //当前时间
        LocalDateTime startTime = LocalDateTime.now();
        //结束时间
        String localTime = df.format(localDateTime);
        LocalDateTime entime = LocalDateTime.parse(localTime, df);
        // 获得两个时间之间的相差值
        Duration dur = Duration.between(startTime, entime);
        //两个时间差的分钟数
        return dur.toMinutes();
    }

    /**
     * 时间差 （分钟数）
     *
     * @param time 最新的活动时间
     * @return 返回值
     */
    public static long LeadTime(Date time) {
        Instant instant = time.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime(); //date转LocalDateTime
        //时间格式
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        //当前时间
        LocalDateTime startTime = LocalDateTime.now();
        //结束时间
        String localTime = df.format(localDateTime);
        LocalDateTime entime = LocalDateTime.parse(localTime, df);
        // 获得两个时间之间的相差值
        Duration dur = Duration.between(startTime, entime);
        //两个时间差的分钟数
        return dur.toMinutes();
    }
}
