package cn.cecep.talroad.service.impl.analysis;

import cn.cecep.talroad.common.core.domain.R;
import cn.cecep.talroad.common.core.utils.DateUtils;
import cn.cecep.talroad.common.core.utils.StringUtils;
import cn.cecep.talroad.common.security.utils.SecurityUtils;
import cn.cecep.talroad.data.analyse.task.real.concentration.GasConcentrationEnum;
import cn.cecep.talroad.domain.SEnvGasMonHour;
import cn.cecep.talroad.domain.SEnvWaterMonHour;
import cn.cecep.talroad.domain.analysis.SRaOverRateGas;
import cn.cecep.talroad.domain.analysis.SRaOverRateWater;
import cn.cecep.talroad.enums.TimeTypeEnum;
import cn.cecep.talroad.feign.BaseRegionService;
import cn.cecep.talroad.enums.StatisticsTypeEnum;
import cn.cecep.talroad.mapper.analysis.SRaOverRateGasMapper;
import cn.cecep.talroad.mapper.analysis.SRaOverRateWaterMapper;
import cn.cecep.talroad.service.IAmProblemFiService;
import cn.cecep.talroad.service.ISEnvGasMonHourService;
import cn.cecep.talroad.service.ISEnvWaterMonHourService;
import cn.cecep.talroad.service.analysis.ISRaOverRateGasService;
import cn.cecep.talroad.service.analysis.ISRaOverRateWaterService;
import cn.cecep.talroad.service.impl.TCodStationServiceImpl.WaterPollutantEnum;
import cn.cecep.talroad.vo.analysis.FactoryOutletStaticsVo;
import cn.cecep.talroad.vo.analysis.SRaOverRateGasVo;
import cn.cecep.talroad.vo.query.analysis.SRaOverRateGasQuery;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.ArrayList;
import java.util.List;


/**
 * 超标率分析-气污染要素Service业务层处理
 */
@Service
public class SRaOverRateGasServiceImpl extends ServiceImpl<SRaOverRateGasMapper, SRaOverRateGas> implements ISRaOverRateGasService
{
    @Autowired
    @Qualifier("baseRegionService")
    private BaseRegionService baseRegionService;
    @Autowired
    private IAmProblemFiService amProblemFiService;
    @Autowired
    private ISEnvGasMonHourService isEnvGasMonHourService;
    @Autowired
    private ISEnvWaterMonHourService isEnvWaterMonHourService;
    @Autowired
    private ISRaOverRateWaterService isRaOverRateWaterService;
    @Autowired
    private SRaOverRateGasMapper sRaOverRateGasMapper;

    @Override
    public List<SRaOverRateGasVo> selectOverRateGasPage(Page<SRaOverRateGasVo> page, SRaOverRateGasQuery query)
    {
        // 若未指定，查询当前用户区域下的数据
        if (StringUtils.isEmpty(query.getRegionCode())) {
            String userRegionCode = SecurityUtils.getLoginUser().getSysUser().getRegionCode();

            if (StringUtils.isEmpty(userRegionCode)) {
                return new ArrayList<>();
            }
            R<List<String>> r = baseRegionService.getRegionCodeListChild(userRegionCode);
            if (r.getCode() == R.SUCCESS) {
                query.setRegionCodeList(r.getData());
            } else {
                return new ArrayList<>();
            }
        }

        List<SRaOverRateGasVo> vos = baseMapper.selectOverRateGasPage(page, query);
        page.setRecords(vos);
        return vos;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean periodTask(StatisticsTypeEnum statisticsTypeEnum, String statisticsTime, Date startTime, Date endTime) {
        Map<String,SRaOverRateGas> gasMap = new HashMap<>();
        Map<String,SRaOverRateWater> waterMap = new HashMap<>();

        if(statisticsTypeEnum.MONTH.getType().equals(statisticsTypeEnum.getType())){
            List<FactoryOutletStaticsVo> list = amProblemFiService.selectStatisDataByMonth(startTime,endTime);
            if(list!=null&&list.size()>0){
                list.forEach(outlet->{
                    if(outlet.getParamName().contains(WaterPollutantEnum.totalNitrogen.label)
                        ||outlet.getParamName().contains(WaterPollutantEnum.cod.label)
                        ||outlet.getParamName().contains(WaterPollutantEnum.ammoniaNitrogen.label)
                        ||outlet.getParamName().contains(WaterPollutantEnum.totalPhosphorus.label)){
                        QueryWrapper<SEnvWaterMonHour> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("factory_id",outlet.getFactoryId());
                        queryWrapper.eq("outlet_id",outlet.getOutletId());
                        queryWrapper.eq("data_type", TimeTypeEnum.HOUR.getCode());
                        queryWrapper.between("monitoring_time",startTime,endTime);
                        if(WaterPollutantEnum.totalNitrogen.label.equals(outlet.getParamName())){
                            queryWrapper.and(wp->{
                                wp.isNull("nitrogen_concentration_flag").or().in("nitrogen_concentration_flag", Arrays.asList("S", "N", "ST", "SD", "B", "FA","STA"));
                            });
                        }else if(WaterPollutantEnum.cod.label.equals(outlet.getParamName())){
                            queryWrapper.and(wp->{
                                wp.isNull("cod_flag").or().in("cod_flag", Arrays.asList("S", "N", "ST", "SD", "B", "FA","STA"));
                            });
                        }else if(WaterPollutantEnum.ammoniaNitrogen.label.contains(outlet.getParamName())){
                            queryWrapper.and(wp->{
                                wp.isNull("ammonia_nitrogen_flag").or().in("ammonia_nitrogen_flag", Arrays.asList("S", "N", "ST", "SD", "B", "FA","STA"));
                            });
                        }else if(WaterPollutantEnum.totalPhosphorus.label.contains(outlet.getParamName())){
                            queryWrapper.and(wp->{
                                wp.isNull("phosphorus_concentration_flag").or().in("phosphorus_concentration_flag", Arrays.asList("S", "N", "ST", "SD", "B", "FA","STA"));
                            });
                        }
                        // 计算排口小时污染物有效数据数量
                        Integer validCount = isEnvWaterMonHourService.count(queryWrapper);
                        if(validCount>0) {
                            BigDecimal rate = BigDecimal.valueOf(outlet.getActualCount()).divide(BigDecimal.valueOf(validCount), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
                            String key = outlet.getFactoryId() + outlet.getOutletId();
                            SRaOverRateWater rateWater = waterMap.get(key);
                            if (rateWater == null) {
                                rateWater = new SRaOverRateWater();
                                rateWater.setId(UUID.randomUUID().toString());
                                rateWater.setFactoryId(outlet.getFactoryId());
                                rateWater.setOutletCode(outlet.getOutletId());
                                rateWater.setPointName(outlet.getOutletName());
                                rateWater.setStatisticsType(statisticsTypeEnum.getType());
                                rateWater.setStatisticsTime(statisticsTime);
                                rateWater.setValidDataCount(String.valueOf(validCount));
                                rateWater.setCreateTime(new Date());
                                if (WaterPollutantEnum.totalNitrogen.label.equals(outlet.getParamName())) {
                                    rateWater.setTnOverCount(String.valueOf(outlet.getActualCount()));
                                    rateWater.setTnOverRate(String.valueOf(rate));
                                } else if (WaterPollutantEnum.cod.label.equals(outlet.getParamName())) {
                                    rateWater.setCodOverCount(String.valueOf(outlet.getActualCount()));
                                    rateWater.setCodOverRate(String.valueOf(rate));
                                } else if (WaterPollutantEnum.ammoniaNitrogen.label.contains(outlet.getParamName())) {
                                    rateWater.setTnOverCount(String.valueOf(outlet.getActualCount()));
                                    rateWater.setTnOverRate(String.valueOf(rate));
                                } else if (WaterPollutantEnum.totalPhosphorus.label.contains(outlet.getParamName())) {
                                    rateWater.setTpOverCount(String.valueOf(outlet.getActualCount()));
                                    rateWater.setTpOverRate(String.valueOf(rate));
                                }
                            } else {
                                if (WaterPollutantEnum.totalNitrogen.label.equals(outlet.getParamName())) {
                                    rateWater.setTnOverCount(String.valueOf(outlet.getActualCount()));
                                    rateWater.setTnOverRate(String.valueOf(rate));
                                } else if (WaterPollutantEnum.cod.label.equals(outlet.getParamName())) {
                                    rateWater.setCodOverCount(String.valueOf(outlet.getActualCount()));
                                    rateWater.setCodOverRate(String.valueOf(rate));
                                } else if (WaterPollutantEnum.ammoniaNitrogen.label.contains(outlet.getParamName())) {
                                    rateWater.setNh3OverCount(String.valueOf(outlet.getActualCount()));
                                    rateWater.setNh3OverRate(String.valueOf(rate));
                                } else if (WaterPollutantEnum.totalPhosphorus.label.contains(outlet.getParamName())) {
                                    rateWater.setTpOverCount(String.valueOf(outlet.getActualCount()));
                                    rateWater.setTpOverRate(String.valueOf(rate));
                                }
                            }
                        }
                    }else {
                        // 包含水、气站点
                        QueryWrapper<SEnvGasMonHour> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("factory_id", outlet.getFactoryId());
                        queryWrapper.eq("outlet_id", outlet.getOutletId());
                        queryWrapper.eq("data_type", TimeTypeEnum.HOUR.getCode());
                        queryWrapper.between("monitoring_time", startTime, endTime);
                        if (GasConcentrationEnum.so2.getPollutantsName().equals(outlet.getParamName())) {
                            queryWrapper.and(wp->{
                                wp.isNull("so2_flag").or().in("so2_flag", Arrays.asList("S", "N", "ST", "SD", "B", "FA","STA"));
                            });
                        } else if (GasConcentrationEnum.nox.getPollutantsName().equals(outlet.getParamName())) {
                            queryWrapper.and(wp->{
                                wp.isNull("nox_flag").or().in("nox_flag", Arrays.asList("S", "N", "ST", "SD", "B", "FA","STA"));
                            });
                        } else if (GasConcentrationEnum.pm.getPollutantsName().contains(outlet.getParamName())) {
                            queryWrapper.and(wp->{
                                wp.isNull("smoke_dust_flag").or().in("smoke_dust_flag", Arrays.asList("S", "N", "ST", "SD", "B", "FA","STA"));
                            });
                        }
                        Integer validCount = isEnvGasMonHourService.count(queryWrapper);
                        if (validCount > 0) {
                            BigDecimal rate = BigDecimal.valueOf(outlet.getActualCount()).divide(BigDecimal.valueOf(validCount), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
                            String key = outlet.getFactoryId() + outlet.getOutletId();
                            SRaOverRateGas rateGas = gasMap.get(key);
                            if (rateGas == null) {
                                rateGas = new SRaOverRateGas();
                                rateGas.setId(UUID.randomUUID().toString());
                                rateGas.setFactoryId(outlet.getFactoryId());
                                rateGas.setOutletCode(outlet.getOutletId());
                                rateGas.setPointName(outlet.getOutletName());
                                rateGas.setStatisticsType(statisticsTypeEnum.getType());
                                rateGas.setStatisticsTime(statisticsTime);
                                rateGas.setValidDataCount(String.valueOf(validCount));
                                rateGas.setCreateTime(new Date());
                                if (GasConcentrationEnum.so2.getPollutantsName().equals(outlet.getParamName())) {
                                    rateGas.setSo2OverCount(String.valueOf(outlet.getActualCount()));
                                    rateGas.setSo2OverRate(String.valueOf(rate));
                                } else if (GasConcentrationEnum.nox.getPollutantsName().equals(outlet.getParamName())) {
                                    rateGas.setNoxOverCount(String.valueOf(outlet.getActualCount()));
                                    rateGas.setNoxOverRate(String.valueOf(rate));
                                } else if (GasConcentrationEnum.pm.getPollutantsName().contains(outlet.getParamName())) {
                                    rateGas.setPmOverCount(String.valueOf(outlet.getActualCount()));
                                    rateGas.setPmOverRate(String.valueOf(rate));
                                }
                            } else {
                                if (GasConcentrationEnum.so2.getPollutantsName().equals(outlet.getParamName())) {
                                    rateGas.setSo2OverCount(String.valueOf(outlet.getActualCount()));
                                    rateGas.setSo2OverRate(String.valueOf(rate));
                                } else if (GasConcentrationEnum.nox.getPollutantsName().equals(outlet.getParamName())) {
                                    rateGas.setNoxOverCount(String.valueOf(outlet.getActualCount()));
                                    rateGas.setNoxOverRate(String.valueOf(rate));
                                } else if (GasConcentrationEnum.pm.getPollutantsName().contains(outlet.getParamName())) {
                                    rateGas.setPmOverCount(String.valueOf(outlet.getActualCount()));
                                    rateGas.setPmOverRate(String.valueOf(rate));
                                }
                            }
                        }
                    }
                });
                // 空气
                if(gasMap.values().size()>0){
                    this.saveBatch(gasMap.values());
                }
                // 水
                if(waterMap.values().size()>0){
                    isRaOverRateWaterService.saveBatch(waterMap.values());
                }
            }
        }else {
            List<String> monthList = DateUtils.getRangeTimes("N",startTime,endTime);
            // 统计季度、年度数据
            List<SRaOverRateGas> rateGasList = sRaOverRateGasMapper.selectByMonthData(monthList);
            if(rateGasList!=null&&rateGasList.size()>0){
                rateGasList.forEach(gas->{
                    gas.setId(UUID.randomUUID().toString());
                    gas.setStatisticsTime(statisticsTime);
                    gas.setStatisticsType(statisticsTypeEnum.getType());
                });
                this.saveBatch(rateGasList);
            }

            // 统计季度、年度数据
            List<SRaOverRateWater> rateWaterList = isRaOverRateWaterService.selectWaterDataByMonth(monthList);
            if(rateWaterList!=null&&rateWaterList.size()>0){
                rateWaterList.forEach(gas->{
                    gas.setId(UUID.randomUUID().toString());
                    gas.setStatisticsTime(statisticsTime);
                    gas.setStatisticsType(statisticsTypeEnum.getType());
                });
                isRaOverRateWaterService.saveBatch(rateWaterList);
            }
        }
        return true;
    }



}
