package com.tuoheng.admin.utils;

import com.tuoheng.admin.enums.InspectionCycleTypeEnum;
import com.tuoheng.common.core.utils.DateUtils;
import com.tuoheng.common.core.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: 吴彬
 * @CreateTime: 2023-06-15  10:13
 * @Description: 周期性计划计算下次执行时间工具类
 * @Version: 1.0
 */
@Slf4j
public class InspectionCycleNextTimeUtil {

    /**
     * 获取下一次执行时间
     *
     * @param type           执行类型：1,单次;2,每天;3,每周;4,每月
     * @param beginDate      开始日期    yyyy-MM-dd
     * @param cycleTime      循环执行时间 HH:mm:SS
     * @param cycleFrequency 循环频率：1~7,每周；1~31,每月
     * @return
     */
    public static Date getCycleNextTime(int type, Date beginDate, Date cycleTime, String cycleFrequency) {
        Calendar cal = Calendar.getInstance(Locale.CHINA);
        cal.setTime(cycleTime);
        int hour = cal.get(Calendar.HOUR_OF_DAY);//获取当前处于一天中的第几个小时，
        int minute = cal.get(Calendar.MINUTE);//获取当前·分钟数
        int second = cal.get(Calendar.SECOND);//获取当前秒数

        //设置年月日+循环执行时间,作为开始日期
        Calendar calBegin = Calendar.getInstance(Locale.CHINA);
        calBegin.setTime(beginDate);
        calBegin.set(Calendar.HOUR_OF_DAY, hour);//时
        calBegin.set(Calendar.MINUTE, minute);//分
        calBegin.set(Calendar.SECOND, second);//秒
        Date beginDateTime = calBegin.getTime();
        //每天
        if (InspectionCycleTypeEnum.EVERYDAY.getCode() == type) {
            if (DateUtils.now().after(beginDateTime)) {//当前时间大于循环执行时间点则取下一天
                return DateUtils.addDateTimeToDate(beginDateTime, 1, 0, 0, 0);
            } else {//当前时间小于等于于循环执行时间点则取当天
                return beginDateTime;
            }
        }
        //每周
        else if (InspectionCycleTypeEnum.EVERYWEEK.getCode() == type) {
            if (StringUtils.isEmpty(cycleFrequency)) {
                return null;
            }
            String[] split = cycleFrequency.split(",");
            /**
             * 根据循环频率计算出所有频率对应的下次执行时间
             */
            List<Date> dateStrList = Arrays.stream(split).map(item -> {
                try {
                    String nextCycleDay = DateUtils.getNextCycleDay(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, beginDateTime), "0", String.valueOf(item));
                    return DateUtils.parseDate(nextCycleDay, DateUtils.YYYY_MM_DD_HH_MM_SS);
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }).collect(Collectors.toList());

            /**
             * 获取日期列表中离当前日期最近的一个日期
             */
            String latestDate = DateUtils.getLatstDate(dateStrList);
            try {
                return DateUtils.parseDate(latestDate, DateUtils.YYYY_MM_DD_HH_MM_SS);
            } catch (Exception e) {
                log.error("获取下次执行时间异常，执行类型：{}，循环频率：{},异常信息：{}", type, cycleFrequency, e);
            }
        }
        //每月
        else if (InspectionCycleTypeEnum.EVERYMONTH.getCode() == type) {
            if (StringUtils.isEmpty(cycleFrequency)) {
                return null;
            }
            String[] split = cycleFrequency.split(",");
            /**
             * 根据循环频率计算出所有频率对应的下次执行时间
             */
            List<Date> dateStrList = Arrays.stream(split).map(item -> {
                try {
                    String nextCycleDay = DateUtils.getNextCycleDay(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, beginDateTime), "1", String.valueOf(item));
                    return DateUtils.parseDate(nextCycleDay, DateUtils.YYYY_MM_DD_HH_MM_SS);
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }).collect(Collectors.toList());

            /**
             * 获取日期列表中离当前日期最近的一个日期
             */
            String latstDate = DateUtils.getLatstDate(dateStrList);
            try {
                return DateUtils.parseDate(latstDate, DateUtils.YYYY_MM_DD_HH_MM_SS);
            } catch (Exception e) {
                log.error("获取下次执行时间异常，执行类型：{}，循环频率：{},异常信息：{}", type, cycleFrequency, e);
            }
        }
        return null;
    }

}
