package com.bocloud.ims.service.utils;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.ims.common.enums.TimeUnit;

import java.text.ParseException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * 日期时间工具类
 *
 * @author zhangdi
 * @since Nov 5,2019
 */
public class DateUtil {

    /**
     * 毫秒数转为时分秒
     *
     * @param millisecond 毫秒数
     * @return
     */
    public static String dateConvert(double millisecond) {
        long time = (long) millisecond / 1000;
        long hour = (time % (3600 * 24)) / 3600;
        long min = (time % (3600 * 24)) % 3600 / 60;
        long second = (time % (3600 * 24)) % 3600 % 60;
        if (hour == 0) {
            if (min == 0) {
                return second + "秒";
            } else {
                return min + "分" + second + "秒";
            }
        } else {
            return hour + "时" + min + "分" + second + "秒";
        }
    }

    public static String localDateTimeFormat(LocalDateTime localDateTime) {
        return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    public static String localDateTimeFormatUTC(LocalDateTime localDateTime) {
        return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
    }

    public static String localDateTimeMinFormat(LocalDateTime localDateTime) {
        return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:00"));
    }

    public static String localDateTimeHourFormat(LocalDateTime localDateTime) {
        return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00"));
    }

    public static String localDateFormat(LocalDateTime localDateTime) {
        return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }

    public static String monthDateFormat(LocalDateTime localDateTime) {
        return localDateTime.format(DateTimeFormatter.ofPattern("MM-dd"));
    }

    public static String localMothFormat(LocalDateTime localDateTime) {
        return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-01"));
    }

    public static Map<String, String> timeToMap(String time) {
        LocalDateTime now = LocalDateTime.now();
        Map<String, String> timeMap = new HashMap<>();
        LocalDateTime startTime = null;
        if (TimeUnit.DAYS.getName().equals(time)) {
            startTime = now.minus(1, ChronoUnit.DAYS);
        }
        if (TimeUnit.WEEKS.getName().equals(time)) {
            startTime = now.minus(1, ChronoUnit.WEEKS);
        }
        if (TimeUnit.WEEKDAYS.getName().equals(time)) {
            startTime = now.minus(1, ChronoUnit.WEEKS).plusDays(1L);
        }
        if (TimeUnit.MONTHS.getName().equals(time)) {
            startTime = now.minus(1, ChronoUnit.MONTHS);
        }
        if (TimeUnit.QUARTER_YEARS.getName().equals(time)) {
            startTime = now.minus(3, ChronoUnit.MONTHS);
        }
        if (TimeUnit.HALF_YEARS.getName().equals(time)) {
            startTime = now.minus(6, ChronoUnit.MONTHS);
        }
        if (TimeUnit.YEARS.getName().equals(time)) {
            startTime = now.minus(1, ChronoUnit.YEARS);
        }
        timeMap.put("start", startTime != null ? DateUtil.localDateTimeFormat(startTime) : DateUtil.localDateTimeFormat(now.minusMonths(1)));
        timeMap.put("end", DateUtil.localDateTimeFormat(now));
        timeMap.put("unit", time);
        return timeMap;
    }

    public static Map<String, String> timeToMapUTC(String time) {
        LocalDateTime now = LocalDateTime.now(ZoneId.of("UTC"));
        Map<String, String> timeMap = new HashMap<>();
        LocalDateTime startTime = null;
        if (TimeUnit.DAYS.getName().equals(time)) {
            startTime = now.minus(1, ChronoUnit.DAYS);
        }
        if (TimeUnit.WEEKS.getName().equals(time)) {
            startTime = now.minus(1, ChronoUnit.WEEKS);
        }
        if (TimeUnit.WEEKDAYS.getName().equals(time)) {
            startTime = now.minus(1, ChronoUnit.WEEKS).plusDays(1L);
        }
        if (TimeUnit.MONTHS.getName().equals(time)) {
            startTime = now.minus(1, ChronoUnit.MONTHS);
        }
        if (TimeUnit.QUARTER_YEARS.getName().equals(time)) {
            startTime = now.minus(3, ChronoUnit.MONTHS);
        }
        if (TimeUnit.HALF_YEARS.getName().equals(time)) {
            startTime = now.minus(6, ChronoUnit.MONTHS);
        }
        if (TimeUnit.YEARS.getName().equals(time)) {
            startTime = now.minus(1, ChronoUnit.YEARS);
        }
        timeMap.put("start", startTime != null ? DateUtil.localDateTimeFormatUTC(startTime) : DateUtil.localDateTimeFormatUTC(now.minusMonths(1)));
        timeMap.put("end", DateUtil.localDateTimeFormatUTC(now));
        timeMap.put("unit", time);
        return timeMap;
    }

    /**
     * 趋势图用这个方法(多线程处理查询)
     *
     * @param params
     * @return
     * @throws ParseException
     */
    public static List<String> timeToList(JSONObject params) {
        List<String> timeList = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        //今天开始时间+1 计算周期结束的时间
        String time = params.getString("time");

        if (null != time && !time.equals("")) {
            if (TimeUnit.DAYS.getName().equals(time)) {
                LocalDateTime start = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), now.getHour(), 0, 0, 0);
                LocalDateTime endTime = start.minus(1, ChronoUnit.DAYS);
                for (LocalDateTime next = start; next.isAfter(endTime) || next.isEqual(endTime); next = next.minusHours(1)) {
                    timeList.add(DateUtil.localDateTimeHourFormat(next));
                }
            }
            if (TimeUnit.WEEKS.getName().equals(time)) {
                LocalDateTime start = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), now.getHour(), 0, 0, 0);
                LocalDateTime endTime = start.minus(1, ChronoUnit.WEEKS);
                for (LocalDateTime next = start; next.isAfter(endTime) || next.isEqual(endTime); next = next.minusHours(6)) {
                    timeList.add(DateUtil.localDateTimeHourFormat(next));
                }
            }
            if (TimeUnit.MONTHS.getName().equals(time)) {
                LocalDateTime start = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), 0, 0, 0, 0);
                LocalDateTime endTime = start.minus(1, ChronoUnit.MONTHS);
                for (LocalDateTime next = start; next.isAfter(endTime) || next.isEqual(endTime); next = next.minusDays(1)) {
                    timeList.add(DateUtil.localDateFormat(next));
                }
            }
            if (TimeUnit.QUARTER_YEARS.getName().equals(time)) {
                LocalDateTime start = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), 0, 0, 0, 0);
                LocalDateTime endTime = start.minus(3, ChronoUnit.MONTHS);
                for (LocalDateTime next = start; next.isAfter(endTime) || next.isEqual(endTime); next = next.minusDays(3)) {
                    timeList.add(DateUtil.localDateFormat(next));
                }
            }
            if (TimeUnit.HALF_YEARS.getName().equals(time)) {
                LocalDateTime start = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), 0, 0, 0, 0);
                LocalDateTime endTime = start.minus(6, ChronoUnit.MONTHS);
                for (LocalDateTime next = start; next.isAfter(endTime) || next.isEqual(endTime); next = next.minusWeeks(1)) {
                    timeList.add(DateUtil.localDateFormat(next));
                }
            }
            if (TimeUnit.YEARS.getName().equals(time)) {
                LocalDateTime start = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), 0, 0, 0, 0);
                LocalDateTime endTime = start.minus(1, ChronoUnit.YEARS);
                for (LocalDateTime next = start; next.isAfter(endTime) || next.isEqual(endTime); next = next.minusWeeks(2)) {
                    timeList.add(DateUtil.localDateFormat(next));
                }
            }
            Collections.reverse(timeList);
        } else {
            String startTime = params.getString("startTime") != null ? params.getString("startTime") : DateUtil.localDateTimeFormat(now.minusMonths(1).minusDays(1));
            String endTime = params.getString("endTime") != null ? params.getString("endTime") : DateUtil.localDateTimeFormat(now);
            timeList = timeToList(startTime, endTime);
        }
        return timeList;
    }

    public static List<String> timeToList(String startTime, String endTime) {
        List<String> timeList = new ArrayList<>();
        LocalDateTime start = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime end = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Duration between = Duration.between(start, end);
        long hours = between.toHours();
        if (hours >= 24 * 365 * 1.5) {
            //超过一年
            end = LocalDateTime.of(end.getYear(), end.getMonth(), 1, 0, 0, 0, 0);
            for (LocalDateTime next = end; next.isAfter(start) || next.isEqual(start); next = next.minusMonths(1)) {
                timeList.add(DateUtil.localMothFormat(next));
            }
        } else if (hours >= 24 * 365) {
            //超过一年
            end = LocalDateTime.of(end.getYear(), end.getMonth(), end.getDayOfMonth(), 0, 0, 0, 0);
            for (LocalDateTime next = end; next.isAfter(start) || next.isEqual(start); next = next.minusWeeks(2)) {
                timeList.add(DateUtil.localDateFormat(next));
            }
        } else if (hours >= 24 * 30 * 6) {
            //超过半年
            end = LocalDateTime.of(end.getYear(), end.getMonth(), end.getDayOfMonth(), 0, 0, 0, 0);
            for (LocalDateTime next = end; next.isAfter(start) || next.isEqual(start); next = next.minusWeeks(1)) {
                timeList.add(DateUtil.localDateFormat(next));
            }
        } else if (hours >= 24 * 30 * 3) {
            //超过三个月
            end = LocalDateTime.of(end.getYear(), end.getMonth(), end.getDayOfMonth(), 0, 0, 0, 0);
            for (LocalDateTime next = end; next.isAfter(start) || next.isEqual(start); next = next.minusDays(3)) {
                timeList.add(DateUtil.localDateFormat(next));
            }
        } else if (hours >= 24 * 30) {
            //超过一个月
            end = LocalDateTime.of(end.getYear(), end.getMonth(), end.getDayOfMonth(), 0, 0, 0, 0);
            for (LocalDateTime next = end; next.isAfter(start) || next.isEqual(start); next = next.minusDays(1)) {
                timeList.add(DateUtil.localDateFormat(next));
            }
        } else if (hours >= 24 * 15) {
            //超过半个月
            end = LocalDateTime.of(end.getYear(), end.getMonth(), end.getDayOfMonth(), end.getHour(), 0, 0, 0);
            for (LocalDateTime next = end; next.isAfter(start) || next.isEqual(start); next = next.minusHours(6)) {
                timeList.add(DateUtil.localDateTimeHourFormat(next));
            }
        } else if (hours >= 24 * 7) {
            //超过一周
            end = LocalDateTime.of(end.getYear(), end.getMonth(), end.getDayOfMonth(), end.getHour(), 0, 0, 0);
            for (LocalDateTime next = end; next.isAfter(start) || next.isEqual(start); next = next.minusHours(6)) {
                timeList.add(DateUtil.localDateTimeHourFormat(next));
            }
        } else if (hours >= 24) {
            end = LocalDateTime.of(end.getYear(), end.getMonth(), end.getDayOfMonth(), end.getHour(), 0, 0, 0);
            for (LocalDateTime next = end; next.isAfter(start) || next.isEqual(start); next = next.minusHours(1)) {
                timeList.add(DateUtil.localDateTimeHourFormat(next));
            }
        } else {
            end = LocalDateTime.of(end.getYear(), end.getMonth(), end.getDayOfMonth(), end.getHour(), end.getMinute(), 0, 0);
            for (LocalDateTime next = end; next.isAfter(start) || next.isEqual(start); next = next.minusMinutes(30)) {
                timeList.add(DateUtil.localDateTimeMinFormat(next));
            }
        }
        Collections.reverse(timeList);
        return timeList;
    }

    public static int dayBetween(String startTime, String endTime) {

        LocalDateTime start = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime end = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Duration between = Duration.between(start, end);
        long hours = between.toHours();
        return (int) (hours % 24 == 0 ? hours / 24 : (hours / 24) + 1);
    }

    public static void main(String[] args) {
        JSONObject object = new JSONObject();
        object.put("time", "Years");
        List<String> toList = timeToList(object);
        for (String s : toList) {
            System.out.println(s);
        }
        LocalDateTime now = LocalDateTime.now();
        System.out.println(localDateTimeFormat(now));
        System.out.println(localDateTimeHourFormat(now));
        System.out.println(localDateTimeMinFormat(now));
        System.out.println(localDateFormat(now));
        System.out.println(localMothFormat(now));
    }
}