package com.moral.api.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.moral.api.config.properties.AnnouncementProperties;
import com.moral.api.config.properties.SpecialCitiesProperties;
import com.moral.api.entity.CityAqiDaily;
import com.moral.api.entity.CityAqiMonthly;
import com.moral.api.entity.SysArea;
import com.moral.api.mapper.CityAqiMonthlyMapper;
import com.moral.api.service.CityAqiDailyService;
import com.moral.api.service.CityAqiMonthlyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.moral.api.service.SysAreaService;
import com.moral.constant.Constants;
import com.moral.constant.RedisConstants;
import com.moral.util.AmendUtils;
import com.moral.util.ComprehensiveIndexUtils;
import com.moral.util.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import java.text.DecimalFormat;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.OptionalDouble;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
/**
 * 
 * 城市aqi月数据表 服务实现类
 * 
 *
 * @author moral
 * @since 2021-11-05
 */
@Service
public class CityAqiMonthlyServiceImpl extends ServiceImpl implements CityAqiMonthlyService {
    @Autowired
    private CityAqiMonthlyMapper cityAqiMonthlyMapper;
    @Autowired
    private SpecialCitiesProperties specialCitiesProperties;
    @Autowired
    private SysAreaService sysAreaService;
    @Autowired
    private CityAqiDailyService cityAqiDailyService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private AnnouncementProperties announcementProperties;
    @Override
    public List getCityAqiMonthByRegionCodeAndTime(Integer regionCode, Date startDate, Date endDate) {
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("city_code", regionCode);
        queryWrapper.between("time", startDate, endDate);
        return cityAqiMonthlyMapper.selectList(queryWrapper);
    }
    @Override
    public CityAqiMonthly getCityAqiMonthByRegionCodeAndTime(Integer regionCode, Date time) {
        time = DateUtils.getFirstDayOfMonth(time);
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("city_code", regionCode);
        queryWrapper.eq("time", time);
        return cityAqiMonthlyMapper.selectOne(queryWrapper);
    }
    @Override
    public Map airQualityRankingAnnouncement(Integer regionCode, Date time) {
        Map result = new LinkedHashMap<>();
        String month = DateUtils.getMonth(time) + "";
        int yearMonthOfSelect = Integer.parseInt(DateUtils.dateToDateString(time, DateUtils.yyyyMM_EN));
        int nowYearMonthOfSelect = Integer.parseInt(DateUtils.getCurDate(DateUtils.yyyyMM_EN));
        if (yearMonthOfSelect > nowYearMonthOfSelect) {
            return result;
        }
        //先根据时间和地区code从redis中获取,没有再计算后存入redis
        result = (Map) redisTemplate.opsForValue().get(RedisConstants.AQI_ANNOUNCEMENT + "_" + regionCode + "_" + DateUtils.dateToDateString(time, DateUtils.yyyyMM_EN));
        if (result != null) {
            return result;
        }
        result = new LinkedHashMap<>();
        //获取xx市和所有县市区名字信息
        QueryWrapper sysAreaQueryWrapper = new QueryWrapper<>();
        sysAreaQueryWrapper.select("area_code", "area_name")
                .eq("parent_code", regionCode).or()
                .eq("area_code", regionCode);
        List sysAreas = sysAreaService.list(sysAreaQueryWrapper);
        Map areasMap = new HashMap<>();
        for (SysArea sysArea : sysAreas) {
            areasMap.put(sysArea.getAreaCode(), sysArea.getAreaName());
        }
        String cityName = areasMap.remove(regionCode);
        result.put("cityName", cityName);
        result.put("areaSize", areasMap.size());
        //一、空气质量排名
        //1.本月xx市空气质量排名
        Map currentRankingResult = new HashMap<>();
        //获取本月xx市空气质量数据
        QueryWrapper cityAqiMonthlyQueryWrapper = new QueryWrapper<>();
        cityAqiMonthlyQueryWrapper.select("value")
                .eq("city_code", regionCode)
                .eq("time", time);
        CityAqiMonthly cityAqiMonthly = cityAqiMonthlyMapper.selectOne(cityAqiMonthlyQueryWrapper);
        Double compositeIndex = null;
        String compositeIndexYearOnYear = null;
        Integer pm25 = null;
        String pm25YearOnYear = null;
        if (cityAqiMonthly != null) {
            Map aqiMap = JSONObject.parseObject(cityAqiMonthly.getValue(), Map.class);
            //1.综指
            if (aqiMap.get("compositeIndex") != null) {
                compositeIndex = Double.parseDouble(aqiMap.get("compositeIndex").toString());
            }
            currentRankingResult.put("compositeIndex", compositeIndex);
            //2.综指同比
            if (aqiMap.get("compositeIndex_yearOnYear") != null) {
                compositeIndexYearOnYear = aqiMap.get("compositeIndex_yearOnYear").toString();
            }
            currentRankingResult.put("compositeIndex_yearOnYear", compositeIndexYearOnYear);
            //3.PM2.5浓度
            if (aqiMap.get("PM2_5") != null) {
                pm25 = Integer.parseInt(aqiMap.get("PM2_5").toString());
            }
            currentRankingResult.put("PM2_5", pm25 + "ug/m³");
            //4.PM.5浓度同比
            if (aqiMap.get("PM2_5_yearOnYear") != null) {
                pm25YearOnYear = aqiMap.get("PM2_5_yearOnYear").toString();
            }
            currentRankingResult.put("PM2_5_yearOnYear", pm25YearOnYear);
            //5.168城市排名,包括综指,综指同比,pm2.5,pm2.5同比
            Map ranking168 = getOneSixEightCitiesRanking(regionCode, time);
            currentRankingResult.putAll(ranking168);
            //6.2+26城市排名,包括综指,综指同比,pm2.5,pm2.5同比
            Map ranking28 = getTwentyEightCitiesRanking(regionCode, time);
            currentRankingResult.putAll(ranking28);
            //7.河北八通道城市排名,包括综指,综指同比,pm2.5,pm2.5同比
            Map ranking8Channels = getHeBeiEightCitiesRanking(regionCode, time);
            currentRankingResult.putAll(ranking8Channels);
        }
        String start = DateUtils.dateToDateString(time, DateUtils.yyyy_MM_dd_CN);
        //本月最后一日
        String end = DateUtils.dateToDateString(DateUtils.getLastDayOfMonth(time), DateUtils.yyyy_MM_dd_CN);
        result.put("currentRanking", aqiQualityRankingResponse(start + "-" + end, cityName, currentRankingResult));
        //2.1-x月xx市空气质量排名
        //所有县市区codes
        List areaCodes = new ArrayList<>(areasMap.keySet());
        //地级市code
        areaCodes.add(regionCode);
        Map> monthlyCumulativeResult = null;
        Double cityCompositeIndex = null;
        String cityCompositeIndexYearOnYear = null;
        Integer cityPM25 = null;
        String cityPM25YearOnYear = null;
        if (!"1".equals(month)) {
            Map cumulativeRankingResult = new HashMap<>();
            //获取xx市和下属所有县市区1-xx月数据
            monthlyCumulativeResult = getMonthlyCumulativeResult(time, areaCodes);
            //xx市数据
            if (monthlyCumulativeResult != null) {
                Map cityMap = monthlyCumulativeResult.remove(regionCode);
                if (cityMap != null) {
                    //地级市综指
                    cityCompositeIndex = Double.parseDouble(cityMap.get("compositeIndex").toString());
                    if (cityMap.get("compositeIndex_yearOnYear") != null) {
                        cityCompositeIndexYearOnYear = cityMap.get("compositeIndex_yearOnYear").toString();
                    }
                    //地级市PM2.5
                    cityPM25 = (int) Double.parseDouble(cityMap.get("PM2_5").toString());
                    if (cityMap.get("PM2_5_yearOnYear") != null) {
                        cityPM25YearOnYear = cityMap.get("PM2_5_yearOnYear").toString();
                    }
                }
            }
            cumulativeRankingResult.put("compositeIndex", cityCompositeIndex);
            cumulativeRankingResult.put("compositeIndex_yearOnYear", cityCompositeIndexYearOnYear);
            cumulativeRankingResult.put("PM2_5", cityPM25);
            if (cityPM25 != null) {
                cumulativeRankingResult.put("PM2_5", cityPM25 + "ug/m³");
            }
            cumulativeRankingResult.put("PM2_5_yearOnYear", cityPM25YearOnYear);
            //5.168城市排名,包括综指,综指同比,pm2.5,pm2.5同比
            Map ranking168 = getOneSixEightCitiesRankingOfCumulative(regionCode, time);
            cumulativeRankingResult.putAll(ranking168);
            //6.2+26城市排名,包括综指,综指同比,pm2.5,pm2.5同比
            Map ranking28 = getTwentyEightCitiesRankingOfCumulative(regionCode, time);
            cumulativeRankingResult.putAll(ranking28);
            //7.河北八通道城市排名,包括综指,综指同比,pm2.5,pm2.5同比
            Map ranking8Channels = getHeBeiEightCitiesRankingOfCumulative(regionCode, time);
            cumulativeRankingResult.putAll(ranking8Channels);
            //开始时间,当年1月1日
            start = DateUtils.dateToDateString(DateUtils.getFirstDayOfYear(time), DateUtils.yyyy_MM_dd_CN);
            //结束时间,当月最后一天
            end = DateUtils.dateToDateString(DateUtils.getLastDayOfMonth(time), DateUtils.yyyy_MM_dd_CN);
            result.put("cumulativeRanking", aqiQualityRankingResponse(start + "-" + end, cityName, cumulativeRankingResult));
        }
        //二、各县市区空气质量情况结果集
        //获取本期xx市下所有县市区数据
        cityAqiMonthlyQueryWrapper.clear();
        areaCodes.remove(regionCode);
        cityAqiMonthlyQueryWrapper.select("city_code", "value")
                .eq("time", time)
                .in("city_code", areaCodes);
        List areaData = cityAqiMonthlyMapper.selectList(cityAqiMonthlyQueryWrapper);
        //获取本期所有县市区与中心城区(地级市)因子对比情况
        Map areaCurrentMonthResult = getAreaCurrentMonthResult(areasMap, areaData, compositeIndex, compositeIndexYearOnYear, pm25, pm25YearOnYear);
        //本月县市区综指与中心城区对比
        result.put("currentCompositeIndexContrast", compositeIndexContrastResponse(month, cityName, areaCodes.size(), areaCurrentMonthResult));
        //本月县市区综指同比与中心城区对比
        result.put("currentCompositeIndexYearOnYearContrast", compositeIndexYearOnYearContrastResponse(month, cityName, areaCodes.size(), areaCurrentMonthResult));
        //本月县市区PM2.5与中心城区对比
        result.put("currentPM25Contrast", pm25tContrastResponse(month, cityName, areaCodes.size(), areaCurrentMonthResult));
        //本月县市区Pm2.5同比与中心城区对比
        result.put("currentPM25YearOnYearContrast", pm25YearOnYearContrastResponse(month, cityName, areaCodes.size(), areaCurrentMonthResult));
        //三、1-x月累计结果
        List cumulativeList = null;
        if (!"1".equals(month)) {
            cumulativeList = new ArrayList<>();
            if (monthlyCumulativeResult != null) {
                for (Map.Entry> entry : monthlyCumulativeResult.entrySet()) {
                    CityAqiMonthly cityAqiMonthly1 = new CityAqiMonthly();
                    cityAqiMonthly1.setCityCode(entry.getKey());
                    cityAqiMonthly1.setValue(JSONObject.toJSONString(entry.getValue()));
                    cumulativeList.add(cityAqiMonthly1);
                }
            }
            month = "1-" + DateUtils.getMonth(time);
            //获取1-x月所有县市区与地级市数据对比情况
            Map monthlyCumulativeListResultMap = getAreaCurrentMonthResult(areasMap, cumulativeList, cityCompositeIndex, cityCompositeIndexYearOnYear, cityPM25, cityPM25YearOnYear);
            //1-xx月份县市区综指与中心城区对比
            result.put("cumulativeCompositeIndexContrast", compositeIndexContrastResponse(month, cityName, areaCodes.size(), monthlyCumulativeListResultMap));
            //1-xx月份县市区综指同比与中心城区对比
            result.put("cumulativeCompositeIndexYearOnYearContrast", compositeIndexYearOnYearContrastResponse(month, cityName, areaCodes.size(), monthlyCumulativeListResultMap));
            //1-xx月份县市区PM2.5与中心城区对比
            result.put("cumulativePM25Contrast", pm25tContrastResponse(month, cityName, areaCodes.size(), monthlyCumulativeListResultMap));
            //1-xx月份县市区Pm2.5同比与中心城区对比
            result.put("cumulativePM25YearOnYearContrast", pm25YearOnYearContrastResponse(month, cityName, areaCodes.size(), monthlyCumulativeListResultMap));
        }
        //四、附件
        //1.本期综指和pm2.5考核排名报表
        List