package com.fizz.business.utils;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author chenhao
 * @date 2023/8/22
 */
public class DateSplitUtil {
    public enum IntervalType {
        DAY,
        HOUR,
        MINUTE,
        SECOND,
        ;
    }

    /**
     * 时间切割
     * @param startTime    被切割的开始时间
     * @param endTime      被切割的结束时间
     * @param intervalType
     * @param interval     >0
     * @return
     */
    public static List<DateSplit> splitDate(LocalDateTime startTime, LocalDateTime endTime, IntervalType intervalType, int interval) {
        if (interval < 0) {
            return Collections.emptyList();
        }
        if (startTime.isAfter(endTime)) {
            return Collections.emptyList();
        }

        if (intervalType == IntervalType.DAY) {
            return splitByDay(startTime, endTime, interval);
        }
        if (intervalType == IntervalType.HOUR) {
            return splitByHour(startTime, endTime, interval);
        }
        if (intervalType == IntervalType.MINUTE) {
            return splitByMinute(startTime, endTime, interval);
        }
        if (intervalType == IntervalType.SECOND) {
            return splitBySecond(startTime, endTime, interval);
        }
        return Collections.emptyList();
    }

    /**
     * 按照小时切割时间区间
     */
    public static List<DateSplit> splitByHour(LocalDateTime startTime, LocalDateTime endTime, int intervalHours) {
        if (startTime.isAfter(endTime)) {
            return Collections.emptyList();
        }

        List<DateSplit> dateSplits = new ArrayList<>(256);

        DateSplit param = new DateSplit();
        do {
            LocalDateTime tempEndTime = startTime.plusHours(intervalHours);
            if (tempEndTime.isAfter(endTime)) {
                tempEndTime = endTime;
            }
            param.setStartTime(startTime);
            param.setEndTime(tempEndTime);

            dateSplits.add(new DateSplit(param.getStartTime(), param.getEndTime()));

            startTime = tempEndTime;
        } while (!startTime.isEqual(endTime));
        return dateSplits;
    }

    /**
     * 按照秒切割时间区间
     */
    public static List<DateSplit> splitBySecond(LocalDateTime startTime, LocalDateTime endTime, int intervalSeconds) {
        if (startTime.isAfter(endTime)) {
            return Collections.emptyList();
        }

        List<DateSplit> dateSplits = new ArrayList<>(256);

        DateSplit param = new DateSplit();
        do {
            LocalDateTime tempEndTime = startTime.plusSeconds(intervalSeconds);
            if (tempEndTime.isAfter(endTime)) {
                tempEndTime = endTime;
            }
            param.setStartTime(startTime);
            param.setEndTime(tempEndTime);

            dateSplits.add(new DateSplit(param.getStartTime(), param.getEndTime()));

            startTime = tempEndTime;
        } while (!startTime.isEqual(endTime));
        return dateSplits;
    }

    /**
     * 按照天切割时间区间
     */
    public static List<DateSplit> splitByDay(LocalDateTime startTime, LocalDateTime endTime, int intervalDays) {
        if (startTime.isAfter(endTime)) {
            return Collections.emptyList();
        }

        List<DateSplit> dateSplits = new ArrayList<>(256);

        DateSplit param = new DateSplit();
        do {
            LocalDateTime tempEndTime = startTime.plusDays(intervalDays);
            if (tempEndTime.isAfter(endTime)) {
                tempEndTime = endTime;
            }
            param.setStartTime(startTime);
            param.setEndTime(tempEndTime);

            dateSplits.add(new DateSplit(param.getStartTime(), param.getEndTime()));

            startTime = tempEndTime;
        } while (!startTime.isEqual(endTime));
        return dateSplits;
    }

    /**
     * 按照分钟切割时间区间
     *
     * @param startTime
     * @param endTime
     * @param intervalMinutes
     * @return
     */
    public static List<DateSplit> splitByMinute(LocalDateTime startTime, LocalDateTime endTime, int intervalMinutes) {
        if (startTime.isAfter(endTime)) {
            return Collections.emptyList();
        }

        List<DateSplit> dateSplits = new ArrayList<>(256);

        DateSplit param = new DateSplit();
        do {
            LocalDateTime tempEndTime = startTime.plusMinutes(intervalMinutes);
            if (tempEndTime.isAfter(endTime)) {
                tempEndTime = endTime;
            }
            param.setStartTime(startTime);
            param.setEndTime(tempEndTime);

            dateSplits.add(new DateSplit(param.getStartTime(), param.getEndTime()));

            startTime = tempEndTime;
        } while (!startTime.isEqual(endTime));
        return dateSplits;
    }

    public static long toMillSeconds(LocalDateTime dateTime) {
        return dateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class DateSplit {
        private LocalDateTime startTime;
        private LocalDateTime endTime;
    }

    public static void main(String[] args) {
        LocalDateTime a = LocalDateTime.of(2023, 6, 30, 12, 0);
        LocalDateTime b = LocalDateTime.of(2023, 7, 1, 11, 44);
        System.out.println(splitDate(a, b, IntervalType.DAY, 1));
        System.out.println(splitDate(a, b, IntervalType.HOUR, 1));
        System.out.println(splitDate(a, b, IntervalType.MINUTE, 15));
        System.out.println(splitDate(a, b, IntervalType.SECOND, 90));
        List<DateSplit> dateSplits = splitDate(a, b, IntervalType.MINUTE, 15);
        dateSplits.forEach(d -> {
            long start = toMillSeconds(d.getStartTime());
            long end= toMillSeconds(d.getEndTime());
            System.out.println(start + "-" + end);
        });

        System.out.println(LocalDateTime.now().plusHours(-24));
    }
}
