package com.scpyun.platform.jilinsscgsdp.service.impl;

import cn.hutool.core.date.DateUtil;
import com.scpyun.base.core.annotation.Api;
import com.scpyun.base.core.annotation.ApiOperation;
import com.scpyun.base.core.utils.DataSourceSwitcher;
import com.scpyun.base.db.service.CommonService;
import com.scpyun.platform.jilinsscgsdp.bean.entity.FocusAreas;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;

@Api("重点领域预警服务")
@Service("areasOcus")
@Slf4j
public class FocusAreasServiceImpl {

    @Resource
    private CommonService commonService;

    @Resource(name = "threadPoolExecutor")
    private ThreadPoolExecutor threadPoolExecutor;

    private final String areasNameSpace = "com.scpyun.platform.standard.jilinsscgsdp.focusareas";

    private final String areasSnapshotNameSpace = "com.scpyun.platform.standard.jilinsscgsdp.focusareasSnapshot";

    private final String eventNameSpace = "com.scpyun.platform.standard.jilinsscgsdp.event";

    private final String supplementEventNameSpace = "com.scpyun.platform.standard.jilinsscgsdp.eventSupplement";

    @Value("${areas.focus.chain.threshold}")
    private Integer threshold;

    @ApiOperation(value = "定时任务测试", desc = "定时任务测试", nologin = true)
    public void areasOcusCount() throws InterruptedException {
        commonService.delete(areasSnapshotNameSpace+".truncateTable",null);
        //获得最开始的任务时间
        Date startDate = commonService.getObject(eventNameSpace+".getEventFirstTime",null);
        //获得当前时间
        Date enddate = new Date();
        List<LocalDateTime> monthFirstDayEnds = getMonthFirstDayEnds(startDate,enddate);
        monthFirstDayEnds.forEach(yesterdayEnd ->{
            //市份环比计算;
            List<String> cityList = commonService.findList(areasNameSpace + ".getArea", "2");
            if (cityList != null && !cityList.isEmpty()) {
                getDateCop(2, cityList, yesterdayEnd);
            } else {
                log.error("时间{}业务异常{}", new Date(), "市级别区域化异常");
            }
            //区份环比计算;
            List<String> areaList = commonService.findList(areasNameSpace + ".getArea", "3");
            if (areaList != null && !areaList.isEmpty()) {
                getDateCop(3, areaList, yesterdayEnd);
            } else {
                log.error("时间{}业务异常{}", new Date(), "区级别区域化异常");
            }

            // 省份环比计算;
            getDateCop(1, new ArrayList<>(), yesterdayEnd);
        });
        commonService.delete(areasNameSpace+".truncateTable",null);
        List<FocusAreas> list = commonService.findList( areasSnapshotNameSpace+ ".findAll", null);
        commonService.insertBatch(areasNameSpace + ".insertFocusArea", list);
    }

    public void getDateCop(Integer type, List<String> list, LocalDateTime yesterdayEnd) {
        switch (type) {
            case 1:
                log.info("开始进行当月省级环比计算");
                List<String> eventCategoryIds = commonService.findList(areasNameSpace + ".geteventCategoryId", null);
                eventCategoryIds.forEach(v -> {
//                    // 获取当前日期
//                    LocalDate today = LocalDate.now();
//                    // 判断是否是本月第一天（Day 1）
//                    if (today.getDayOfMonth() == 1) {
//                        LocalDateTime localDateTime = LocalDateTime.from(today.minusMonths(1));
//                        HashMap<String, Object> map = new HashMap<>();
//                        map.put("occurrenceTime", DateUtil.format(localDateTime, "yyyy-MM"));
//                        map.put("eventCategoryId", v);
//                        chain(map, "220000000000", "1");
//                    }
                    HashMap<String, Object> map = new HashMap<>();
                    map.put("occurrenceTime", DateUtil.format(yesterdayEnd, "yyyy-MM"));
                    map.put("eventCategoryId", v);
                    chain(map, "220000000000", "1");
                });
                log.info("结束进行当月省级环比计算");
                break;
            case 2:
                log.info("开始进行当市级环比计算");
                List<String> eventCategoryIdss = commonService.findList(areasNameSpace + ".geteventCategoryId", null);
                list.forEach(v -> {
                    eventCategoryIdss.forEach(eventCategoryId -> {
//                        // 判断是否是本月第一天（Day 1）
//                        if (today.getDayOfMonth() == 1) {
//                            LocalDateTime localDateTime = LocalDateTime.from(today.minusMonths(1));
//                            HashMap<String, Object> map = new HashMap<>();
//                            map.put("occurrenceTime", DateUtil.format(localDateTime, "yyyy-MM"));
//                            map.put("eventCategoryId", eventCategoryId);
//                            chain(map, v, "2");
//                        }
                        HashMap<String, Object> map = new HashMap<>();
                        map.put("occurrenceTime", DateUtil.format(yesterdayEnd, "yyyy-MM"));
                        map.put("eventCategoryId", eventCategoryId);
                        chain(map, v, "2");
//                        chainAfter(map,v,"2");
                    });
                });
                log.info("开始进行当市级环比计算");
                break;
            case 3:
                log.info("开始进行当区级环比计算");
                List<String> areaEventCategoryIds = commonService.findList(areasNameSpace + ".geteventCategoryId", null);
                list.forEach(v -> {
                    areaEventCategoryIds.forEach(eventCategoryId -> {
//                        // 获取当前日期
//                        LocalDate today = LocalDate.now();
//                        // 判断是否是本月第一天（Day 1）
//                        if (today.getDayOfMonth() == 1) {
//                            LocalDateTime localDateTime = LocalDateTime.from(today.minusMonths(1));
//                            HashMap<String, Object> map = new HashMap<>();
//                            map.put("occurrenceTime", DateUtil.format(localDateTime, "yyyy-MM"));
//                            map.put("eventCategoryId", eventCategoryId);
//                            chain(map, v, "3");
//                        }
                        HashMap<String, Object> map = new HashMap<>();
                        map.put("occurrenceTime", DateUtil.format(yesterdayEnd ,"yyyy-MM"));
                        map.put("eventCategoryId", eventCategoryId);
                        chain(map, v, "3");
//                        chainAfter(map,v,"3");
                    });
                });
                log.info("结束进行区级环比计算");
                break;
            default:
                log.error("区域化等级异常");
                return;
        }
    }


    public void chain(HashMap<String, Object> chainMap, String code, String level) {
        String occurrenceTime = String.valueOf(chainMap.get("occurrenceTime"));
        chainMap.put("regionLevel", level);
        chainMap.put("regionId", code);
        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .appendPattern("yyyy-MM")
                .parseDefaulting(ChronoField.DAY_OF_MONTH, 1) // 设置默认日为1
                .toFormatter();

        // 先解析为LocalDate，再转为LocalDateTime
        LocalDate localDate = LocalDate.parse(occurrenceTime, formatter);
        LocalDate occurrenceStartTime = localDate.with(TemporalAdjusters.firstDayOfMonth());
        LocalDate occurrenceEndTime = localDate.with(TemporalAdjusters.lastDayOfMonth());
        chainMap.put("occurrenceStartTime", occurrenceStartTime);
        chainMap.put("occurrenceEndTime", occurrenceEndTime);
        Integer eventCopCount = commonService.getObject(eventNameSpace + ".getEventCountAllByCode", chainMap);
        // 解析为 YearMonth
        YearMonth yearMonth = YearMonth.parse(
                occurrenceTime,
                DateTimeFormatter.ofPattern("yyyy-MM")
        );
        YearMonth previousMonth = yearMonth.minusMonths(1);

        LocalDate befOccurrenceStartTime = previousMonth.atDay(1);
        LocalDate vefOccurrenceEndTime = previousMonth.atEndOfMonth();
//        LocalDate befOccurrenceStartTime = DateUtil.parseLocalDateTime(DateUtil.format(DateUtil
//                .parseLocalDateTime(occurrenceTime).minusMonths(1),"yyyy-MM-dd HH:mm:ss"))
//                .with(TemporalAdjusters.firstDayOfMonth()).toLocalDate();
//        LocalDate vefOccurrenceEndTime =  DateUtil
//                .parseLocalDateTime(DateUtil.format(DateUtil.parseLocalDateTime(occurrenceTime)
//                        .minusMonths(1),"yyyy-MM-dd HH:mm:ss"))
//                .with(TemporalAdjusters.lastDayOfMonth()).toLocalDate();
        chainMap.put("occurrenceStartTime", befOccurrenceStartTime);
        chainMap.put("occurrenceEndTime", vefOccurrenceEndTime);
        Integer eventCopBefCount = commonService.getObject(eventNameSpace + ".getEventCountAllByCode", chainMap);
        BigDecimal calculate = calculateMoMGrowth(eventCopCount, eventCopBefCount);
        if (eventCopCount.compareTo(threshold) >= 0) {
            Integer alarmLevel;
            if (calculate.compareTo(BigDecimal.valueOf(30)) >= 0 && calculate.compareTo(BigDecimal.valueOf(50)) <= 0) {
                alarmLevel = 2;
            } else if (calculate.compareTo(BigDecimal.valueOf(50)) > 0) {
                alarmLevel = 1;
            } else {
                return;
            }
//            HashMap<String, Object> pamap = new HashMap<>();
//            pamap.put("count",eventCopCount);
//            pamap.put("percentage",calculate);
//            pamap.put("areaLevel",level);
//            pamap.put("regionCode",code);
//            pamap.put("statisticalTime",chainMap.get("occurrenceTime"));
//            pamap.put("eventCategoryId",chainMap.get("eventCategoryId"));
//            pamap.put("alarmLevel",alarmLevel);
//            int update = commonService.update(areasNameSpace + ".updateinfo", pamap);
//            if (update==0) {
            FocusAreas focusAreas = new FocusAreas();
            focusAreas.setCount(eventCopCount);
            focusAreas.setPercentage(calculate);
            focusAreas.setStatisticalTime(String.valueOf(chainMap.get("occurrenceTime")));
            focusAreas.setEventCategoryId(String.valueOf(chainMap.get("eventCategoryId")));
            focusAreas.setAreaLevel(Integer.valueOf(level));
            focusAreas.setRegionCode(code);
            focusAreas.setAlarmLevel(alarmLevel);
            commonService.insert(areasSnapshotNameSpace + ".insertFocusArea", focusAreas);
            }
//        }
    }

    public void chainAfter(HashMap<String, Object> chainMap, String code, String level) {
        String occurrenceTime = String.valueOf(chainMap.get("occurrenceTime"));
        chainMap.put("regionLevel", level);
        chainMap.put("regionId", code);
        LocalDate occurrenceStartTime = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
        LocalDate occurrenceEndTime = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
        chainMap.put("occurrenceStartTime", occurrenceStartTime);
        chainMap.put("occurrenceEndTime", occurrenceEndTime);
        Integer eventCopCount = commonService.getObject(eventNameSpace + ".getEventCountAllByCode", chainMap);
        YearMonth occurrenceTimeYearMonth = YearMonth.parse(occurrenceTime, DateTimeFormatter.ofPattern("yyyy-MM"));
        YearMonth newYearMonth = occurrenceTimeYearMonth.plusMonths(1);
        String formattedDate = newYearMonth.format(DateTimeFormatter.ofPattern("yyyy-MM"));
        chainMap.put("occurrenceTime", formattedDate);
        // 解析为 YearMonth
        YearMonth yearMonth = YearMonth.parse(
                occurrenceTime,
                DateTimeFormatter.ofPattern("yyyy-MM")
        );
        YearMonth previousMonth = yearMonth.plusMonths(1);

        LocalDate aftOccurrenceStartTime = previousMonth.atDay(1);
        LocalDate aftOccurrenceEndTime = previousMonth.atEndOfMonth();
//        LocalDate aftOccurrenceStartTime = DateUtil.parseLocalDateTime(DateUtil.format(DateUtil.parseLocalDateTime(occurrenceTime).plusMonths(1),"yyyy-MM-dd HH:mm:ss")).with(TemporalAdjusters.firstDayOfMonth()).toLocalDate();
//        LocalDate aftOccurrenceEndTime = DateUtil.parseLocalDateTime(DateUtil.format(DateUtil.parseLocalDateTime(occurrenceTime).plusMonths(1),"yyyy-MM-dd HH:mm:ss")).with(TemporalAdjusters.lastDayOfMonth()).toLocalDate();
        chainMap.put("occurrenceStartTime", aftOccurrenceStartTime);
        chainMap.put("occurrenceEndTime", aftOccurrenceEndTime);
        Integer eventCopAfTCount = commonService.getObject(eventNameSpace + ".getEventCountAllByCode", chainMap);
        BigDecimal calculate = calculateMoMGrowth(eventCopAfTCount, eventCopCount);
        HashMap<String, Object> pamap = new HashMap<>();
        if (eventCopAfTCount.compareTo(threshold) >= 0) {
            Integer alarmLevel;
            if (calculate.compareTo(BigDecimal.valueOf(30)) >= 0 && calculate.compareTo(BigDecimal.valueOf(50)) <= 0) {
                alarmLevel = 2;
            } else if (calculate.compareTo(BigDecimal.valueOf(50)) > 0) {
                alarmLevel = 1;
            } else {
                return;
            }
//            pamap.put("count", eventCopAfTCount);
//            pamap.put("percentage", calculate);
//            pamap.put("areaLevel", level);
//            pamap.put("regionCode", code);
//            pamap.put("statisticalTime", formattedDate);
//            pamap.put("eventCategoryId", chainMap.get("eventCategoryId"));
//            pamap.put("alarmLevel", alarmLevel);
//            int update = commonService.update(areasNameSpace + ".updateinfo", pamap);
//            if (update == 0) {
            FocusAreas focusAreas = new FocusAreas();
            focusAreas.setCount(eventCopAfTCount);
            focusAreas.setPercentage(calculate);
            focusAreas.setStatisticalTime(formattedDate);
            focusAreas.setEventCategoryId(String.valueOf(chainMap.get("eventCategoryId")));
            focusAreas.setAreaLevel(Integer.valueOf(level));
            focusAreas.setRegionCode(code);
            focusAreas.setAlarmLevel(alarmLevel);
            log.info("");
            commonService.insert(areasSnapshotNameSpace + ".insertFocusArea", focusAreas);
//            }
        }
    }

//    public void  copAftprovince(HashMap<String,Object> map){
//        HashMap<String, Object> param = new HashMap<>();
//        LocalDate occurrenceStartTime = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
//        LocalDate occurrenceEndTime = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
//        map.put("occurrenceStartTime",occurrenceStartTime);
//        map.put("occurrenceEndTime",occurrenceEndTime);
//        Integer copCount = commonService.getObject(eventNameSpace + ".getEventCountAll", map);
//        LocalDateTime copTime = DateUtil.parseLocalDateTime(String.valueOf(map.get("occurrenceTime")));
//        String copAft = DateUtil.format(copTime.plusMonths(1), "yyyy-MM");
//        LocalDate aftOccurrenceStartTime = DateUtil.parseLocalDateTime(copAft).with(TemporalAdjusters.firstDayOfMonth()).toLocalDate();
//        LocalDate aftOccurrenceEndTime = DateUtil.parseLocalDateTime(copAft).with(TemporalAdjusters.lastDayOfMonth()).toLocalDate();
//        param.put("occurrenceStartTime",aftOccurrenceStartTime);
//        param.put("occurrenceEndTime",aftOccurrenceEndTime);
//        param.put("occurrenceTime",copAft);
//        param.put("eventCategoryId",String.valueOf(map.get("eventCategoryId")));
//        Integer copAftCount = commonService.getObject(eventNameSpace + ".getEventCountAll", param);
//        BigDecimal calculate = calculateMoMGrowth(copAftCount, copCount);
//        if (copAftCount>threshold) {
//            Integer alarmLevel = 0;
//            if (calculate.compareTo(BigDecimal.valueOf(30))>=0&&calculate.compareTo(BigDecimal.valueOf(50))<=0){
//                alarmLevel= 2;
//            }else if(calculate.compareTo(BigDecimal.valueOf(50))>0){
//                alarmLevel= 1;
//            }else {
//                return;
//            }
//            HashMap<String, Object> pamap = new HashMap<>();
//            pamap.put("count",copAftCount);
//            pamap.put("percentage",calculate);
//            pamap.put("areaLevel",1);
//            pamap.put("regionCode","220000000000");
//            pamap.put("statisticalTime",String.valueOf(map.get("occurrenceTime")));
//            pamap.put("eventCategoryId",String.valueOf(map.get("eventCategoryId")));
//            pamap.put("alarmLevel",alarmLevel);
//            int update = commonService.update(areasNameSpace + ".updateinfo", pamap);
//            if (update == 0) {
//                FocusAreas focusAreas = new FocusAreas();
//                focusAreas.setCount(copAftCount);
//                focusAreas.setPercentage(calculate);
//                focusAreas.setStatisticalTime(String.valueOf(map.get("occurrenceTime")));
//                focusAreas.setEventCategoryId(String.valueOf(map.get("eventCategoryId")));
//                focusAreas.setAreaLevel(1);
//                focusAreas.setRegionCode("220000000000");
//                focusAreas.setAlarmLevel(alarmLevel);
//                commonService.insert(areasNameSpace, focusAreas);
//            }
//        }
//    }
//
//    public void befprovince(HashMap<String,Object> map){
//        HashMap<String, Object> param = new HashMap<>();
//        LocalDate occurrenceStartTime = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
//        LocalDate occurrenceEndTime = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
//        map.put("occurrenceStartTime",occurrenceStartTime);
//        map.put("occurrenceEndTime",occurrenceEndTime);
//        Integer copCount = commonService.getObject(eventNameSpace + ".getEventCountAll", map);
//        LocalDateTime copTime = DateUtil.parseLocalDateTime(String.valueOf(map.get("occurrenceTime")));
//        String copBef = DateUtil.format(copTime.minusMonths(1), "yyyy-MM");
//        LocalDate befOccurrenceStartTime = DateUtil.parseLocalDateTime(copBef).with(TemporalAdjusters.firstDayOfMonth()).toLocalDate();
//        LocalDate vefOccurrenceEndTime =  DateUtil.parseLocalDateTime(copBef).with(TemporalAdjusters.lastDayOfMonth()).toLocalDate();
//        param.put("occurrenceStartTime",befOccurrenceStartTime);
//        param.put("occurrenceEndTime",vefOccurrenceEndTime);
//        param.put("eventCategoryId",map.get("eventCategoryId"));
//        Integer copBefCount = commonService.getObject(eventNameSpace + ".getEventCountAll", param);
//        BigDecimal calculate = calculateMoMGrowth(copCount, copBefCount);
//        if (copCount>threshold) {
//            Integer alarmLevel = 0;
//            if (calculate.compareTo(BigDecimal.valueOf(30))>=0&&calculate.compareTo(BigDecimal.valueOf(50))<=0){
//                alarmLevel= 2;
//            }else if(calculate.compareTo(BigDecimal.valueOf(50))>0){
//                alarmLevel= 1;
//            }else {
//                return;
//            }
//            HashMap<String, Object> pamap = new HashMap<>();
//            pamap.put("count",copCount);
//            pamap.put("percentage",calculate);
//            pamap.put("areaLevel",1);
//            pamap.put("regionCode","220000000000");
//            pamap.put("statisticalTime",String.valueOf(map.get("occurrenceTime")));
//            pamap.put("eventCategoryId",String.valueOf(map.get("eventCategoryId")));
//            pamap.put("alarmLevel",alarmLevel);
//            int update = commonService.update(areasNameSpace + ".updateinfo", pamap);
//            if (update == 0) {
//                FocusAreas focusAreas = new FocusAreas();
//                focusAreas.setCount(copCount);
//                focusAreas.setPercentage(calculate);
//                focusAreas.setStatisticalTime(String.valueOf(map.get("occurrenceTime")));
//                focusAreas.setEventCategoryId(String.valueOf(map.get("eventCategoryId")));
//                focusAreas.setAreaLevel(1);
//                focusAreas.setRegionCode("220000000000");
//                focusAreas.setAlarmLevel(alarmLevel);
//                commonService.insert(areasNameSpace, focusAreas);
//            }
//        }
//    }

    public BigDecimal calculateMoMGrowth(int currentMonthCount, int lastMonthCount) {

        if (lastMonthCount == 0) {
            return BigDecimal.valueOf(100);
        }
        return BigDecimal.valueOf(((double) (currentMonthCount - lastMonthCount) / lastMonthCount) * 100);


    }


    /**
     * 获取两个Date之间的所有月份（包含起止月份）
     * @param startDate 起始日期
     * @param endDate 结束日期
     * @return 格式化的月份列表
     */
    public  List<LocalDateTime> getMonthFirstDayEnds(Date startDate, Date endDate) {
        List<LocalDateTime> result = new ArrayList<>();

        // 将Date转换为YearMonth
        YearMonth startMonth = convertToYearMonth(startDate);
        YearMonth endMonth = convertToYearMonth(endDate);

        // 循环处理每个月份
        YearMonth currentMonth = startMonth;
        while (!currentMonth.isAfter(endMonth)) {
            // 每个月的第一天的23:59:59
            LocalDateTime firstDayEnd = currentMonth.atDay(1)
                    .atTime(23, 59, 59);

            result.add(firstDayEnd);
            currentMonth = currentMonth.plusMonths(1);
        }

        return result;
    }


    /**
     * 将Date转换为YearMonth
     * @param date 要转换的日期
     * @return 对应的YearMonth对象
     */
    private  YearMonth convertToYearMonth(Date date) {
        // 将Date转换为Instant，再转换为LocalDate，最后获取YearMonth
        // Java 8兼容方式：通过ZonedDateTime中转
        Instant instant = date.toInstant();
        ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
        LocalDate localDate = zonedDateTime.toLocalDate();
        return YearMonth.from(localDate);
    }

    public static void main(String[] args) {
        String dateStr = "2024-05";
        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .appendPattern("yyyy-MM")
                .parseDefaulting(ChronoField.DAY_OF_MONTH, 1) // 设置默认日为1
                .toFormatter();

        // 先解析为LocalDate，再转为LocalDateTime
        LocalDate localDate = LocalDate.parse(dateStr, formatter);
        localDate.atStartOfDay();
    }

}
