package cn.cecep.talroad.data.analyse.task.factory.label.change;

import cn.cecep.talroad.data.analyse.task.entity.PollutantChangeVO;
import cn.cecep.talroad.domain.PcFactory;
import cn.cecep.talroad.domain.analysis.SRaActionReportsActualEmissions;
import cn.cecep.talroad.domain.dto.FactoryLabelChangeDTO;
import cn.cecep.talroad.enums.LabelFactoryEnum;
import cn.cecep.talroad.mapper.PcFactoryMapper;
import cn.cecep.talroad.mapper.analysis.SRaActionReportsActualEmissionsMapper;
import cn.cecep.talroad.util.DateUtil;
import cn.cecep.talroad.vo.ChartVo;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author: Frank
 * @createTime: 2023年07月18日 21:59:25
 * @version:
 * @Description:
 */
@Service
@AllArgsConstructor
public class PollutantChangeService extends AbstractFactoryLabelChangeService {

    private static final Logger logger = LoggerFactory.getLogger(PollutantChangeService.class);

    private final SRaActionReportsActualEmissionsMapper sRaActionReportsActualEmissionsMapper;

    private final PcFactoryMapper pcFactoryMapper;

    private List<String> allEnumIds;

    private Map<String, BigDecimal> allConfig;

    private Map<String, String> labelPollutantMapping;


    @Override
    public boolean support(String enumId) {
        init();
        return allEnumIds.contains(enumId);
    }

    private void init() {
        initEnumIds();
        initConfig();
        initLabelMapping();
    }

    private void initLabelMapping() {
        if (CollUtil.isEmpty(labelPollutantMapping)) {
            labelPollutantMapping.put(LabelFactoryEnum.PF008.getEnumId(), ChartVo.AirPollutant.P_1.getCode());
            labelPollutantMapping.put(LabelFactoryEnum.PF009.getEnumId(), ChartVo.AirPollutant.P_2.getCode());
            labelPollutantMapping.put(LabelFactoryEnum.PF010.getEnumId(), ChartVo.AirPollutant.P_3.getCode());
            labelPollutantMapping.put(LabelFactoryEnum.PF011.getEnumId(), ChartVo.AirPollutant.P_4.getCode());
            labelPollutantMapping.put(LabelFactoryEnum.PF012.getEnumId(), ChartVo.WaterPollutant.P_1.getCode());
            labelPollutantMapping.put(LabelFactoryEnum.PF013.getEnumId(), ChartVo.WaterPollutant.P_2.getCode());
            labelPollutantMapping.put(LabelFactoryEnum.PF014.getEnumId(), ChartVo.WaterPollutant.P_3.getCode());
            labelPollutantMapping.put(LabelFactoryEnum.PF015.getEnumId(), ChartVo.WaterPollutant.P_4.getCode());
        }
    }

    private void initConfig() {
        if (CollUtil.isEmpty(allConfig)) {
            allConfig.put(ChartVo.AirPollutant.P_1.getCode(), new BigDecimal("250"));
            allConfig.put(ChartVo.AirPollutant.P_2.getCode(), new BigDecimal("250"));
            allConfig.put(ChartVo.AirPollutant.P_3.getCode(), new BigDecimal("500"));
            allConfig.put(ChartVo.AirPollutant.P_4.getCode(), new BigDecimal("0"));
            allConfig.put(ChartVo.WaterPollutant.P_1.getCode(), new BigDecimal("30"));
            allConfig.put(ChartVo.WaterPollutant.P_2.getCode(), new BigDecimal("30"));
            allConfig.put(ChartVo.WaterPollutant.P_3.getCode(), new BigDecimal("10"));
            allConfig.put(ChartVo.WaterPollutant.P_4.getCode(), new BigDecimal("0.5"));
        }
    }

    private void initEnumIds() {
        if (CollUtil.isEmpty(allEnumIds)) {
            allEnumIds = LabelFactoryEnum.getPollutantEnumIds();
        }
    }

    @Override
    public void execute(FactoryLabelChangeDTO factoryLabelChangeDTO) {
        logger.info("所有配置:{}",allConfig);
        logger.info("所有标签:{}",allEnumIds);
        logger.info("标签和污染物映射关系:{}",labelPollutantMapping);

        //大户为1039 一般为1040
        final String highLevel = "1039", generalLevel = "1040";
        //根据当前污染物CODE查询实际排放量
        List<SRaActionReportsActualEmissions> sRaActionReportsActualEmissions = queryByCurrentPollutantCode(labelPollutantMapping.get(factoryLabelChangeDTO.getEnumId()));
        if (CollUtil.isEmpty(sRaActionReportsActualEmissions)) return;
        logger.info("根据当前污染物CODE查询实际排放量:{}", JSON.toJSONString(sRaActionReportsActualEmissions));
        Set<String> factoryIds = sRaActionReportsActualEmissions.stream().map(SRaActionReportsActualEmissions::getFactoryId).collect(Collectors.toSet());
        //根据factoryIds查询企业信息
        Map<String, PcFactory> factoryDataMap = queryByFactoryIds(factoryIds);
        if (CollUtil.isEmpty(sRaActionReportsActualEmissions)) return;
        logger.info("根据factoryIds查询企业信息:{}", JSON.toJSONString(factoryDataMap));

        List<String> highLevelFactoryIds = Lists.newArrayList();
        List<PollutantChangeVO> pollutantChangeVOList = Lists.newArrayList();
        //从配置中获取当前污染物code对应的实际用量阈值
        BigDecimal bigDecimal = allConfig.get(labelPollutantMapping.get(factoryLabelChangeDTO.getEnumId()));
        logger.info("当前污染物code对应的实际用量阈值:{}", bigDecimal);
        for (SRaActionReportsActualEmissions sRaActionReportsActualEmission : sRaActionReportsActualEmissions) {
            //计算用电量是否大于阈值，如果大于阈值则归类为大户
            if (bigDecimal.compareTo(BigDecimal.ZERO) > 0 && sRaActionReportsActualEmission.getActualEmissions().compareTo(bigDecimal) > 0) {
                highLevelFactoryIds.add(sRaActionReportsActualEmission.getFactoryId());
            }
            PcFactory pcFactory = factoryDataMap.get(sRaActionReportsActualEmission.getFactoryId());
            if (Objects.nonNull(pcFactory)) {
                pollutantChangeVOList.add(new PollutantChangeVO(pcFactory.getId(), sRaActionReportsActualEmission.getActualEmissions()
                        , pcFactory.getCityCode(), pcFactory.getCityName()));
            }
        }
        logger.info("实际用量大户:{}", JSON.toJSONString(highLevelFactoryIds));
        logger.info("pollutantChangeVOList:{}", JSON.toJSONString(pollutantChangeVOList));

        if (CollUtil.isNotEmpty(pollutantChangeVOList)) {
            //计算用电量是否在全市前5%，如果在全市前5%则归类为大户
            Map<String, List<PollutantChangeVO>> mapData = pollutantChangeVOList.stream().collect(Collectors.groupingBy(PollutantChangeVO::getCityCode));
            for (Map.Entry<String, List<PollutantChangeVO>> entry : mapData.entrySet()) {
                List<PollutantChangeVO> result = entry.getValue();
                int n = result.size();
                int k = 5; // k = 5%
                int m = (int) Math.ceil(k * n / 100.0);
                result.sort(Comparator.comparing(PollutantChangeVO::getActualEmissions).reversed());
                List<PollutantChangeVO> pollutantChangeVOS = result.subList(0, m);
                if (CollUtil.isNotEmpty(pollutantChangeVOS)) {
                    highLevelFactoryIds.addAll(pollutantChangeVOS.stream().map(PollutantChangeVO::getFactoryId).collect(Collectors.toSet()));
                }
            }
        }
        logger.info("实际用量大户:{}", JSON.toJSONString(highLevelFactoryIds));

        if (CollUtil.isNotEmpty(highLevelFactoryIds)) {
            insertOrUpdateFactoryLabel(new HashSet<>(highLevelFactoryIds), highLevel, factoryLabelChangeDTO.getEnumId());
        }
        //如果不是大户，则归类为一般
        Set<String> generalLevelFactoryIds = factoryIds.stream().filter(f -> !highLevelFactoryIds.contains(f)).collect(Collectors.toSet());
        if (CollUtil.isNotEmpty(generalLevelFactoryIds)) {
            insertOrUpdateFactoryLabel(generalLevelFactoryIds, generalLevel, factoryLabelChangeDTO.getEnumId());
        }
    }

    //根据企业ID获取企业详细信息
    private Map<String, PcFactory> queryByFactoryIds(Set<String> factoryIds) {
        List<PcFactory> factoryList = pcFactoryMapper.selectBatchIds(factoryIds);
        if (CollUtil.isNotEmpty(factoryList)) {
            return factoryList.stream().filter(f -> StringUtils.isNotBlank(f.getCityCode())).collect(Collectors.toMap(PcFactory::getId, Function.identity(), (k1, k2) -> k2));
        }
        return Maps.newHashMap();
    }

    //根据污染物code获取上一年年报的实际实际排放量
    public List<SRaActionReportsActualEmissions> queryByCurrentPollutantCode(String currentPollutantCode) {
        LambdaQueryWrapper<SRaActionReportsActualEmissions> lambdaQueryWrapper = new QueryWrapper<SRaActionReportsActualEmissions>().lambda()
                .select(SRaActionReportsActualEmissions::getFactoryId)
                .select(SRaActionReportsActualEmissions::getActualEmissions)
                .eq(SRaActionReportsActualEmissions::getPollutantCode, currentPollutantCode)
                .eq(SRaActionReportsActualEmissions::getReportType, "y")
                .eq(SRaActionReportsActualEmissions::getReportTime, Integer.parseInt(DateUtil.getYear()) - 1);
        List<SRaActionReportsActualEmissions> raActionReportsActualEmissions = sRaActionReportsActualEmissionsMapper.selectList(lambdaQueryWrapper);
        if (CollUtil.isNotEmpty(raActionReportsActualEmissions)) {
            return raActionReportsActualEmissions.stream()
                    .filter(r -> StringUtils.isNotBlank(r.getFactoryId()) && Objects.nonNull(r.getActualEmissions()) && r.getActualEmissions().compareTo(BigDecimal.ZERO) > 0)
                    .collect(Collectors.toList());
        }
        return Lists.newArrayList();
    }
}
