package com.slodon.b2b2c.enums;

import cn.hutool.core.date.DateUtil;
import com.slodon.b2b2c.core.util.TimeUtil;
import lombok.SneakyThrows;

import java.util.Calendar;
import java.util.Date;

/**
 * 统计时间类型枚举
 */
public enum StatsTimeType {

    //时
    HOUR,
    //日
    DAY,
    //周
    WEEK,
    //月
    MONTH,
    //年
    YEAR,
    ;

    /**
     * 给定时间，计算其上一个统计时间阶段的开始时间
     *
     * @param now           给定时间，在统计时间阶段之后的时间
     * @param statsTimeType 统计时间类型枚举
     * @return 统计时间阶段的开始时间
     */
    public static Date getStartTime(Date now, StatsTimeType statsTimeType) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        switch (statsTimeType) {
            case HOUR:
                calendar.add(Calendar.HOUR, -1);
                calendar.set(Calendar.MINUTE, 0);
                calendar.set(Calendar.SECOND, 0);
                calendar.set(Calendar.MILLISECOND, 0);
                return calendar.getTime();
            case DAY:
                calendar.add(Calendar.DATE, -1);
                return DateUtil.beginOfDay(calendar.getTime());
            case WEEK:
                calendar.add(Calendar.DATE, -7);
                return DateUtil.beginOfWeek(calendar.getTime());
            case MONTH:
                calendar.add(Calendar.MONTH, -1);
                return DateUtil.beginOfMonth(calendar.getTime());
            case YEAR:
                calendar.add(Calendar.YEAR, -1);
                return DateUtil.beginOfYear(calendar.getTime());
            default:
                return now;
        }
    }

    /**
     * 给定时间，计算其上一个统计时间阶段的结束时间
     *
     * @param now           给定时间，在统计时间阶段之后的时间
     * @param statsTimeType 统计时间类型枚举
     * @return 统计时间阶段的结束时间
     */
    public static Date getEndTime(Date now, StatsTimeType statsTimeType) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        switch (statsTimeType) {
            case HOUR:
                calendar.add(Calendar.HOUR, -1);
                calendar.set(Calendar.MINUTE, 59);
                calendar.set(Calendar.SECOND, 59);
                calendar.set(Calendar.MILLISECOND, 999);
                return calendar.getTime();
            case DAY:
                calendar.add(Calendar.DATE, -1);
                return DateUtil.endOfDay(calendar.getTime());
            case WEEK:
                calendar.add(Calendar.DATE, -7);
                return DateUtil.endOfWeek(calendar.getTime());
            case MONTH:
                calendar.add(Calendar.MONTH, -1);
                return DateUtil.endOfMonth(calendar.getTime());
            case YEAR:
                calendar.add(Calendar.YEAR, -1);
                return DateUtil.endOfYear(calendar.getTime());
            default:
                return now;
        }
    }

    /**
     * 获取上期开始时间
     *
     * @param now 本期开始时间
     * @param num 天数
     * @return 上期开始时间
     */
    public static Date getPreStartTime(Date now, int num) {
        //只查询近7天和近30天的数据
//        if (!(num != 7 && num != 30)) {
//            return null;
//        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        calendar.add(Calendar.DATE, -num);
        return DateUtil.beginOfDay(calendar.getTime());
    }

    /**
     * 获取上期结束时间
     *
     * @param now 本期结束时间
     * @param num 天数
     * @return 上期结束时间
     */
    public static Date getPreEndTime(Date now, int num) {
        //只查询近7天和近30天的数据
//        if (!(num != 7 && num != 30)) {
//            return null;
//        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        calendar.add(Calendar.DATE, -num);
        return DateUtil.endOfDay(calendar.getTime());
    }

    /**
     * 判断时间类型
     *
     * @param startTime        开始时间
     * @param endTime          结束时间
     * @param isNeedNaturalDay 是否需要自然日 true==说明需要查询当天24个小时的数据，false==只查询当天数据
     * @return
     */
    @SneakyThrows
    public static StatsTimeType checkTimeType(Date startTime, Date endTime, boolean isNeedNaturalDay) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endTime);
        calendar.add(Calendar.SECOND, 1); //23:59:59 加一秒变成第二天
        Integer apartDay = TimeUtil.countApartDay(startTime, calendar.getTime());
        if (apartDay == 1 && isNeedNaturalDay) {
            return isNaturalDay(startTime, endTime);
        } else if (apartDay == 7) {
            return isNaturalWeek(startTime, endTime);
        } else if (apartDay >= 28 && apartDay <= 31) {
            return isNaturalMonth(startTime, endTime);
        } else if (apartDay >= 365 && apartDay <= 366) {
            return isNaturalYear(startTime, endTime);
        } else {
            return DAY;
        }
    }

    /**
     * 获取相差天数
     *
     * @param startTime 开始时间 2021-01-01 00:00:00
     * @param endTime   结束时间 2021-01-01 23:59:59
     * @return
     */
    @SneakyThrows
    public static Integer getDifferentDay(Date startTime, Date endTime) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endTime);
        calendar.add(Calendar.SECOND, 1); //23:59:59 加一秒变成第二天
        return TimeUtil.countApartDay(startTime, calendar.getTime());
    }

    /**
     * 是否自然日
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static StatsTimeType isNaturalDay(Date startTime, Date endTime) {
        //获取当日的开始时间，并比较是否同一天
        boolean isStart = DateUtil.beginOfDay(startTime).getTime() / 1000 == startTime.getTime() / 1000;
        //获取当日的结束时间，并比较是否同一天
        boolean isEnd = DateUtil.endOfDay(endTime).getTime() / 1000 == endTime.getTime() / 1000;
        if (isStart && isEnd) {
            return HOUR;
        } else {
            return DAY;
        }
    }

    /**
     * 是否自然周
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static StatsTimeType isNaturalWeek(Date startTime, Date endTime) {
        //获取当周的开始时间，并比较是否同一天
        boolean isStart = DateUtil.beginOfWeek(startTime).getTime() / 1000 == startTime.getTime() / 1000;
        //获取当周的结束时间，并比较是否同一天
        boolean isEnd = DateUtil.endOfWeek(endTime).getTime() / 1000 == endTime.getTime() / 1000;
        if (isStart && isEnd) {
            return WEEK;
        } else {
            return DAY;
        }
    }

    /**
     * 是否自然月
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static StatsTimeType isNaturalMonth(Date startTime, Date endTime) {
        //获取当月的开始时间，并比较是否同一天
        boolean isStart = DateUtil.beginOfMonth(startTime).getTime() / 1000 == startTime.getTime() / 1000;
        //获取当月的结束时间，并比较是否同一天
        boolean isEnd = DateUtil.endOfMonth(endTime).getTime() / 1000 == endTime.getTime() / 1000;
        if (isStart && isEnd) {
            return MONTH;
        } else {
            return DAY;
        }
    }

    /**
     * 是否自然年
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static StatsTimeType isNaturalYear(Date startTime, Date endTime) {
        //获取当年的开始时间，并比较是否同一天
        boolean isStart = DateUtil.beginOfYear(startTime).getTime() / 1000 == startTime.getTime() / 1000;
        //获取当年的结束时间，并比较是否同一天
        boolean isEnd = DateUtil.endOfYear(endTime).getTime() / 1000 == endTime.getTime() / 1000;
        if (isStart && isEnd) {
            return YEAR;
        } else {
            return DAY;
        }
    }
}
