package com.yeejoin.amos.boot.module.statistcs.biz.service.impl.ZBGLImpl;

import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.dto.KeyValueDto;
import com.yeejoin.amos.boot.module.common.api.dto.DPFilterParamForDetailDto;
import com.yeejoin.amos.boot.module.statistcs.biz.service.IZBGLService;
import com.yeejoin.amos.boot.module.statistcs.biz.service.impl.AQZSDPStatisticsServiceImpl;
import com.yeejoin.amos.boot.module.statistcs.biz.service.impl.StCommonServiceImpl;
import com.yeejoin.amos.boot.module.statistics.api.dto.SecurityIndexCountItemDto;
import com.yeejoin.amos.boot.module.statistics.api.mapper.AQZSDPStatisticsMapper;
import com.yeejoin.amos.boot.module.statistics.api.mapper.CylinderStatisticsMapper;
import com.yeejoin.amos.boot.module.statistics.api.mapper.ZBGLStatisticsMapper;
import com.yeejoin.amos.feign.systemctl.model.RegionModel;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.core.CountResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class QyaqzstjServiceImpl implements IZBGLService {

    private final static String LICENSE_IS_OK = "正常";
    private final static String NO_DATA_STR = "--";
    @Resource
    private StCommonServiceImpl stCommonService;

    @Resource
    private ZBGLStatisticsMapper zbglStatisticsMapper;
    @Resource
    private CylinderStatisticsMapper cylinderStatisticsMapper;
    @Resource
    private AQZSDPStatisticsMapper statisticsMapper;
    @Resource
    private RestHighLevelClient restHighLevelClient;
    @Override
    public Map<String, Object> getChart(DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        List<RegionModel> regionModels = stCommonService.setRegionIfRootParent(dpFilterParamForDetailDto.getCityCode());
        List<SecurityIndexCountItemDto> result =  regionModels.parallelStream().map(r -> {
            String orgCode = stCommonService.getAndSetOrgCode(r.getRegionCode()+"");
            SecurityIndexCountItemDto countItemDto = new SecurityIndexCountItemDto();
            countItemDto.setRegionCode(r.getRegionCode().toString());
            countItemDto.setRegionName(r.getRegionName());
            if (ObjectUtils.isEmpty(orgCode)) {
                this.setDefaultZeroData(countItemDto);
            } else {
                // 1.许可有效率
                String value = this.getLicenseEfficiencyByRegion(orgCode);
                if (NO_DATA_STR.equals(value)) {
                    value = "0";
                    countItemDto.setXuke(value);
                } else {
                    countItemDto.setXuke(value);
                }
                // 2.使用登记办理率
                countItemDto.setShiyongdengji(cylinderStatisticsMapper.queryUserRegisterCertAppPercent(orgCode));
                // 3.检验超期率
                countItemDto.setJianyanchaoqi(statisticsMapper.getInspectionExpiredRate(orgCode, null).get("expiredRate").toString());
                // 4.检验合格率
                countItemDto.setJianyanhege(statisticsMapper.getInspectionResultRate(orgCode, null).get("resultRate").toString());
                // 5.充装检查率
                long totalAll = searchEsCount(false, false, orgCode, null);
                long totalCheck = searchEsCount(true, false, orgCode, null);
                long totalResult = searchEsCount(false, true, orgCode, null);
                if (totalAll != 0) {
                    countItemDto.setCzjc(new DecimalFormat("#.00").format(((double) totalCheck / totalAll) * 100));
                } else {
                    countItemDto.setCzjc("0");
                }
                // 6.充装检查合格率
                if (totalAll != 0) {
                    countItemDto.setCzjchege(new DecimalFormat("#.00").format(((double) totalResult / totalAll) * 100));
                } else {
                    countItemDto.setCzjchege("0");
                }
                // todo: 7.人员合规率（资质有效期统计） 8.数据合规率需求未明确暂时都为0
                // 7.人员合规率（资质有效期统计）
                countItemDto.setRyhg("0");
                // 8.数据合规率
                countItemDto.setSjhg("0");
            }
            return countItemDto;
        }).collect(Collectors.toList());

        Set<Map<String, String>> legendData = getLegendForCyArea();
        List<String> xuke = new ArrayList<>();
        List<String> shiyongdengji = new ArrayList<>();
        List<String> jianyanchaoqi = new ArrayList<>();
        List<String> jianyanhege = new ArrayList<>();
        List<String> czjc = new ArrayList<>();
        List<String> czjchege = new ArrayList<>();
        List<String> ryhg = new ArrayList<>();
        List<String> sjhg = new ArrayList<>();
        List<String> xdata = new ArrayList<>();
        result.forEach(countItemDto -> {
            xuke.add(this.castScore2Percent(countItemDto.getXuke()));
            shiyongdengji.add(this.castScore2Percent(countItemDto.getShiyongdengji()));
            jianyanchaoqi.add(this.castScore2Percent(countItemDto.getJianyanchaoqi()));
            jianyanhege.add(this.castScore2Percent(countItemDto.getJianyanhege()));
            czjc.add(this.castScore2Percent(countItemDto.getCzjc()));
            czjchege.add(this.castScore2Percent(countItemDto.getCzjchege()));
            ryhg.add(this.castScore2Percent(countItemDto.getRyhg()));
            sjhg.add(this.castScore2Percent(countItemDto.getSjhg()));
            xdata.add(countItemDto.getRegionName());
        });
        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("xdata", xdata);
        returnMap.put("legendData", legendData);
        returnMap.put("xuke", xuke);
        returnMap.put("shiyongdengji", shiyongdengji);
        returnMap.put("jianyanchaoqi", jianyanchaoqi);
        returnMap.put("jianyanhege", jianyanhege);
        returnMap.put("czjc", czjc);
        returnMap.put("czjchege", czjchege);
        returnMap.put("ryhg", ryhg);
        returnMap.put("sjhg", sjhg);

        return returnMap;
    }

    @Override
    public Page<Map<String, Object>> getPage(Page page,DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        List<RegionModel> regionModels = stCommonService.setRegionIfRootParent(dpFilterParamForDetailDto.getCityCode());
        List<SecurityIndexCountItemDto> result =  regionModels.parallelStream().map(r -> {
            String orgCode = stCommonService.getAndSetOrgCode(r.getRegionCode()+"");
            SecurityIndexCountItemDto countItemDto = new SecurityIndexCountItemDto();
            countItemDto.setRegionCode(r.getRegionCode().toString());
            countItemDto.setRegionName(r.getRegionName());
            if (ObjectUtils.isEmpty(orgCode)) {
                this.setDefaultZeroData(countItemDto);
            } else {
                // 1.许可有效率
                String value = this.getLicenseEfficiencyByRegion(orgCode);
                if (NO_DATA_STR.equals(value)) {
                    value = "0";
                    countItemDto.setXuke(value);
                } else {
                    countItemDto.setXuke(value);
                }
                // 2.使用登记办理率
                countItemDto.setShiyongdengji(cylinderStatisticsMapper.queryUserRegisterCertAppPercent(orgCode));
                // 3.检验超期率
                countItemDto.setJianyanchaoqi(statisticsMapper.getInspectionExpiredRate(orgCode, null).get("expiredRate").toString());
                // 4.检验合格率
                countItemDto.setJianyanhege(statisticsMapper.getInspectionResultRate(orgCode, null).get("resultRate").toString());
                // 5.充装检查率
                long totalAll = searchEsCount(false, false, orgCode, null);
                long totalCheck = searchEsCount(true, false, orgCode, null);
                long totalResult = searchEsCount(false, true, orgCode, null);
                if (totalAll != 0) {
                    countItemDto.setCzjc(new DecimalFormat("#.00").format(((double) totalCheck / totalAll) * 100));
                } else {
                    countItemDto.setCzjc("0");
                }
                // 6.充装检查合格率
                if (totalAll != 0) {
                    countItemDto.setCzjchege(new DecimalFormat("#.00").format(((double) totalResult / totalAll) * 100));
                } else {
                    countItemDto.setCzjchege("0");
                }
                // todo: 7.人员合规率（资质有效期统计） 8.数据合规率需求未明确暂时都为0
                // 7.人员合规率（资质有效期统计）
                countItemDto.setRyhg("0");
                // 8.数据合规率
                countItemDto.setSjhg("0");
            }
            return countItemDto;
        }).collect(Collectors.toList());
        page.setRecords(result);
        return page;
    }

    @Override
    public List<Map<String, String>> getTitle(DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        List<Map<String, String>> list = new ArrayList<>();
        for(int i = 0; i < 9; i++){
            Map<String,String> map = new HashMap<>();
            if(i == 0){
                map.put("dataIndex","regionName");
                map.put("title","区域");
            }else if(i == 1){
                map.put("dataIndex","czjc");
                map.put("title","充装检查率");
            }else if(i == 2){
                map.put("dataIndex","xuke");
                map.put("title","许可有效率");
            }else if(i == 3){
                map.put("dataIndex","shiyongdengji");
                map.put("title","使用登记办理率");
            }else if(i == 4){
                map.put("dataIndex","jianyanchaoqi");
                map.put("title","检验超期率");
            }else if(i == 5){
                map.put("dataIndex","jianyanhege");
                map.put("title","检验合格率");
            }else if(i == 6){
                map.put("dataIndex","czjchege");
                map.put("title","充装检查率");
            }else if(i == 7){
                map.put("dataIndex","ryhg");
                map.put("title","人员合规率（资质有效期统计）");
            }else if(i == 8){
                map.put("dataIndex","sjhg");
                map.put("title","数据合规率");
            }
            list.add(map);
        }

        return list;
    }

    private void setDefaultZeroData(SecurityIndexCountItemDto countItemDto) {
        countItemDto.setXuke("0");
        countItemDto.setShiyongdengji("0");
        countItemDto.setJianyanhege("0");
        countItemDto.setCzjc("0");
        countItemDto.setCzjchege("0");
        countItemDto.setJianyanchaoqi("0");
        countItemDto.setRyhg("0");
        countItemDto.setSjhg("0");
    }

    private long searchEsCount(Boolean checkOk, Boolean resultOk, String regionCode, String appId) {
        CountRequest countRequest = new CountRequest("cylinder_filling");
        BoolQueryBuilder boolMust = QueryBuilders.boolQuery();
        if (checkOk) {
            //匹配充装前检查和充装后检查都有数据
            BoolQueryBuilder meBuilder = QueryBuilders.boolQuery();
            meBuilder.must(QueryBuilders.existsQuery("inspectionDateMs"));
            meBuilder.must(QueryBuilders.existsQuery("inspectionDateAfterMS"));
            boolMust.must(meBuilder);
        }
        if (resultOk) {
            //匹配充装前检查和充装后检查都有数据
            BoolQueryBuilder meBuilder = QueryBuilders.boolQuery();
            meBuilder.must(QueryBuilders.termQuery("fillingResult.keyword", "合格"));
            meBuilder.must(QueryBuilders.termQuery("checkResult.keyword", "合格"));
            boolMust.must(meBuilder);
        }

        //匹配行政区划
        if (!ObjectUtils.isEmpty(regionCode)) {
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.wildcardQuery("regionCode", "*" + regionCode + "*"));
            boolMust.must(query);
        }
        //匹配appId
        if (!ObjectUtils.isEmpty(appId)) {
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.matchQuery("appId", appId));
            boolMust.must(query);
        }

        countRequest.query(boolMust);
        try {
            CountResponse countResponse = restHighLevelClient.count(countRequest, RequestOptions.DEFAULT);
            return countResponse.getCount();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private String getLicenseEfficiencyByRegion(String orgCode) {
        List<KeyValueDto> keyValueDtos = statisticsMapper.queryLicenseEfficiencyOfRegion(orgCode);
        int totalUnitNumber = keyValueDtos.stream().mapToInt(KeyValueDto::getIValue).sum();
        int okUnitNumberNumber = keyValueDtos.stream().filter(k -> k.getStrKey().equals(LICENSE_IS_OK)).mapToInt(KeyValueDto::getIValue).sum();
        if (totalUnitNumber == 0) {
            return NO_DATA_STR;
        }
        BigDecimal bigTotalUnitNumber = new BigDecimal(String.valueOf(totalUnitNumber));
        BigDecimal bigOkUnitNumberNumber = new BigDecimal(String.valueOf(okUnitNumberNumber));
        BigDecimal result = bigOkUnitNumberNumber.divide(bigTotalUnitNumber, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP);
        return result.toPlainString();
    }

    private Set<Map<String, String>> getLegendForCyArea() {
        Set<Map<String, String>> legendData = new HashSet<>();
        for (int i = 0; i < 8; i++) {
            Map<String, String> map = new HashMap<>();
            if (i == 0) {
                map.put("dataKey", "xuke");
                map.put("value", "许可有效率");
            } else if (i == 1) {
                map.put("dataKey", "shiyongdengji");
                map.put("value", "使用登记办理率");
            } else if (i == 2) {
                map.put("dataKey", "jianyanchaoqi");
                map.put("value", "检验超期率");
            } else if (i == 3) {
                map.put("dataKey", "jianyanhege");
                map.put("value", "检验合格率");
            } else if (i == 4) {
                map.put("dataKey", "czjc");
                map.put("value", "充装检查");
            } else if (i == 5) {
                map.put("dataKey", "czjchege");
                map.put("value", "充装检查合格率");
            } else if (i == 6) {
                map.put("dataKey", "ryhg");
                map.put("value", "人员合规率（资质有效期统计）");
            } else if (i == 7) {
                map.put("dataKey", "sjhg");
                map.put("value", "数据合规率");
            }
            legendData.add(map);
        }
        return legendData;
    }
    public String castScore2Percent(String score) {
        BigDecimal big = new BigDecimal(score);
        BigDecimal percent = big.divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
        return percent.toPlainString();
    }
}
