package cn.cecep.talroad.data.analyse.task.limestone;

import cn.cecep.talroad.domain.*;
import cn.cecep.talroad.enums.DeviceStatusEnum;
import cn.cecep.talroad.enums.EnIndustry;
import cn.cecep.talroad.mapper.*;
import cn.cecep.talroad.vo.analysis.AvgValueVo;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author：haoyan
 * @date：2023/6/12 13:46
 */
@Service
public class DesulphurizerAnomalyService{

    @Autowired
    private BasDeviceMapper basDeviceMapper;

    @Autowired
    private BasDeviceSalAnalysisMapper basDeviceSalAnalysisMapper;

    @Autowired
    private BasThresholdConfigMapper configMapper;

    @Autowired
    private MonDevRealMapper monDevRealMapper;

    @Autowired
    private SEnvGasMonRealMapper sEnvGasMonRealMapper;

    @Autowired
    private AmProblemFiMapper amProblemFiMapper;

    private static final int PAGE_SIZE = 10;

    public void demo(EnIndustry enIndustry) {
        //获取设备
        List<BasDevice> basDevList = queryUsableDeviceIds(enIndustry);

        //获取石灰石纯度配置
        BasThresholdConfig config = configMapper.selectByParamCode("T01");
        //将取出的配置值进行转换85%-》0.85
        BigDecimal purityValue = config.getThresholdValue().divide(new BigDecimal(100),2, RoundingMode.HALF_UP);
        //获取日实际消耗量小于石灰石消耗量
        config = configMapper.selectByParamCode("T02");
        //将取出的配置值进行转换50%-》0.5
        BigDecimal judgeValue = config.getThresholdValue().divide(new BigDecimal(100),2, RoundingMode.HALF_UP);

        if (!CollectionUtil.isEmpty(basDevList)) {
            //获取当前天的前一天开始时间
            Date startTime = getBeforeDayStart();
            //获取当前天的前一天结束时间
            Date endTime = getBeforeDayEnd();
            //获取日均排放量
            List<AvgValueVo> avg = sEnvGasMonRealMapper.getEmissionDayAvg(startTime.toString(), endTime.toString());
            Map<String, AvgValueVo> emissionAvgMap = avg.stream().collect(Collectors.toMap(AvgValueVo::getDeviceId, o -> o));

            List<List<BasDevice>> baseDevicePage = Lists.partition(basDevList, PAGE_SIZE);
            for (List<BasDevice> deviceList : baseDevicePage) {
                //根据设备id分组
                List<String> deviceIds = deviceList.stream().map(BasDevice::getDeviceId).collect(Collectors.toList());
                //获取每个设备的出入口SO2
                List<MonDevReal> realList = queryMonDevReal(deviceIds, startTime, endTime);
                //根据设备分组出入口SO2
                Map<String, List<MonDevReal>> devRealMap = realList.stream().collect(Collectors.groupingBy(MonDevReal::getDeviceId));
                //计算每个设备的出入口SO2
                Map<String, AvgValueVo> so2AvgValue = getSO2AvgValue(deviceIds, devRealMap);
                Map<String, AvgValueVo> desulfurizerAvgValue = getDesulfurizerAvgValue(deviceIds, devRealMap);

                judge(so2AvgValue,desulfurizerAvgValue,emissionAvgMap,purityValue,judgeValue,deviceList);
            }
        }
    }

    private Map<String, AvgValueVo> getDesulfurizerAvgValue(List<String> deviceIds, Map<String, List<MonDevReal>> devRealMap) {
        Map<String, AvgValueVo> map = new HashMap<>();
        for (String deviceId : deviceIds) {
            List<MonDevReal> realList = devRealMap.get(deviceId);
            BigDecimal g08 = new BigDecimal(0);
            BigDecimal g09 = new BigDecimal(0);
            for (MonDevReal real : realList) {
                g08 = g08.add(new BigDecimal(real.getGb08()));
                g09 = g09.add(new BigDecimal(real.getGb09()));
            }
            g08 = g08.divide(new BigDecimal(realList.size()),6, RoundingMode.HALF_UP);
            g09 = g09.divide(new BigDecimal(realList.size()),6, RoundingMode.HALF_UP);
            AvgValueVo vo = new AvgValueVo();
            vo.setDeviceId(deviceId);
            vo.setAvgValue(g08);
            vo.setAvgValue2(g09);
            map.put(deviceId,vo);
        }
        return map;
    }

    private void judge(Map<String, AvgValueVo> so2AvgValue, Map<String, AvgValueVo> jhMap, Map<String, AvgValueVo> emissionAvgMap, BigDecimal purityValue, BigDecimal judgeValue,List<BasDevice> deviceIds) {
        for (BasDevice device : deviceIds) {
            String deviceId = device.getDeviceId();
            AvgValueVo so2Value = so2AvgValue.get(deviceId);
            AvgValueVo jhValue = jhMap.get(deviceId);
            AvgValueVo emiValue = emissionAvgMap.get(deviceId);
            //（入口SO2日均浓度-出口SO2日均浓度）/入口SO2日均浓度
            BigDecimal div = so2Value.getAvgValue().subtract(so2Value.getAvgValue2()).divide(so2Value.getAvgValue(), 6, RoundingMode.HALF_UP);
            //日废气排放量*入口SO2日均浓度/1000000*（（入口SO2日均浓度-出口SO2日均浓度）/入口SO2日均浓度）*100/64/石灰石纯度（一般为85%-90%）*1.03
            BigDecimal limestone = emiValue.getAvgValue()
                    .multiply(so2Value.getAvgValue())
                    .divide(new BigDecimal("1000000"), 6, RoundingMode.HALF_UP)
                    .multiply(div)
                    .multiply(new BigDecimal(100))
                    .divide(new BigDecimal(64), 6, RoundingMode.HALF_UP)
                    .divide(purityValue, 6, RoundingMode.HALF_UP)
                    .multiply(new BigDecimal("1.03"));


            int jhValue1 = jhValue.getAvgValue().compareTo(limestone.multiply(judgeValue));
            int jhValue2 = jhValue.getAvgValue2().compareTo(limestone.multiply(judgeValue));
            if (jhValue1 < 0) {
                addProblem(device.getName(),jhValue.getAvgValue(),limestone.multiply(judgeValue),limestone,device.getFactoryId());
            }
            if ( jhValue2  < 0) {
                addProblem(device.getName(),jhValue.getAvgValue2(),limestone.multiply(judgeValue),limestone,device.getFactoryId());
            }
        }
    }

    private void addProblem(String name,BigDecimal value,BigDecimal minValue,BigDecimal maxValue,String factoryId) {
        //出现报警
        AmProblemFi amProblemFi = new AmProblemFi();
        amProblemFi.setFactoryId(factoryId);
        String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
        amProblemFi.setId(uuid);
        // 问题来源 1:关联分析系统, 2:分表计电系统, 3:动态管控系统
        amProblemFi.setProblemSources("1");
        // 新增一条，代表企业生产设施运行分析
        amProblemFi.setProblemType("004");
        String date = new SimpleDateFormat("yyyy年MM月dd日").format(getBeforeDayStart());
        String message  = String.format("%s,%s实际使用脱硫剂%skg，理论药剂投加量应为%s-%skg，实际药剂使用量过低，请注意排查。",name,date,value,minValue,maxValue);
        amProblemFi.setProblemDetails(message);
        amProblemFi.setType(1);
        amProblemFiMapper.insert(amProblemFi);
    }

    private Map<String, AvgValueVo> getSO2AvgValue(List<String> deviceIds, Map<String, List<MonDevReal>> devRealMap) {
        Map<String, AvgValueVo> map = new HashMap<>();
        for (String deviceId : deviceIds) {
            List<MonDevReal> realList = devRealMap.get(deviceId);
            BigDecimal so2In = new BigDecimal(0);
            BigDecimal so2Out = new BigDecimal(0);
            for (MonDevReal real : realList) {
                so2In = so2In.add(new BigDecimal(real.getSo2In()));
                so2Out = so2Out.add(new BigDecimal(real.getSo2Out()));
            }
            so2In = so2In.divide(new BigDecimal(realList.size()),6, RoundingMode.HALF_UP);
            so2Out = so2Out.divide(new BigDecimal(realList.size()),6, RoundingMode.HALF_UP);
            AvgValueVo vo = new AvgValueVo();
            vo.setDeviceId(deviceId);
            vo.setAvgValue(so2In);
            vo.setAvgValue2(so2Out);
            map.put(deviceId,vo);
        }
        return map;
    }

    protected List<MonDevReal> queryMonDevReal(List<String> deviceIds, Date startTime , Date endTime){

        LambdaQueryWrapper<MonDevReal> monDevRealLambdaQueryWrapper = new QueryWrapper<MonDevReal>().lambda()
                .in(MonDevReal::getDeviceId,deviceIds)
                .ge(MonDevReal::getDataTime,startTime)
                .le(MonDevReal::getDataTime,endTime)
                .isNotNull(MonDevReal::getSo2In)
                .isNotNull(MonDevReal::getSo2Out);

        List<MonDevReal> monDevReals = monDevRealMapper.selectList(monDevRealLambdaQueryWrapper);

        return monDevReals;
    }

    /**
     * @Description 获取当前时期前 i 天 日期的零点 当前日期 2019-7-8 13:13:13 --> 获取日期 2019-07-07
     * @Author: szj
     * @param:  [i]  输入int值 代表天数 00:00:00  UNIX 时间
     * @Return: int
     */
    public Date getBeforeDayStart() {
        Calendar zero = Calendar.getInstance();
        zero.add(Calendar.DATE, -1);
        zero.set(zero.get(Calendar.YEAR), zero.get(Calendar.MONTH), zero.get(Calendar.DATE), 0, 0, 0);
        return zero.getTime();
    }
    /**
     * @Description 获取当前时期前 i 天 日期的23:59:59 当前日期 2019-7-8 13:13:13 --> 获取日期 2019-7-7 23:59:59 UNIX 时间
     * @Author: szj
     * @param:  [i]  输入int值 代表天数
     * @Return: int
     */
    public Date getBeforeDayEnd() {
        Calendar zero = Calendar.getInstance();
        zero.add(Calendar.DATE, -1);
        zero.set(zero.get(Calendar.YEAR), zero.get(Calendar.MONTH), zero.get(Calendar.DATE), 23, 59, 59);
        return zero.getTime();
    }

    protected List<BasDevice> queryUsableDeviceIds(EnIndustry enIndustry) {
        List<BasDevice> basDevices = queryDevice(enIndustry);
        if (CollectionUtil.isEmpty(basDevices)){
            return new ArrayList<>();
        }
        return filterOpenDeviceIds(basDevices);
    }

    protected List<BasDevice> queryDevice(EnIndustry enIndustry){
        if (enIndustry == null){
            throw new RuntimeException("queryDeviceIds is null!");
        }
        LambdaQueryWrapper<BasDevice> wrapper = Wrappers.<BasDevice>lambdaQuery()
                .select(BasDevice::getDeviceId)
                .eq(BasDevice::getIndustry, enIndustry.id());
        return basDeviceMapper.selectList(wrapper);
    }

    protected List<BasDevice> filterOpenDeviceIds(List<BasDevice> devices) {
        if (CollectionUtil.isEmpty(devices)) {
            return new ArrayList<>();
        }
        List<String> deviceIds = devices.stream().map(BasDevice::getDeviceId).collect(Collectors.toList());
        List<BasDeviceSalAnalysis> basDeviceSalAnalyses = basDeviceSalAnalysisMapper.selectList(Wrappers.<BasDeviceSalAnalysis>lambdaQuery().in(BasDeviceSalAnalysis::getDeviceId, deviceIds));
        if (CollectionUtil.isEmpty(basDeviceSalAnalyses)){
            return new ArrayList<>();
        }
        //过滤出所有 ！= 停产的 设备
        List<String> openDeviceIds = getOpenDeviceIds(deviceIds, basDeviceSalAnalyses);

        List<BasDevice> basDevices = devices.stream().filter((device) -> {
            for (String openDeviceId : openDeviceIds) {
                if (openDeviceId.equals(device.getDeviceId())) {
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toList());

        return basDevices;
    }
    protected List<String> getOpenDeviceIds(List<String> deviceIds,List<BasDeviceSalAnalysis> basDeviceSalAnalyses){
        return basDeviceSalAnalyses
                .stream()
                .filter(deviceSalAnalysis -> !DeviceStatusEnum.STOP.getValue().equals(deviceSalAnalysis.getMonStatus()))
                .map(BasDeviceSalAnalysis::getDeviceId)
                .collect(Collectors.toList());
    }
}
