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

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
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 areasNameSpaceEventNow = "com.scpyun.platform.standard.jilinsscgsdp.focusareasNowEvent";

    private final String areasNameSpaceEventHistory = "com.scpyun.platform.standard.jilinsscgsdp.focusareasHisToryEvent";

    private final String areasNameSpaceHistory = "com.scpyun.platform.standard.jilinsscgsdp.focusareasHisTory";

    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);
        });
        List<Map<String, Object>> fids = commonService.findList(areasNameSpace + ".findAllFids", null);
        if (fids!=null&&fids.size()>0) {
            fids.forEach(v -> {
                commonService.delete(areasNameSpaceEventNow + ".deleteEventId", v.get("fid"));
            });
        }
        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 -> {
                    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 -> {
                        HashMap<String, Object> map = new HashMap<>();
                        map.put("occurrenceTime", DateUtil.format(yesterdayEnd, "yyyy-MM"));
                        map.put("eventCategoryId", eventCategoryId);
                        chain(map, v, "2");
                    });
                });
                 log.info("开始进行当市级环比计算");
                break;
            case 3:
                 log.info("开始进行当区级环比计算");
                List<String> areaEventCategoryIds = commonService.findList(areasNameSpace + ".geteventCategoryId", null);
                list.forEach(v -> {
                    areaEventCategoryIds.forEach(eventCategoryId -> {
                        HashMap<String, Object> map = new HashMap<>();
                        map.put("occurrenceTime", DateUtil.format(yesterdayEnd, "yyyy-MM"));
                        map.put("eventCategoryId", eventCategoryId);
                        chain(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);
        chainMap.put("statisticalTime",occurrenceTime);
        LocalDate occurrenceStartTime = localDate.with(TemporalAdjusters.firstDayOfMonth());
        LocalDate occurrenceEndTime = localDate.with(TemporalAdjusters.lastDayOfMonth());
        chainMap.put("occurrenceStartTime", occurrenceStartTime);
        chainMap.put("occurrenceEndTime", occurrenceEndTime);
        HashMap<String, Object> chainMapNodes = new HashMap<>();
        chainMapNodes.putAll(chainMap);
        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();
        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 {
                alarmLevel = 0;
            }
            Integer hisLevel = commonService.getObject(areasNameSpace + ".getlevel", chainMap);
            if (!alarmLevel.equals(hisLevel)) {
                FocusAreas focusAreas = commonService.getObject(areasNameSpace + ".findAllOne", chainMap);
                if (focusAreas != null) {
                    commonService.insert(areasNameSpaceHistory + ".insertFocusArea", focusAreas);
                    List<HashMap<String, Object>> eventids = commonService.findList(areasNameSpaceEventNow + ".findListForFocus", focusAreas.getFid());
                    if (eventids!=null&&eventids.size()>0) {
                        commonService.insertBatch(areasNameSpaceEventHistory + ".insertAll", eventids);
                    }
                }

            }
            if (!alarmLevel.equals(0)) {
                String fid = UUID.randomUUID().toString();
                FocusAreas focusAreas = new FocusAreas();
                focusAreas.setCount(eventCopCount);
                focusAreas.setFid(fid);
                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);
                log.error("空指针入参=============================》{}", JSONUtil.toJsonStr(chainMapNodes));
                List<Map<String,Object>> ids = commonService.findList(eventNameSpace + ".getEventIdAllByCode", chainMapNodes);
                ids.forEach(v->{
                    v.put("fid",fid);
                });
                commonService.insertBatch(areasNameSpaceEventNow+".insertAll",ids);

            }
        }else{
            Integer hisLevel = commonService.getObject(areasNameSpace + ".getlevel", chainMap);
            log.info("历史的等级是{}》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》",hisLevel);
            if (hisLevel!=null&&!hisLevel.equals(0)) {
                log.info("历史的参数是{}》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》",JSONUtil.toJsonStr(chainMap));
                FocusAreas focusAreas = commonService.getObject(areasNameSpace + ".findAllOne", chainMap);
                log.info("历史的数据是{}》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》",JSONUtil.toJsonStr(focusAreas));
                if (focusAreas != null) {
                    commonService.insert(areasNameSpaceHistory + ".insertFocusArea", focusAreas);
                    List<HashMap<String, Object>> eventids = commonService.findList(areasNameSpaceEventNow + ".findListForFocus", focusAreas.getFid());
                    log.info("历史的时间id是{}》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》",JSONUtil.toJsonStr(eventids));
                    if (eventids!=null&&eventids.size()>0) {
                        commonService.insertBatch(areasNameSpaceEventHistory + ".insertAll", eventids);
                    }
                }

            }
        }
//        }
    }

    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();
    }

}
