package com.ruoyi.test;


import com.ruoyi.common.utils.Arith;
import com.ruoyi.doubledefense.domain.CheckTaskInventory;
import org.junit.jupiter.api.Test;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 生成1年内的间隔为1个月的开始结束时间
 */
public class TestDateYearV1 {

    public static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

    public static SimpleDateFormat formatTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");


//    生成任务清单规则，假如频次为2：
//      hourTask  1、小时：00:00  <= 任务1 <= 29:59    ；30:00    <= 任务2 <= 59:59
//      dayTask   2、天：00:00:00 <= 任务1 <= 11:59:59 ；12:00:00 <= 任务2 <= 23:59:59
//      monthTask 3、月：1号      <= 任务1 <= 15号     ；16号     <= 任务2 <= (28/29/30/31)
//      yeayTask  4、年：1月1日   <= 任务1 <= 6月30日  ；7月:1日  <= 任务2 <= 12月31日

    public static void main(String[] args) throws Exception {
        //频次数量
        int count = 3;
        List<CheckTaskInventory> list = null;

        System.out.println();
        list = hourTask(count);
        System.out.println("==============小时===================");
        for (int index = 1; index <= list.size(); index++) {
            CheckTaskInventory data = list.get(index - 1);
            System.out.println(index + "\t" + formatTime.format(data.getStartDate()) + "\t" + formatTime.format(data.getEndDate()));
        }

        System.out.println();
        list = null;
        list = dayTask(count);
        System.out.println();
        System.out.println("==============天===================");
        for (int index = 1; index <= list.size(); index++) {
            CheckTaskInventory data = list.get(index - 1);
            System.out.println(index + "\t" + formatTime.format(data.getStartDate()) + "\t" + formatTime.format(data.getEndDate()));
        }

        System.out.println();
        list = null;
        list = monthTask(count);
        System.out.println();
        System.out.println("==============月===================");
        for (int index = 1; index <= list.size(); index++) {
            CheckTaskInventory data = list.get(index - 1);
            System.out.println(index + "\t" + formatTime.format(data.getStartDate()) + "\t" + formatTime.format(data.getEndDate()));
        }

        System.out.println();
        list = null;
        list = yeayTask(count);
        System.out.println();
        System.out.println("==============年===================");
        for (int index = 1; index <= list.size(); index++) {
            CheckTaskInventory data = list.get(index - 1);
            System.out.println(index + "\t" + formatTime.format(data.getStartDate()) + "\t" + formatTime.format(data.getEndDate()));
        }


//        Date start = formatTime.parse("2023-01-01 00:00:00.000");
//        Date end = formatTime.parse("2023-01-01 01:00:00.000");


//        Calendar calendar = Calendar.getInstance();
//        calendar.setTime(new Date());
//        calendar.set(Calendar.YEAR,2024);
//        calendar.set(Calendar.MONTH,1);//月份取值范围[0,11]
//        int month = calendar.get(Calendar.MONTH);
//        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
//        int lastDayOfMonth = calendar.getActualMaximum(Calendar.DATE);


//        splitByTime(start, end, count);

//        List<CheckTaskInventory> list = monthTask(count);
//        List<CheckTaskInventory> list = yeayTask(count);

//        System.out.println("==============返回结果===================");
//        for (int index = 1; index <= list.size(); index++) {
//            CheckTaskInventory data = list.get(index - 1);
//            System.out.println(index + "\t" + formatTime.format(data.getStartDate()) + "\t" + formatTime.format(data.getEndDate()));
//        }
    }

    /**
     * 每小时指定N次，生成1天内所有的任务
     *
     * @param count 执行的次数
     */
    public static List<CheckTaskInventory> hourTask(int count) {
        List<CheckTaskInventory> list = new ArrayList<>();

        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 1); //增加一天

        //循环0点到23点
        int total = 24;
        for (int i = 0; i < total; i++) {
            //1、得到下一天的开始时间和结束时间 00:00:00.000 23:59:59.999
            Date start, end = null;
            calendar.set(Calendar.HOUR_OF_DAY, i); //时
            calendar.set(Calendar.MINUTE, 0); //分
            calendar.set(Calendar.SECOND, 0); //秒
            calendar.set(Calendar.MILLISECOND, 0); //毫秒
            start = calendar.getTime();

            calendar.set(Calendar.MINUTE, 59); //分
            calendar.set(Calendar.SECOND, 59); //秒
            calendar.set(Calendar.MILLISECOND, 999); //毫秒
            end = calendar.getTime();

            //2、根据频次N，生成时间段的开始时间和结束时间
            list.addAll(splitByTime(start, end, count));

            //3、设置下一小时的开始时间
            if (i < total - 1) {
                calendar.set(Calendar.HOUR_OF_DAY, i + 1); //时
                calendar.set(Calendar.MINUTE, 0); //分
                calendar.set(Calendar.SECOND, 0); //秒
                calendar.set(Calendar.MILLISECOND, 0); //毫秒
            }
        }
        return list;
    }

    /**
     * 每天指定N次，生成1天内所有的任务
     *
     * @param count 执行的次数
     */
    public static List<CheckTaskInventory> dayTask(int count) {
        //1、得到下一天的开始时间和结束时间 00:00:00.000 23:59:59.999
        Date start, end = null;
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 1); //增加一天
        calendar.set(Calendar.HOUR_OF_DAY, 0); //时
        calendar.set(Calendar.MINUTE, 0); //分
        calendar.set(Calendar.SECOND, 0); //秒
        calendar.set(Calendar.MILLISECOND, 0); //毫秒
        start = calendar.getTime();
        calendar.set(Calendar.HOUR_OF_DAY, 23); //时
        calendar.set(Calendar.MINUTE, 59); //分
        calendar.set(Calendar.SECOND, 59); //秒
        calendar.set(Calendar.MILLISECOND, 999); //毫秒
        end = calendar.getTime();
        //2、根据频次N，生成时间段的开始时间和结束时间
        return splitByTime(start, end, count);
    }

    /**
     * 每月指定N次，生成1个月的任务
     * 3、月：1号      <= 任务1 <= 15号     ；16号     <= 任务2 <= (28/29/30/31)
     *
     * @param count 执行的次数
     */
    public static List<CheckTaskInventory> monthTask(int count) {
        //1、得到下一天的开始时间和结束时间 00:00:00.000 23:59:59.999
        Date start, end = null;
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.setTime(new Date());
//        calendar.set(Calendar.YEAR,2024);
//        calendar.set(Calendar.MONTH,1);//月份取值范围[0,11]
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        int lastDayOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        //每个月的最后一天才可以生成，其他时段不可以生成
        if (dayOfMonth != lastDayOfMonth) {
            return new ArrayList<>();
        }

//        System.out.println(lastDayOfMonth + "\t" + dayOfMonth);

        //增加一天为下月第一天
        calendar.add(Calendar.DATE, 1); //增加一天
        calendar.set(Calendar.HOUR_OF_DAY, 0); //时
        calendar.set(Calendar.MINUTE, 0); //分
        calendar.set(Calendar.SECOND, 0); //秒
        calendar.set(Calendar.MILLISECOND, 0); //毫秒
        start = calendar.getTime();


        //通过下月第1天取本月最后一天
        calendar.add(Calendar.MONTH, 1); //增加一月
        calendar.set(Calendar.MILLISECOND, -1); //偏移1毫秒
        end = calendar.getTime();

//        System.out.println(formatTime.format(start) + "\t" + formatTime.format(end));

        //2、根据频次N，生成时间段的开始时间和结束时间
        return splitByTime(start, end, count);
    }

    /**
     * 每年指定N次，生成1年的任务
     *
     * @param count 执行的次数
     */
    public static List<CheckTaskInventory> yeayTask(int count) {
        //1、得到下一天的开始时间和结束时间 00:00:00.000 23:59:59.999
        Date start, end = null;
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.setTime(new Date());
//        calendar.set(Calendar.YEAR,2024);
//        calendar.set(Calendar.MONTH,1);//月份取值范围[0,11]
        int month = calendar.get(Calendar.MONTH);
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        int lastDayOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        //每年最后一个月的最后一天才可以生成，其他时段不可以生成
        if (month != 11 || dayOfMonth != lastDayOfMonth) {
            return new ArrayList<>();
        }

        //下年第一天
        calendar.add(Calendar.DATE, 1); //增加一天
        calendar.set(Calendar.HOUR_OF_DAY, 0); //时
        calendar.set(Calendar.MINUTE, 0); //分
        calendar.set(Calendar.SECOND, 0); //秒
        calendar.set(Calendar.MILLISECOND, 0); //毫秒
        start = calendar.getTime();
        //下年最后一天
        calendar.set(Calendar.MONTH, 11); //12月
        calendar.set(Calendar.DAY_OF_MONTH, 31); //31日
        calendar.set(Calendar.HOUR_OF_DAY, 23); //时
        calendar.set(Calendar.MINUTE, 59); //分
        calendar.set(Calendar.SECOND, 59); //秒
        calendar.set(Calendar.MILLISECOND, 999); //毫秒
        end = calendar.getTime();
        //2、根据频次N，生成时间段的开始时间和结束时间
        return splitByTime(start, end, count);
    }

    /**
     * 生成任务的开始时间和结束时间
     *
     * @param start 开始时间
     * @param end   结束时间
     */
    public static List<CheckTaskInventory> splitByTime(Date start, Date end, int count) {
        System.out.println(formatTime.format(start) + "\t" + formatTime.format(end));
        List<CheckTaskInventory> list = new ArrayList<>();
        CheckTaskInventory inventory = null;
        System.out.println("频次数量 = " + count);

        //1、计算相差的毫秒数
        long shiJianCha = end.getTime() - start.getTime();
        System.out.println("时间差（毫秒值）" + shiJianCha);

        //2、按频次平分时间
        long timeInterval = shiJianCha / count;
//        System.out.println("时间间隔（毫秒） = " + timeInterval);
//        System.out.println("时间间隔（秒） = " + (timeInterval / 1000));
        System.out.println("时间间隔（分） = " + (timeInterval / 1000 / 60));
//        System.out.println("时间间隔（小时） = " + (timeInterval / 1000 / 60 / 60));

        //3、设置开始时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(start);

//        int index = 1;
//        while (calendar.getTime().before(end)) {
        for (int index = 1; index <= count; index++) {
            Date startTime = calendar.getTime();
            //下一段的开始时间
            Date nextMillisecond = getNextMillisecond(calendar, timeInterval);

            //本段的结束时间：结束时间往前偏移1毫秒
            Calendar endCalendar = Calendar.getInstance();
            endCalendar.setTime(nextMillisecond);
            Date endTime = getNextMillisecond(endCalendar, -1);
            System.out.println(index + "\t" + formatTime.format(startTime) + "\t" + formatTime.format(endTime));
            inventory = new CheckTaskInventory();
            inventory.setStartDate(startTime);
            if (index == count) {
                inventory.setEndDate(end);
            } else {
                inventory.setEndDate(endTime);
            }
            list.add(inventory);
            //将第二段的开始的时间设置进去
            if (index < count)
                calendar.setTime(nextMillisecond);
        }
        return list;
    }

    /**
     * 日期偏移 单位：毫秒
     *
     * @param calendar
     * @param unit     需要偏移的单元（毫秒）
     * @return
     */
    public static Date getNextMillisecond(Calendar calendar, long unit) {
        Calendar tempCalendar = Calendar.getInstance();
        tempCalendar.setTime(calendar.getTime());

        //处理整数溢出
        int maxValue = Integer.MAX_VALUE;
        //不会溢出直接偏移
        if (unit < maxValue) {
            tempCalendar.add(Calendar.MILLISECOND, Math.toIntExact(unit));
        }
        //会溢出，分次偏移
        else {
//            long page = unit / maxValue;
//            long xiaoShu = unit % maxValue;
//            page = xiaoShu == 0 ? page : page + 1;
//            for (long i = 0; i < page; i++)
            while (unit > 0) {
                if (unit > maxValue) {
                    tempCalendar.add(Calendar.MILLISECOND, maxValue);
                } else {
                    tempCalendar.add(Calendar.MILLISECOND, Math.toIntExact(unit));
                }
                unit = unit - maxValue;
            }

        }
        return tempCalendar.getTime();
    }

    @Test
    public void testQueryEndDayOfMonth() throws Exception {
//        for (int i = 1; i < 13; i++) {
//            System.out.println("2021年" + i + "月最后一天为：" + TestDateYearV1.queryEndDayOfMonth(2021, i));
//        }
        Calendar c = Calendar.getInstance();
        c.clear();
//        c.set(Calendar.YEAR, year);
//        c.set(Calendar.MONTH, month - 1);
        Date date = formatTime.parse("2023-06-01 00:00:00.000");
        c.setTime(date);
        int month = c.get(Calendar.MONTH);

        System.out.println("month = " + month + "月 " + formatTime.format(c.getTime()));
    }

    public static int queryEndDayOfMonth(Integer year, int month) {
        Calendar c = Calendar.getInstance();
        c.clear();

//        c.set(Calendar.DAY_OF_MONTH, 1);
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, month - 1);
        int actualMaximum = c.getActualMaximum(Calendar.DAY_OF_MONTH);
        int day = c.getActualMaximum(Calendar.DATE);
        System.out.println(actualMaximum + "  " + day);
        return actualMaximum;
    }
}
