/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package com.unis.dev.modular.job.task;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.unis.basic.info.modular.grainPriceCollect.entity.GrainPriceCollect;
import com.unis.basic.info.modular.grainPriceCollect.mapper.GrainPriceCollectMapper;
import com.unis.basic.info.modular.grainPriceCollectCitySum.entity.GrainPriceCollectCitySum;
import com.unis.basic.info.modular.grainPriceCollectCitySum.mapper.GrainPriceCollectCitySumMapper;
import com.unis.basic.info.modular.pricemonitor.entity.PriceMonitor;
import com.unis.basic.info.modular.pricemonitor.mapper.PriceMonitorMapper;
import com.unis.basic.info.modular.remindcycle.entity.RemindCycle;
import com.unis.basic.info.modular.remindcycle.mapper.RemindCycleMapper;
import com.unis.basic.info.modular.reportpricemonitor.entity.ReportPriceMonitor;
import com.unis.basic.info.modular.reportpricemonitor.mapper.ReportPriceMonitorMapper;
import com.unis.basic.info.modular.unReporCity.entity.UnReporCity;
import com.unis.basic.info.modular.unReporCity.mapper.UnReporCityMapper;
import com.unis.common.timer.CommonTimerTaskRunner;
import com.unis.sys.modular.org.entity.SysOrg;
import com.unis.sys.modular.org.mapper.SysOrgMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 市州，站点漏报---定时任务
 *
 * @author xuyuxiang
 * @date 2022/8/5 15:52
 **/
@Slf4j
@Component
public class UnReportCityTaskRunner implements CommonTimerTaskRunner {

    @Autowired
    private RemindCycleMapper remindCycleMapper;  //价格上报周期

    @Autowired
    private GrainPriceCollectCitySumMapper grainPriceCollectCitySumMapper;  //市级粮食汇总

    @Autowired
    private GrainPriceCollectMapper grainPriceCollectMapper; //站点汇总

    @Autowired
    private ReportPriceMonitorMapper unreportPriceMonitorMapper; //站点漏报

    @Autowired
    private UnReporCityMapper unReporCityMapper;  //市州漏报

    @Autowired
    private PriceMonitorMapper priceMonitorMapper; //价格监测点

    @Autowired
    private SysOrgMapper sysOrgMapper; //市州实体


    //漏报：上报开始之前的信息和结束之后的信息，都属于漏报
    //错报：移动端采集人员进行登录采集的时候，若果上传超过两次就记为错报
    @Override
    public void action() {

        log.info("------------各市州站点漏报的定时任务开始执行------------");

        //获取签约的站点记录
        List<PriceMonitor> priceMonitors = priceMonitorMapper.selectList(null);

        if (CollectionUtil.isEmpty(priceMonitors)) {
            log.error("未获取到系统中对应站点信息,流程终止");
            return;
        }

        List<SysOrg> sysOrgs = sysOrgMapper.selectList(null);
        if (CollectionUtil.isEmpty(sysOrgs)) {
            log.error("未获取到系统中对应州市信息,流程终止");
            return;
        }


        //获取上报时间周期
        List<RemindCycle> remindCycles = remindCycleMapper.selectList(null);

        if (CollectionUtil.isEmpty(remindCycles)) {
            log.error("未配置时间周期,流程结束");
            return;
        }


        RemindCycle remindCycle = remindCycles.get(0);

        // 获取当前日期
        LocalDate today = LocalDate.now(ZoneId.systemDefault());

        // 获取当前日期是周几
        DayOfWeek dayOfWeek = today.getDayOfWeek();


        //判断是否大于或等于最小上报周期
        if (dayOfWeek.getValue() < remindCycle.getDayOfWeek()) {
            log.info("当前时间未到上报周期时间");
            return;
        }
        //获取最小上报时间结束时间点
        Date remindCycleEndTime = remindCycle.getEndTime();

        //获取当前时间点
        LocalTime time = LocalTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
        String format = time.format(formatter);
        int i = 1;
        try {
            //比较结束时间点
            i = remindCycleEndTime.compareTo(new SimpleDateFormat("HH:mm:ss").parse(format));
        } catch (ParseException e) {
            log.error("当前时间转换异常，流程终止");
            return;
        }

        if (i == 1) {
            log.info("未到当前报送周期截止时间,本日汇总终止");
            return;
        }


        //获取本周设置的具体时间
        Integer remindCycleDayOfWeek = remindCycle.getDayOfWeek();

        // 获取本周的目标日期
        LocalDate targetDate = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.of(remindCycleDayOfWeek)));

        //转换开始时间
        String startTime = targetDate + " " + remindCycle.getStartTime();
        String endTime = targetDate + " " + remindCycle.getEndTime();

        //新增map集合记录错报中未在实地采集的次数
        HashMap<String, Integer> noGatheMap = new HashMap<>();

        //过滤出漏报站点信息
        List<PriceMonitor> missList = priceMonitors.stream().filter(o -> {
            List<GrainPriceCollect> grainPriceCollects = grainPriceCollectMapper.selectList(new LambdaQueryWrapper<GrainPriceCollect>()
                    .eq(GrainPriceCollect::getPriceMonitorId, o.getId())
                    .ge(GrainPriceCollect::getCreateTime, startTime)
                    .lt(GrainPriceCollect::getCreateTime, endTime));
            return CollectionUtil.isEmpty(grainPriceCollects);
        }).collect(Collectors.toList());

        //统计错报站点信息
        List<PriceMonitor> errList = priceMonitors.stream().filter(o -> {
            List<GrainPriceCollect> grainPriceCollects = grainPriceCollectMapper.selectList(new LambdaQueryWrapper<GrainPriceCollect>()
                    .eq(GrainPriceCollect::getPriceMonitorId, o.getId())
                    .ge(GrainPriceCollect::getCreateTime, startTime)
                    .lt(GrainPriceCollect::getCreateTime, endTime)
                    .ge(GrainPriceCollect::getUserCollectDateCount, 2));
            GrainPriceCollect grainPriceCollect = grainPriceCollects.get(0);
            if (CollectionUtil.isNotEmpty(grainPriceCollects)
                    && (grainPriceCollect.getType().equals(0)
                    && grainPriceCollect.getIsSelfPriceMonitor().equals(0))) {
                noGatheMap.put(grainPriceCollect.getPriceMonitorId(), grainPriceCollect.getUserCollectDateCount());
                return true;
            }
            return false;
        }).collect(Collectors.toList());


        //对所在州市去重处理
        HashMap<String, Integer> missMap = new HashMap<>();
        HashMap<String, Integer> errMap = new HashMap<>();

        for (PriceMonitor priceMonitor : missList) {
            if (ObjectUtil.isEmpty(missMap.get(priceMonitor.getSysOrgId()))) {
                missMap.put(priceMonitor.getSysOrgId(), 1);
                continue;
            }
            missMap.put(priceMonitor.getSysOrgId(), missMap.get(priceMonitor.getSysOrgId()) + 1);
        }

        for (PriceMonitor priceMonitor : errList) {
            if (ObjectUtil.isEmpty(errMap.get(priceMonitor.getSysOrgId()))) {
                errMap.put(priceMonitor.getSysOrgId(), 1);
                continue;
            }
            errMap.put(priceMonitor.getSysOrgId(), errMap.get(priceMonitor.getSysOrgId()) + 1);
        }

        //对市州错报漏报信息进行入库处理
        Set<Map.Entry<String, Integer>> missEntry = missMap.entrySet();
        for (Map.Entry<String, Integer> entry : missEntry) {
            UnReporCity unReporCity = new UnReporCity();
            unReporCity.setUnReportCount(entry.getValue());
            unReporCity.setCreateTime(new Date());
            unReporCity.setUpdateTime(new Date());
            unReporCity.setSysOrgId(entry.getKey());
            unReporCity.setReportDate(new Date());
            try {
                unReporCityMapper.insert(unReporCity);
            } catch (Exception e) {
                log.error("插入对应市州漏报信息出错,对应市州id[{}]", entry.getKey());
            }
        }

        Set<Map.Entry<String, Integer>> errEntrySet = errMap.entrySet();
        for (Map.Entry<String, Integer> entry : errEntrySet) {
            UnReporCity unReporCity = new UnReporCity();
            unReporCity.setFalseReportCount(entry.getValue());
            unReporCity.setCreateTime(new Date());
            unReporCity.setUpdateTime(new Date());
            unReporCity.setSysOrgId(entry.getKey());
            unReporCity.setReportDate(new Date());
            try {
                unReporCityMapper.insert(unReporCity);
            } catch (Exception e) {
                log.error("插入对应市州错报信息出错,对应市州id[{}]", entry.getKey());
            }
        }

        //对站点错漏报信息进行入库处理
        for (PriceMonitor priceMonitor : missList) {
            ReportPriceMonitor reportPriceMonitor = new ReportPriceMonitor();
            reportPriceMonitor.setCreateTime(new Date());
            reportPriceMonitor.setUpdateTime(new Date());
            reportPriceMonitor.setUnReportCount(1);
            reportPriceMonitor.setReportDate(new Date());
            reportPriceMonitor.setPriceMonitorId(priceMonitor.getId());
            reportPriceMonitor.setUnReportCityId(priceMonitor.getSysOrgId());
            try {
                unreportPriceMonitorMapper.insert(reportPriceMonitor);
            } catch (Exception e) {
                log.error("插入对应站点漏报信息出错,对应站点id[{}]", priceMonitor.getId());
            }

        }


        for (PriceMonitor priceMonitor : errList) {
            ReportPriceMonitor reportPriceMonitor = new ReportPriceMonitor();
            reportPriceMonitor.setCreateTime(new Date());
            reportPriceMonitor.setUpdateTime(new Date());
            reportPriceMonitor.setFalseReportCount(1);
            reportPriceMonitor.setReportDate(new Date());
            reportPriceMonitor.setPriceMonitorId(priceMonitor.getId());
            reportPriceMonitor.setUnReportCityId(priceMonitor.getSysOrgId());
            reportPriceMonitor.setUnSelfPriceMonitorCount(noGatheMap.get(priceMonitor.getId()));
            try {
                unreportPriceMonitorMapper.insert(reportPriceMonitor);
            } catch (Exception e) {
                log.error("插入对应站点错报信息出错,对应站点id[{}]", priceMonitor.getId());
            }

        }


    }

    public static void main(String[] args) throws ParseException {
        // 获取当前日期
        LocalDate today = LocalDate.now(ZoneId.systemDefault());
        LocalDate targetDate = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.of(1)));

        System.out.println(targetDate);
    }


}



