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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.dao.mapper.DataDictionaryMapper;
import com.yeejoin.amos.boot.biz.common.dto.CountDto;
import com.yeejoin.amos.boot.biz.common.dto.KeyValueDto;
import com.yeejoin.amos.boot.biz.common.entity.DataDictionary;
import com.yeejoin.amos.boot.module.common.api.dto.DPFilterParamDto;
import com.yeejoin.amos.boot.module.common.api.dto.DPFilterParamForDetailDto;
import com.yeejoin.amos.boot.module.common.api.dto.LegendDataDto;
import com.yeejoin.amos.boot.module.common.api.enums.IssueMainBodyEnum;
import com.yeejoin.amos.boot.module.common.api.enums.IssueProblemLevelEnum;
import com.yeejoin.amos.boot.module.common.api.enums.IssueTypeEnum;
import com.yeejoin.amos.boot.module.common.api.enums.StatisticalAnalysisEnum;
import com.yeejoin.amos.boot.module.common.biz.service.impl.TZSCommonServiceImpl;
import com.yeejoin.amos.boot.module.jg.api.enums.DPMapStatisticsItemEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.SafetyProblemStatusEnum;
import com.yeejoin.amos.boot.module.statistics.api.dto.EquipQuestionNumCountDto;
import com.yeejoin.amos.boot.module.statistics.api.dto.SafetyProblemTracingDto;
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.ymt.api.enums.EquipmentClassifityEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.TzBaseEnterpriseInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.TzsUserInfoMapper;
import com.yeejoin.amos.feign.systemctl.model.RegionModel;
import org.apache.commons.lang3.StringUtils;
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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 气瓶区域统计表服务实现类
 *
 * @author system_generator
 * @date 2022-03-08
 */
@Service
public class AQZSDPStatisticsServiceImpl {

    private final static String LICENSE_IS_OK = "正常";

    private final static String NO_DATA_STR = "--";

    /**
     * 单位类型-使用单位
     */
    private final static String COMPANY_TYPE_USE = "使用单位";

    /**
     * 单位类型-安装改造维修单位
     */
    private final static String COMPANY_TYPE_MAINTENANCE = "安装改造维修单位";

    /**
     * 单位类型-制造单位
     */
    private final static String COMPANY_TYPE_MANUFACTURE = "制造单位";

    /**
     * 单位类型-充装单位
     */
    private final static String COMPANY_TYPE_FILLING = "充装单位";


    private RestHighLevelClient restHighLevelClient;


    private AQZSDPStatisticsMapper statisticsMapper;


    private TzBaseEnterpriseInfoMapper enterpriseInfoMapper;


    private TzsUserInfoMapper userInfoMapper;

    private CylinderStatisticsMapper cylinderStatisticsMapper;


    private StCommonServiceImpl stCommonService;

    private TZSCommonServiceImpl tstCommonService;

    private JGDPStatisticsServiceImpl jgDPStatisticsService;

    private DataDictionaryMapper dataDictionaryMapper;

    @Autowired
    private ComprehensiveStatisticalAnalysisServiceImpl statisticalAnalysisService;


    public AQZSDPStatisticsServiceImpl(RestHighLevelClient restHighLevelClient,
                                       AQZSDPStatisticsMapper statisticsMapper,
                                       TzBaseEnterpriseInfoMapper enterpriseInfoMapper,
                                       TzsUserInfoMapper userInfoMapper,
                                       CylinderStatisticsMapper cylinderStatisticsMapper,
                                       StCommonServiceImpl stCommonService,
                                       DataDictionaryMapper dataDictionaryMapper,
                                       JGDPStatisticsServiceImpl jgDPStatisticsService,
                                       TZSCommonServiceImpl tstCommonService) {
        this.restHighLevelClient = restHighLevelClient;
        this.statisticsMapper = statisticsMapper;
        this.enterpriseInfoMapper = enterpriseInfoMapper;
        this.userInfoMapper = userInfoMapper;
        this.cylinderStatisticsMapper = cylinderStatisticsMapper;
        this.stCommonService = stCommonService;
        this.dataDictionaryMapper = dataDictionaryMapper;
        this.jgDPStatisticsService = jgDPStatisticsService;
        this.tstCommonService = tstCommonService;
    }


    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 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);
        }
    }

    public Map<String, Object> getChildEarlyWarning(DPFilterParamDto dpFilterParamDto) {
        List<RegionModel> regionModels = stCommonService.setRegionIfRootParentAndNoAccessIf3Level(dpFilterParamDto.getCityCode());
        Map<String, SecurityIndexCountItemDto> regionCodeSecurityIndexMap = getSecurityIndexCountItemDtoMap(regionModels);
        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<>();
        //TODO 多线程处理后，regionCodeSecurityIndexMap顺序与regionModels的顺序不一致，需让数据和x轴的顺序保存一致
        List<String> xdata = stCommonService.buildXData(regionModels);
        regionModels.forEach(r -> {
            SecurityIndexCountItemDto countItemDto = regionCodeSecurityIndexMap.get(r.getRegionCode().toString());
            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()));
        });
        Map<String, Object> result = new HashMap<>();
        result.put("xdata", xdata);
        result.put("legendData", legendData);
        result.put("xuke", xuke);
        result.put("shiyongdengji", shiyongdengji);
        result.put("jianyanchaoqi", jianyanchaoqi);
        result.put("jianyanhege", jianyanhege);
        result.put("czjc", czjc);
        result.put("czjchege", czjchege);
        result.put("ryhg", ryhg);
        result.put("sjhg", sjhg);
        return result;
    }

    public String castScore2Percent(String score) {
        BigDecimal big = new BigDecimal(score);
        BigDecimal percent = big.divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
        return percent.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 Map<String, Object> getSecurityIndex(DPFilterParamDto dpFilterParamDto) {
        List<RegionModel> regionModels = stCommonService.setRegionIfRootParentAndNoAccessIf3Level(dpFilterParamDto.getCityCode());
        Map<String, SecurityIndexCountItemDto> regionCodeSecurityIndexMap = getSecurityIndexCountItemDtoMap(regionModels);
        List<Map<String, String>> data = new ArrayList<>();
        List<Map<String, String>> finalData = data;
        this.getCitySecurityIndex(finalData, regionCodeSecurityIndexMap);
        data = finalData.stream()
                .filter(map -> map.containsKey("value"))
                .sorted(Comparator.comparingDouble(map -> {
                    // 检查并解析值，如果失败则返回Double.MIN_VALUE（或根据需要处理）
                    try {
                        return Double.parseDouble(map.get("value"));
                    } catch (NumberFormatException e) {
                        // 处理无法解析为double的情况，这里返回Double.MIN_VALUE表示最小
                        // 或者可以抛出自定义异常，记录日志等
                        return Double.MIN_VALUE;
                    }
                }))
                .collect(Collectors.toList());
        Map<String, Object> result = new HashMap<>();
        List<String> name = data.stream().map(map -> map.get("name")).collect(Collectors.toList());
        Collections.reverse(name);
        result.put("xdata", name);
        List<String> value = data.stream().map(map -> map.get("value")).collect(Collectors.toList());
        Collections.reverse(value);
        result.put("ydata", value);
        return result;
    }

    public void getCitySecurityIndex(List<Map<String, String>> finalData, Map<String, SecurityIndexCountItemDto> regionCodeSecurityIndexMap) {
        /**
         * 计算权重，总分100分：
         * 检验超期率、检验合格率、充装检查率、充装检查合格率，占15%
         * 许可有效率、使用登记办理率、人员合规率（资质有效期统计）、数据合规率，占10%
         */
        double weightTen = 0.10;
        double weightFifteen = 0.15;
        regionCodeSecurityIndexMap.forEach((k, v) -> {
            Map<String, String> item = new HashMap<>();
            item.put("name", v.getRegionName());
            item.put("regionCode", v.getRegionCode());
            // 许可有效率的加权值
            double xukeWeighted = Double.parseDouble(v.getXuke()) * weightTen;
            // 使用登记办理率的加权值
            double sydjWeighted = Double.parseDouble(v.getShiyongdengji()) * weightTen;
            // 人员合规率（资质有效期统计）的加权值
            double ryhgWeighted = Double.parseDouble(v.getRyhg()) * weightTen;
            // 数据合规率的加权值
            double sjhgWeighted = Double.parseDouble(v.getSjhg()) * weightTen;
            // 检验超期率的加权值
            double jianyanchaoqiWeighted = Double.parseDouble(v.getJianyanchaoqi()) * weightFifteen;
            // 检验合格率的加权值
            double jianyanhegeWeighted = Double.parseDouble(v.getJianyanhege()) * weightFifteen;
            // 充装检查率的加权值
            double czjcWeighted = Double.parseDouble(v.getCzjc()) * weightFifteen;
            // 充装检查合格率的加权值
            double czjchegeWeighted = Double.parseDouble(v.getCzjchege()) * weightFifteen;
            // 计算总指数
            double totalIndex = xukeWeighted + sydjWeighted + ryhgWeighted + sjhgWeighted + jianyanchaoqiWeighted + jianyanhegeWeighted + czjcWeighted + czjchegeWeighted;
            item.put("value", String.format("%.2f", totalIndex));
            finalData.add(item);
        });
    }


    public Map<String, SecurityIndexCountItemDto> getSecurityIndexCountItemDtoMap(List<RegionModel> regionModels) {
        // 多线程处理后，顺序与regionModels的顺序不一致，故生成list
        List<SecurityIndexCountItemDto> countItemDtoList = getSecurityIndexCountDtoList(regionModels);
        return countItemDtoList.stream().collect(Collectors.toMap(SecurityIndexCountItemDto::getRegionCode, Function.identity(), (k1, k2) -> k2));
    }

    private List<SecurityIndexCountItemDto> getSecurityIndexCountDtoList(List<RegionModel> regionModels) {
        return regionModels.parallelStream().map(r -> {
            String orgCode = stCommonService.getAndSetOrgCode(r.getRegionCode().toString());
            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());
    }

    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");
    }

    public Map<String, Object> mainBodyCount(DPFilterParamDto dpFilterParamDto) {
        this.setDefaultFilter(dpFilterParamDto);
        List<Object> problemCount = new ArrayList<>();
        List<Object> problemRate = new ArrayList<>();
        Map<String, Object> resultMap = new HashMap<>();
        // 1.图列设置
        List<IssueMainBodyEnum> mainBodyEnums = Arrays.asList(IssueMainBodyEnum.values());
        resultMap.put("legendData", buildMainBodyLegendData());
        // 2.x轴设置
        resultMap.put("xdata", mainBodyEnums.stream().map(IssueMainBodyEnum::getName).collect(Collectors.toList()));
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if (orgCode == null) {
            return resultMap;
        }
        // 3.y轴数据设置
        // 按照问题状态、问题类型分组统计问题数量
        List<CountDto> countDtos = statisticsMapper.selectByOrgAndMainBody(orgCode, dpFilterParamDto, null);
        mainBodyEnums.forEach(e -> {
            Long allProblemNum = countDtos.stream().filter(c -> c.getKeyStr().equals(e.getCode())).mapToLong(CountDto::getLongValue).sum();
            long handledProblemNum = countDtos.stream().filter(c -> c.getKeyStr().equals(e.getCode()) && c.getLabel().equals(SafetyProblemStatusEnum.HANDLED.getCode())).mapToLong(CountDto::getLongValue).sum();
            problemCount.add(allProblemNum);
            problemRate.add(calPercent(allProblemNum, handledProblemNum));
        });
        resultMap.put("problemCount", problemCount);
        resultMap.put("problemRate", problemRate);
        return resultMap;
    }

    private List<Object> buildMainBodyLegendData() {
        List<Object> legendDataList = new ArrayList<>();
        for (int i = 0; i < 2; i++) {
            Map<String, Object> map = new HashMap<>();
            if (0 == i) {
                map.put("dataKey", "problemCount");
                map.put("value", "问题数量");
            } else {
                map.put("dataKey", "problemRate");
                map.put("value", "问题闭环率");
            }
            legendDataList.add(map);
        }
        return legendDataList;
    }


    public Map<String, Object> equipmentCount(DPFilterParamDto dpFilterParamDto) {
        this.setDefaultFilter(dpFilterParamDto);
        Map<String, Object> resultMap = new HashMap<>();
        Map<String, Object> dataMap = new HashMap<>();
        List<Object> xdata = new ArrayList<>();
        List<Object> ydata = new ArrayList<>();
        // 不需要统计资质超期和许可超期数据，2024-11-12日需求修改
        List<String> enumNameList = IssueTypeEnum.getEnumNameListByMainBody("3").stream()
                .filter(item -> !(item.contains("资质超期") || item.contains("许可超期")))
                .collect(Collectors.toList());
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if (orgCode != null) {
            List<CountDto> countDtos = statisticsMapper.selectByOrgAndProblemType(orgCode, enumNameList, dpFilterParamDto, IssueMainBodyEnum.EQUIPMENT.getCode(), null);
            countDtos.forEach(t -> dataMap.put(t.getKeyStr(), t.getLongValue()));
        }
        for (int i = 0; i < enumNameList.size(); i++) {
            xdata.add(enumNameList.get(i));
            ydata.add(dataMap.getOrDefault(enumNameList.get(i), "0"));
        }
        resultMap.put("xdata", xdata);
        resultMap.put("ydata", ydata);
        return resultMap;
    }

    public List<Map<String, Object>> companyCount(DPFilterParamDto dpFilterParamDto) {
        this.setDefaultFilter(dpFilterParamDto);
        List<Map<String, Object>> resultList = new ArrayList<>();
        Map<String, Object> dataMap = new HashMap<>();
        List<String> enumNameList = IssueTypeEnum.getEnumNameListByMainBody("2");
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if (orgCode != null) {
            List<CountDto> countDtos = statisticsMapper.selectByOrgAndProblemType(orgCode, enumNameList, dpFilterParamDto, IssueMainBodyEnum.COMPANY.getCode(), null);
            countDtos.forEach(t -> dataMap.put(t.getKeyStr(), t.getLongValue()));
            // 企业维保合同过期单独查询（企业下有设备维保超期就算）
            CountDto wbCountDto = statisticsMapper.selectByOrgAndProblemTypeForWb(orgCode, IssueTypeEnum.MAINTENANCE_OVERDUE_EQUMENT.getCode(), dpFilterParamDto, IssueMainBodyEnum.EQUIPMENT.getCode(), "3000");
            dataMap.put(IssueTypeEnum.MAINTENANCE_RECORD_OVERDUE_COMPANY.getName(), wbCountDto == null ? 0 : wbCountDto.getLongValue());
        }
        for (int i = 0; i < enumNameList.size(); i++) {
            Map<String, Object> map = new HashMap<>();
            switch (enumNameList.get(i)) {
                case "许可临期":
                    map.put("key", "licenseExpirationDateNumber");
                    map.put("label", "许可临期数");
                    map.put("value", dataMap.getOrDefault(enumNameList.get(i), "0"));
                    break;
                case "许可超期":
                    map.put("key", "licenseOverdueNumber");
                    map.put("label", "许可超期数");
                    map.put("value", dataMap.getOrDefault(enumNameList.get(i), "0"));
                    break;
                case "维保备案超期":
                    map.put("key", "maintenanceFilingOverdueNumber");
                    map.put("label", "维保合同备案超期数（仅电梯）");
                    map.put("value", dataMap.getOrDefault(enumNameList.get(i), "0"));
                    break;
                default:
                    break;
            }
            resultList.add(map);
        }
        return resultList;
    }

    public Map<String, Object> personCount(DPFilterParamDto dpFilterParamDto) {
        this.setDefaultFilter(dpFilterParamDto);
        Map<String, Object> resultMap = new HashMap<>();
        Map<String, Object> dataMap = new HashMap<>();
        List<Object> xdata = new ArrayList<>();
        List<Object> ydata = new ArrayList<>();
        List<String> enumNameList = IssueTypeEnum.getEnumNameListByMainBody("1");
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if (orgCode != null) {
            BoolQueryBuilder overdueQuery = new BoolQueryBuilder();
            overdueQuery.must(QueryBuilders.prefixQuery("superviseOrgCode", orgCode));
            tstCommonService.buildExpiryDateQueryBuilder(overdueQuery, "overdue", "licenses", "licenses.expiryDate");
            Long overNumber = stCommonService.getNestedQueryStatisticCount(overdueQuery, StatisticalAnalysisEnum.person.getKey(), "licenses", "expiryDate");
            BoolQueryBuilder nearQuery = new BoolQueryBuilder();
            nearQuery.must(QueryBuilders.prefixQuery("superviseOrgCode", orgCode));
            tstCommonService.buildExpiryDateQueryBuilder(nearQuery, "near", "licenses", "licenses.expiryDate");
            Long nearNumber = stCommonService.getNestedQueryStatisticCount(nearQuery, StatisticalAnalysisEnum.person.getKey(), "licenses", "expiryDate");
            dataMap.put(IssueTypeEnum.LICENSE_OVERDUE_PERSON.getName(), overNumber);
            dataMap.put(IssueTypeEnum.LICENSE_EXPIRY_PERSON.getName(), nearNumber);
        }
        for (int i = 0; i < enumNameList.size(); i++) {
            xdata.add(enumNameList.get(i));
            ydata.add(dataMap.getOrDefault(enumNameList.get(i), "0"));
        }
        resultMap.put("xdata", xdata);
        resultMap.put("ydata", ydata);
        return resultMap;
    }

    public Map<String, Object> cylinderCount(DPFilterParamDto dpFilterParamDto) {
        this.setDefaultFilter(dpFilterParamDto);
        Map<String, Object> resultMap = new HashMap<>();
        Map<String, Object> dataMap = new HashMap<>();
        List<Object> xdata = new ArrayList<>();
        List<Object> ydata = new ArrayList<>();
        List<String> enumNameList = IssueTypeEnum.getEnumNameListByMainBody("4");
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if (orgCode != null) {
            List<CountDto> countDtos = statisticsMapper.selectByOrgAndProblemTypeForCy(orgCode, dpFilterParamDto);
            countDtos.forEach(t -> dataMap.put(t.getKeyStr(), t.getLongValue()));
        }
        for (int i = 0; i < enumNameList.size(); i++) {
            xdata.add(enumNameList.get(i));
            ydata.add(dataMap.getOrDefault(enumNameList.get(i), "0"));
        }
        resultMap.put("xdata", xdata);
        resultMap.put("ydata", ydata);
        return resultMap;
    }

    public Map<String, Object> issueCountByMonth(DPFilterParamDto dpFilterParamDto) {
        Map<String, Object> resultMap = new HashMap<>();
        List<Object> legendData = new ArrayList<>();
        for (int i = 0; i < 2; i++) {
            Map<String, Object> map = new HashMap<>();
            if (i == 0) {
                map.put("key", "problemCount");
                map.put("value", "问题数量");
            } else {
                map.put("key", "processedRate");
                map.put("value", "已处理");
            }
            legendData.add(map);
        }
        resultMap.put("legendData", legendData);
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        Map<String, Object> allIssueMap = new HashMap<>();
        Map<String, Object> endIssueMap = new HashMap<>();
        if (orgCode != null) {
            int year = LocalDate.now().getYear();
            List<Map<String, Object>> allIssue = statisticsMapper.getIssueCountByMonth(orgCode, String.valueOf(year), null);
            List<Map<String, Object>> endIssue = statisticsMapper.getIssueCountByMonth(orgCode, String.valueOf(year), "1");
            allIssue.forEach(t -> {
                allIssueMap.put(t.get("time").toString(), t.get("count"));
            });
            endIssue.forEach(t -> {
                endIssueMap.put(t.get("time").toString(), t.get("count"));
            });
        }
        List<Object> problemCount = new ArrayList<>();
        List<Object> processedRate = new ArrayList<>();
        List<Object> xdata = new ArrayList<>();
        for (int i = 0; i < 12; i++) {
            String time = LocalDate.now().minusMonths(i).format(DateTimeFormatter.ofPattern("yyyy-MM"));
            xdata.add(time);
            if (allIssueMap.get(time) == null) {
                problemCount.add("0");
                processedRate.add("0");
            } else {
                problemCount.add(allIssueMap.get(time));
                if (endIssueMap.get(time) == null) {
                    processedRate.add("0");
                } else {
                    processedRate.add(new DecimalFormat("0.00").format(Double.parseDouble(endIssueMap.get(time).toString()) / Double.parseDouble(allIssueMap.get(time).toString())));
                }
            }
        }
        Collections.reverse(xdata);
        Collections.reverse(problemCount);
        Collections.reverse(processedRate);
        resultMap.put("xdata", xdata);
        resultMap.put("problemCount", problemCount);
        resultMap.put("processedRate", processedRate);
        return resultMap;
    }

    public Map<String, Object> issueCountByDay(String cityCode) {
        Map<String, Object> resultMap = new HashMap<>();
        List<Object> legendData = new ArrayList<>();
        for (int i = 0; i < 2; i++) {
            Map<String, Object> map = new HashMap<>();
            if (i == 0) {
                map.put("dataKey", "problemCount");
                map.put("value", "问题数量");
            } else {
                map.put("dataKey", "processedRate");
                map.put("value", "已处理");
            }
            legendData.add(map);
        }
        resultMap.put("legendData", legendData);
        String orgCode = stCommonService.getAndSetOrgCode(cityCode);
        String year = LocalDate.now().minusDays(29).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        List<Map<String, Object>> allIssue = statisticsMapper.getIssueCountByDate(orgCode, year, null);
        List<Map<String, Object>> endIssue = statisticsMapper.getIssueCountByDate(orgCode, year, "1");
        Map<String, Object> allIssueMap = new HashMap<>();
        Map<String, Object> endIssueMap = new HashMap<>();
        allIssue.stream().forEach(t -> {
            allIssueMap.put(t.get("time").toString(), t.get("count"));
        });
        endIssue.stream().forEach(t -> {
            endIssueMap.put(t.get("time").toString(), t.get("count"));
        });
        List<Object> problemCount = new ArrayList<>();
        List<Object> processedRate = new ArrayList<>();
        List<Object> xdata = new ArrayList<>();
        for (int i = 0; i < 29; i++) {
            String time = LocalDate.now().minusDays(i).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            xdata.add(time);
            if (allIssueMap.get(time) == null) {
                problemCount.add("0");
                processedRate.add("0");
            } else {
                problemCount.add(allIssueMap.get(time));
                if (endIssueMap.get(time) == null) {
                    processedRate.add("0");
                } else {
                    processedRate.add(new DecimalFormat("0.00").format(Double.parseDouble(endIssueMap.get(time).toString()) / Double.parseDouble(allIssueMap.get(time).toString())));
                }
            }
        }
        Collections.reverse(xdata);
        Collections.reverse(problemCount);
        Collections.reverse(processedRate);
        resultMap.put("xdata", xdata);
        resultMap.put("problemCount", problemCount);
        resultMap.put("processedRate", processedRate);
        return resultMap;
    }

    public Map<String, Object> issueCountByCityCode(String cityCode) {
        String orgCode = stCommonService.getAndSetOrgCode(cityCode);
        String now = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"));
        int count = statisticsMapper.countByOrgCode(orgCode, now, null);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("issueCount", count);
        return resultMap;
    }


    public List<Map<String, Object>> issueChildrenCityCount(String cityCode) {
        List<RegionModel> regionModels = stCommonService.setRegionIfRootParent(cityCode);
        List<Integer> regionCodeList = regionModels.stream().map(RegionModel::getRegionCode).collect(Collectors.toList());
        List<Map<String, String>> orgCodeAndCompanyCodesByCompanyCodes = statisticsMapper.getOrgCodeAndCompanyCodesByCompanyCodes(regionCodeList);
        List<String> orgCodes = orgCodeAndCompanyCodesByCompanyCodes.stream().map(m -> m.get("orgCode")).collect(Collectors.toList());
        String now = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"));
        Map<String, String> orgCodeAndCompanyCodesMap = new HashMap<>();
        orgCodeAndCompanyCodesByCompanyCodes.forEach(t -> {
            orgCodeAndCompanyCodesMap.put(t.get("companyCode"), t.get("orgCode"));
        });
        List<Map<String, Object>> list = statisticsMapper.countByOrgCodes(orgCodes, now);
        Map<String, Object> dataMap = new HashMap<>();
        list.forEach(t -> {
            dataMap.put(t.get("orgCode").toString(), t.get("count"));
        });

        List<Map<String, Object>> resultList = new ArrayList<>();
        for (RegionModel regionModel : regionModels) {
            Map<String, Object> map = new HashMap<>();
            AtomicInteger count = new AtomicInteger();
            map.put("regionCode", regionModel.getRegionCode());
            map.put("regionName", regionModel.getRegionName());
            if (StringUtils.isNotBlank(orgCodeAndCompanyCodesMap.get(regionModel.getRegionCode() + ""))) {
                dataMap.forEach((k, v) -> {
                    if (k.startsWith(orgCodeAndCompanyCodesMap.get(regionModel.getRegionCode() + ""))) {
                        if (null != v) {
                            count.addAndGet(Integer.valueOf(v + ""));
                        }
                    }
                });
            }
            map.put("issueCount", count);
            resultList.add(map);
        }

        return resultList;
    }

    public List<Map<String, Object>> issueMonthList(String cityCode) {
        String orgCode = stCommonService.getAndSetOrgCode(cityCode);
        if (orgCode == null) {
            return new ArrayList<>(0);
        }
        String time = LocalDate.now().minusDays(29).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        return statisticsMapper.issueMonthList(orgCode, time);
    }

    public Map<String, Object> issueProblemLevelCount(DPFilterParamDto dpFilterParamDto) {
        Map<String, Object> resultMap = new HashMap<>();
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        String time = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy"));
        Map<String, Long> problemLevelNumMap = new LinkedHashMap<>();
        if (orgCode != null) {
            List<CountDto> list = statisticsMapper.issueProblemLevelCount(orgCode, time);
            problemLevelNumMap = list.stream().collect(Collectors.toMap(CountDto::getKeyStr, CountDto::getLongValue));
        }
        List<Object> xdata = new ArrayList<>();
        List<Object> ydata = new ArrayList<>();
        Map<String, Long> finalProblemLevelNumMap = problemLevelNumMap;
        Arrays.stream(IssueProblemLevelEnum.values()).forEach(e -> {
            xdata.add(e.getName());
            ydata.add(finalProblemLevelNumMap.getOrDefault(e.getCode(), 0L));
        });
        resultMap.put("xdata", xdata);
        resultMap.put("ydata", ydata);
        return resultMap;
    }

    public List<Map<String, Object>> issueCompanyTop(DPFilterParamDto dpFilterParamDto) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if (orgCode == null) {
            return new ArrayList<>();
        }
        String time = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy"));
        List<Map<String, Object>> list = statisticsMapper.issueCompanyTop(orgCode, time);
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> map = new HashMap<>();
            map.put("sequenceNbr", (i + 1) + "");
            map.put("region", list.get(i).get("governingBody"));
            map.put("company", list.get(i).get("principalUnit"));
            map.put("count", list.get(i).get("count"));
            resultList.add(map);
        }
        return resultList;
    }

    public List<Map<String, Object>> issueChildrenCityCountTop(DPFilterParamDto dpFilterParamDto) {
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if (orgCode == null) {
            return new ArrayList<>();
        }
        List<RegionModel> regionModels = stCommonService.setRegionIfRootParentAndNoAccessIf3Level(dpFilterParamDto.getCityCode());
        List<Integer> regionCodeList = regionModels.stream().map(RegionModel::getRegionCode).collect(Collectors.toList());
        List<Map<String, String>> orgCodeAndCompanyCodesByCompanyCodes = statisticsMapper.getOrgCodeAndCompanyCodesByCompanyCodes(regionCodeList);
        List<String> orgCodes = orgCodeAndCompanyCodesByCompanyCodes.stream().map(m -> m.get("orgCode")).collect(Collectors.toList());
        String now = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy"));
        Map<String, String> orgCodeAndCompanyCodesMap = new HashMap<>();
        orgCodeAndCompanyCodesByCompanyCodes.forEach(t -> {
            orgCodeAndCompanyCodesMap.put(t.get("companyCode"), t.get("orgCode"));
        });
        List<Map<String, Object>> allIssueCount = statisticsMapper.issueChildrenCityCountTop(orgCodes, now, null);
        List<Map<String, Object>> endIssueCount = statisticsMapper.issueChildrenCityCountTop(orgCodes, now, "1");
        Map<String, Object> allIssuedataMap = new HashMap<>();
        Map<String, Object> endIssuedataMap = new HashMap<>();
        allIssueCount.forEach(t -> {
            allIssuedataMap.put(t.get("orgCode").toString(), t.get("count"));
        });

        endIssueCount.forEach(t -> {
            endIssuedataMap.put(t.get("orgCode").toString(), t.get("count"));
        });

        List<Map<String, Object>> resultList = new ArrayList<>();
        for (RegionModel regionModel : regionModels) {
            Map<String, Object> map = new HashMap<>();
            AtomicInteger allCount = new AtomicInteger();
            AtomicInteger endCount = new AtomicInteger();
            map.put("region", regionModel.getRegionName());
            if (StringUtils.isNotBlank(orgCodeAndCompanyCodesMap.get(regionModel.getRegionCode() + ""))) {
                allIssuedataMap.forEach((k, v) -> {
                    if (k.startsWith(orgCodeAndCompanyCodesMap.get(regionModel.getRegionCode() + ""))) {
                        if (null != v) {
                            allCount.addAndGet(Integer.parseInt(v + ""));
                        }
                    }
                });
                endIssuedataMap.forEach((k, v) -> {
                    if (k.startsWith(orgCodeAndCompanyCodesMap.get(regionModel.getRegionCode() + ""))) {
                        if (null != v) {
                            endCount.addAndGet(Integer.parseInt(v + ""));
                        }
                    }
                });
            }
            if (allCount.get() != 0) {
                map.put("rate", new DecimalFormat("0.00").format(Double.parseDouble(endCount + "") / (Double.parseDouble(allCount.get() + ""))));
            } else {
                map.put("rate", "0.00");
            }
            resultList.add(map);
        }
        resultList.sort(Comparator.comparingDouble(m -> Double.parseDouble(m.get("rate").toString())));
        Collections.reverse(resultList);
        for (int i = 0; i < resultList.size(); i++) {
            resultList.get(i).put("sequenceNbr", (i + 1) + "");
        }
        return resultList;
    }

    public List<Map<String, Object>> issueCountTopByProblemType(String cityCode) {
        String orgCode = stCommonService.getAndSetOrgCode(cityCode);
        List<Map<String, Object>> allList = new ArrayList<>();
        Map<String, Object> endIssueDataMap = new HashMap<>();
        if (orgCode != null) {
            allList = statisticsMapper.issueCountTopByProblemType(orgCode, null);
            List<Map<String, Object>> endList = statisticsMapper.issueCountTopByProblemType(orgCode, "1");
            endList.forEach(t -> {
                endIssueDataMap.put(t.get("problemTypeCode").toString(), t.get("count"));
            });
        }
        List<Map<String, Object>> resultList = new ArrayList<>();
        for (Map<String, Object> stringObjectMap : allList) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", IssueTypeEnum.getNameByCode(stringObjectMap.get("problemTypeCode").toString()));
            map.put("count", stringObjectMap.get("count"));
            if (null != endIssueDataMap.get(stringObjectMap.get("problemTypeCode").toString())) {
                map.put("rate", new DecimalFormat("0.00").format(Double.parseDouble(endIssueDataMap.get(stringObjectMap.get("problemTypeCode").toString()) + "") / (Double.parseDouble(stringObjectMap.get("count") + ""))));
            } else {
                map.put("rate", "0");
            }
            resultList.add(map);
        }
        return resultList;
    }

    public List<Map<String, Object>> getEquipQuestionList(DPFilterParamDto dpFilterParamDto) {
        this.setDefaultFilter(dpFilterParamDto);
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if (StringUtils.isEmpty(orgCode)) {
            return new ArrayList<>();
        }
        List<EquipQuestionNumCountDto> equipQuestionNumCountDtos = statisticsMapper.queryEquipQuestionList(orgCode, dpFilterParamDto);
        return this.calPercentFinishedAndCast2Map(equipQuestionNumCountDtos);
    }

    private List<Map<String, Object>> calPercentFinishedAndCast2Map(List<EquipQuestionNumCountDto> equipQuestionNumCountDtos) {
        return equipQuestionNumCountDtos.stream().map(e -> {
            Map<String, Object> item = new HashMap<>();
            // 设备id
            item.put("key", e.getSourceId());
            // 区域名称
            item.put("regionName", e.getCityName());
            // 设备种类
            item.put("deviceCategoryName", EquipmentClassifityEnum.getNameByCode(e.getEquList()));
            // 监管码/使用登记证编号
            item.put("code", this.buildCodeWithSplit(e.getSupervisoryCode(), e.getUseOrgCode()));
            // 使用单位
            item.put("useUnitName", e.getUseUnitName());
            // 问题次数
            item.put("issuesNumber", e.getTotal());
            // 闭环率
            item.put("closedLoopRate", this.calClosedLoopRate(e.getTotal(), e.getFinished()));
            return item;
        }).collect(Collectors.toList());
    }

    private String calClosedLoopRate(Long total, Long finished) {
        if (total == 0) {
            return "0";
        }
        BigDecimal totalBig = new BigDecimal(total.toString());
        BigDecimal finishedBig = new BigDecimal(finished.toString());
        BigDecimal result = finishedBig.divide(totalBig, 2, RoundingMode.HALF_UP);
        NumberFormat nt = NumberFormat.getPercentInstance();
        nt.setMinimumFractionDigits(0);
        return nt.format(result);
    }

    private String buildCodeWithSplit(String supervisoryCode, String useOrgCode) {
        if (StringUtils.isNotEmpty(supervisoryCode) && StringUtils.isNotEmpty(useOrgCode)) {
            return String.format("%s/%s", supervisoryCode, useOrgCode);
        }
        if (StringUtils.isNotEmpty(supervisoryCode)) {
            return supervisoryCode;
        }
        if (StringUtils.isNotEmpty(useOrgCode)) {
            return useOrgCode;
        }
        return "";
    }

    private void setDefaultFilter(DPFilterParamDto dpFilterParamDto) {
        if (StringUtils.isEmpty(dpFilterParamDto.getBeginDate())) {
            dpFilterParamDto.setBeginDate(cn.hutool.core.date.DateUtil.offsetDay(new Date(), -30).toDateStr());
        }
        if (StringUtils.isEmpty(dpFilterParamDto.getEndDate())) {
            dpFilterParamDto.setEndDate(cn.hutool.core.date.DateUtil.offsetDay(new Date(), -1).toDateStr());
        }
    }

    public Map<String, Object> getCenterMapCountDataForGlobal(DPFilterParamDto dpFilterParamDto) {
        Map<String, Object> result = new HashMap<>();
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if (StringUtils.isEmpty(orgCode)) {
            return new HashMap<>();
        }
        // 1.气瓶数量统计
        long cylinderNum = stCommonService.staticsCenterMapCountDataForCylinder(result, orgCode,true, false, false);
        //1.8大类设备数量统计,压力容器里包括气瓶所以需要特殊处理，在统计压力容器时去掉气瓶的数量
        stCommonService.staticsCenterMapCountDataForEquip(result, cylinderNum, orgCode,true,false, false);
        // 单独计算已纳管设备（台套）数量总数
        long hasSupervisoryCodeEquipCount = stCommonService.queryHasSupervisoryCodeEquipCount(orgCode, false);
        result.put("total", hasSupervisoryCodeEquipCount);
        //2.压力管道长度统计
//        stCommonService.staticsCenterMapCountDataForPipeline(result, orgCode,true, false);
        jgDPStatisticsService.staticsCenterMapCountPipLine(result, orgCode, true, false);
        //3.单位数量统计
        // 单位统计修改为查询es
//        this.staticsCenterMapCountDataForCompany(result, orgCode, dpFilterParamDto.getCityCode());
          this.staticsCenterMapCompanyCountToEs(result, orgCode);
         //4.人员数量统计
        // 人员统计改为查询es，修改之前查询的是作业人员的总数，修改为所有人员的总数
//        this.staticsCenterMapCountDataForPerson(result, dpFilterParamDto, orgCode);
        this.staticsCenterMapPersonCountToEs(result, orgCode);
        //5.问题数统计
        this.staticsCenterMapCountDataForIssue(result, orgCode);
        return result;
    }

    private void staticsCenterMapPersonCountToEs(Map<String, Object> result, String orgCode) {
        BoolQueryBuilder personBoolMust = QueryBuilders.boolQuery();
        personBoolMust.must(QueryBuilders.prefixQuery("superviseOrgCode", orgCode));
        Long personCount = statisticalAnalysisService.getStatisticCount(personBoolMust, StatisticalAnalysisEnum.person.getKey());
        result.put(DPMapStatisticsItemEnum.PERSON_TOTAL.getCode(), personCount);
    }

    private void staticsCenterMapCompanyCountToEs(Map<String, Object> result, String orgCode) {
        BoolQueryBuilder companyBoolMust = QueryBuilders.boolQuery();
        companyBoolMust.must(QueryBuilders.prefixQuery("superviseOrgCode.keyword", orgCode));
        Long companyCount = statisticalAnalysisService.getStatisticCount(companyBoolMust, StatisticalAnalysisEnum.company.getKey());
        result.put("companyCount", companyCount);
    }

    private void staticsCenterMapCountDataForIssue(Map<String, Object> result, String orgCode) {
        List<Map<String, Object>> list = statisticsMapper.selectByOrg(orgCode);
        Map<String, Object> dataMap = new HashMap<>();
        AtomicReference<Long> issueCount = new AtomicReference<>(0L);
        list.forEach(t -> {
            dataMap.put(t.get("sourceType").toString(), t.get("count"));
            issueCount.updateAndGet(v -> v + Long.parseLong(t.get("count").toString()));
        });
        result.put("issueCount", issueCount.get());
        result.put("deviceIssueCount", dataMap.getOrDefault(DPMapStatisticsItemEnum.EQU_ISSUES_COUNT.getCode(), 0L));
        result.put("companyIssueCount", dataMap.getOrDefault(DPMapStatisticsItemEnum.COMPANY_ISSUES_COUNT.getCode(), 0L));
        result.put("personIssueCount", dataMap.getOrDefault(DPMapStatisticsItemEnum.PERSON_ISSUES_COUNT.getCode(), 0L));

    }

    private void staticsCenterMapCountDataForCompany(Map<String, Object> result, String orgCode, String cityCode) {
        if (orgCode == null) {
            setDefaultCompanyCountData(result);
            return;
        }
        List<CountDto> countDtos = enterpriseInfoMapper.countByUnitTypeAndOrgCode(orgCode, cityCode, false);
        result.put(DPMapStatisticsItemEnum.USERS_UNITS.getCode(), countDtos.stream().filter(c -> c.getKeyStr().contains(COMPANY_TYPE_USE)).mapToInt(CountDto::getIntValue).sum());
        result.put(DPMapStatisticsItemEnum.CONSTRUCTION_UNITS.getCode(), countDtos.stream().filter(c -> c.getKeyStr().contains(COMPANY_TYPE_MAINTENANCE)).mapToInt(CountDto::getIntValue).sum());
        result.put(DPMapStatisticsItemEnum.MANUFACTURING_UNITS.getCode(), countDtos.stream().filter(c -> c.getKeyStr().contains(COMPANY_TYPE_MANUFACTURE)).mapToInt(CountDto::getIntValue).sum());
        result.put(DPMapStatisticsItemEnum.GAS_UNITS.getCode(), countDtos.stream().filter(c -> c.getKeyStr().contains(COMPANY_TYPE_FILLING)).mapToInt(CountDto::getIntValue).sum());
        result.put("companyCount", countDtos.stream().mapToInt(CountDto::getIntValue).sum());
    }

    private void setDefaultCompanyCountData(Map<String, Object> m) {
        m.put(DPMapStatisticsItemEnum.USERS_UNITS.getCode(), 0);
        m.put(DPMapStatisticsItemEnum.CONSTRUCTION_UNITS.getCode(), 0);
        m.put(DPMapStatisticsItemEnum.MANUFACTURING_UNITS.getCode(), 0);
        m.put(DPMapStatisticsItemEnum.GAS_UNITS.getCode(), 0);
    }

    private void staticsCenterMapCountDataForPerson(Map<String, Object> result, DPFilterParamDto dpFilterParamDto, String orgCode) {
        if (orgCode == null) {
            result.put(DPMapStatisticsItemEnum.OPERATORS.getCode(), 0);
            return;
        }
        Long num = userInfoMapper.countUserByPostAndAreaCode(orgCode, "6552", dpFilterParamDto.getCityCode());
        result.put(DPMapStatisticsItemEnum.OPERATORS.getCode(), num);
    }

    public List<Map<String, Object>> getCenterMapCountDataForOverview(DPFilterParamDto dpFilterParamDto) {
        List<RegionModel> regionModels = stCommonService.setRegionIfRootParent(dpFilterParamDto.getCityCode());
        List<Map<String, Object>> result = regionModels.parallelStream().map(r -> {
            DPFilterParamDto filterParamDto = new DPFilterParamDto();
            filterParamDto.setCityCode(r.getRegionCode().toString());
            Map<String, Object> itemResult = getCenterMapOverviewData(filterParamDto);
            itemResult.put("regionCode", r.getRegionCode());
            itemResult.put("regionName", r.getRegionName());
            return itemResult;
        }).collect(Collectors.toList());
        this.setCompanyDataBatch(result);
        return result;
    }

    private void setCompanyDataBatch(List<Map<String, Object>> result) {
        List<CountDto> countDtos = enterpriseInfoMapper.countByUnitTypeAndOrgCodeNoParam();
        result.forEach(m -> {
            String cityCode = m.get("regionCode").toString();
            String orgCode = stCommonService.getAndSetOrgCode(cityCode);
            if (orgCode != null) {
                m.put(DPMapStatisticsItemEnum.USERS_UNITS.getCode(), countDtos.stream().filter(c -> c.getKeyStr().contains(COMPANY_TYPE_USE) && c.getLabel().contains(orgCode)).mapToInt(CountDto::getIntValue).sum());
                m.put(DPMapStatisticsItemEnum.CONSTRUCTION_UNITS.getCode(), countDtos.stream().filter(c -> c.getKeyStr().contains(COMPANY_TYPE_MAINTENANCE) && c.getLabel().contains(orgCode)).mapToInt(CountDto::getIntValue).sum());
                m.put(DPMapStatisticsItemEnum.MANUFACTURING_UNITS.getCode(), countDtos.stream().filter(c -> c.getKeyStr().contains(COMPANY_TYPE_MANUFACTURE) && c.getLabel().contains(orgCode)).mapToInt(CountDto::getIntValue).sum());
                m.put(DPMapStatisticsItemEnum.GAS_UNITS.getCode(), countDtos.stream().filter(c -> c.getKeyStr().contains(COMPANY_TYPE_FILLING) && c.getLabel().contains(orgCode)).mapToInt(CountDto::getIntValue).sum());
            } else {
                setDefaultCompanyCountData(m);
            }
        });
    }

    private Map<String, Object> getCenterMapOverviewData(DPFilterParamDto dpFilterParamDto) {
        Map<String, Object> result = new HashMap<>();
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if (StringUtils.isEmpty(orgCode)) {
            return new HashMap<>();
        }
        // 0. 气瓶数量统计
        long cylinderNum = stCommonService.staticsCenterMapCountDataForCylinder(result, orgCode,true, true, false);
        // 1. 8大类设备数量统计,压力容器里包括气瓶所以需要特殊处理，在统计压力容器时去掉气瓶的数量
        stCommonService.staticsCenterMapCountDataForEquip(result, cylinderNum, orgCode,true,true, false);
        // 2. 压力管道长度统计
//        stCommonService.staticsCenterMapCountDataForPipeline(result, orgCode,true, false);
        jgDPStatisticsService.staticsCenterMapCountPipLine(result, orgCode, true, false);
        //3.单位数量统计
        // 单位统计修改为查询es
//        this.staticsCenterMapCountDataForCompany(result, orgCode, dpFilterParamDto.getCityCode());
        this.staticsCenterMapCompanyCountToEs(result, orgCode);
        //4.人员数量统计
        // 人员统计改为查询es，修改之前查询的是作业人员的总数，修改为所有人员的总数
//        this.staticsCenterMapCountDataForPerson(result, dpFilterParamDto, orgCode);
        this.staticsCenterMapPersonCountToEs(result, orgCode);
        // 5.问题统计
        this.staticsCenterMapCountDataForIssue(result, orgCode);

        return result;
    }

    public List<Map<String, Object>> getDetailTree(DPFilterParamDto dpFilterParamDto) {
        List<Map<String, Object>> result = new ArrayList<>();
        Map<String, Object> item1 = new HashMap<>();
        item1.put("title", "主体类型");
        item1.put("value", "");
        item1.put("children", this.buildMainBodyChild());
        result.add(item1);
        return result;
    }

    private List<Map<String, Object>> buildMainBodyChild() {
        List<Map<String, Object>> child = Arrays.stream(IssueMainBodyEnum.values()).map(e -> {
            Map<String, Object> item1 = new HashMap<>();
            item1.put("title", e.getName());
            item1.put("value", e.getCode());
            item1.put("children", new ArrayList<>());
            return item1;
        }).collect(Collectors.toList());
        Collections.reverse(child);
        return child;
    }

    public Map<String, Object> issueCompanyTopDetailBar(DPFilterParamForDetailDto dpFilterParamDto) {
        // 1.查询区域信息
        Map<String, Object> result = new HashMap<>();
        List<RegionModel> childRegion = stCommonService.setRegionIfRootParentAndNoAccessIf3Level(dpFilterParamDto.getCityCode());
        if (childRegion.isEmpty()) {
            return new HashMap<>(0);
        }
        // 2.按照前端约定格式返回数据
        List<LegendDataDto> legendDataDtos = this.buildLegendDataListForCompanyTopDetailBar();
        // 2.1 图列数据构造
        result.put("legendData", legendDataDtos);
        // 2.2 x轴数据构造
        result.put("xdata", stCommonService.buildXData(childRegion));
        // 2.3 y轴数据构造
        result.put("yhTotal", this.buildYDataForIssueCompanyTopDetailBar(childRegion, dpFilterParamDto.getTreeValue()));
        return result;
    }

    private List<LegendDataDto> buildLegendDataListForChildrenCityCountTopLine() {
        List<LegendDataDto> legendDataDtos = new ArrayList<>();
        legendDataDtos.add(LegendDataDto.builder().dataKey("yhbhPercent").value("隐患闭环率").chartType("line").build());
        return legendDataDtos;
    }

    private List<LegendDataDto> buildLegendDataListForCompanyTopDetailBar() {
        List<LegendDataDto> legendDataDtos = new ArrayList<>();
        legendDataDtos.add(LegendDataDto.builder().dataKey("yhTotal").value("隐患总数").chartType("bar").build());
        return legendDataDtos;
    }

    private List<Long> buildYDataForIssueCompanyTopDetailBar(List<RegionModel> regionModels, String sourceTypeCode) {
        // 多线程处理
        List<CountDto> countDtos = regionModels.parallelStream().map(r -> {
            CountDto dto = new CountDto();
            dto.setKeyStr(r.getRegionCode().toString());
            String orgCode = stCommonService.getAndSetOrgCode(r.getRegionCode().toString());
            if (orgCode == null) {
                dto.setLongValue(0L);
            } else {
                long num = statisticsMapper.countByOrgCode(orgCode, null, sourceTypeCode);
                dto.setLongValue(num);
            }
            return dto;
        }).collect(Collectors.toList());
        // 多线程处理后数据顺序与x轴不一致，进行顺序调整
        return regionModels.stream().map(r -> countDtos.stream().filter(c -> c.getKeyStr().equals(r.getRegionCode().toString())).mapToLong(CountDto::getLongValue).sum()).collect(Collectors.toList());
    }

    public Map<String, Object> issueChildrenCityCountTopDetailLine(DPFilterParamForDetailDto dpFilterParamDto) {
        // 1.查询区域信息
        Map<String, Object> result = new HashMap<>();
        List<RegionModel> childRegion = stCommonService.setRegionIfRootParentAndNoAccessIf3Level(dpFilterParamDto.getCityCode());
        if (childRegion.isEmpty()) {
            return new HashMap<>(0);
        }
        // 2.按照前端约定格式返回数据
        List<LegendDataDto> legendDataDtos = this.buildLegendDataListForChildrenCityCountTopLine();
        // 2.1 图列数据构造
        result.put("legendData", legendDataDtos);
        // 2.2 x轴数据构造
        result.put("xdata", stCommonService.buildXData(childRegion));
        // 2.3 y轴数据构造
        result.put("yhbhPercent", this.buildYDataForChildrenCityCountDetailBar(childRegion, dpFilterParamDto.getTreeValue()));
        return result;
    }

    private List<String> buildYDataForChildrenCityCountDetailBar(List<RegionModel> regionModels, String sourceTypeCode) {
        // 多线程处理
        List<CountDto> countDtos = regionModels.parallelStream().map(r -> {
            CountDto dto = new CountDto();
            dto.setKeyStr(r.getRegionCode().toString());
            String orgCode = stCommonService.getAndSetOrgCode(r.getRegionCode().toString());
            if (orgCode == null) {
                dto.setStrValue("0");
            } else {
                List<CountDto> dtoList = statisticsMapper.selectByOrgAndMainBody(orgCode, null, sourceTypeCode);
                Long allProblemNum = dtoList.stream().mapToLong(CountDto::getLongValue).sum();
                Long handledProblemNum = dtoList.stream().filter(c -> c.getLabel().equals(SafetyProblemStatusEnum.HANDLED.getCode())).mapToLong(CountDto::getLongValue).sum();
                dto.setStrValue(calPercent(allProblemNum, handledProblemNum));
            }
            return dto;
        }).collect(Collectors.toList());
        // 多线程处理后数据顺序与x轴不一致，进行顺序调整
        return regionModels.stream().map(r -> countDtos.stream().filter(c -> c.getKeyStr().equals(r.getRegionCode().toString())).map(CountDto::getStrValue).findFirst().orElse("0")).collect(Collectors.toList());
    }

    private String calPercent(Long allProblemNum, Long handledProblemNum) {
        BigDecimal all = new BigDecimal(allProblemNum.toString());
        BigDecimal handled = new BigDecimal(Long.toString(handledProblemNum));
        String percent = "0";
        if (all.compareTo(BigDecimal.ZERO) > 0) {
            percent = handled.divide(all, 2, RoundingMode.HALF_UP).toPlainString();
        }
        return percent;
    }

    public Page<SafetyProblemTracingDto> getProblemRecords(Page<SafetyProblemTracingDto> page, SafetyProblemTracingDto problemModel) {
        String orgCode = stCommonService.getAndSetOrgCode(problemModel.getCityCode());
        if (orgCode == null) {
            return new Page<>();
        }
        problemModel.setGoverningBodyOrgCode(orgCode);
        // 使用orgCode过滤
        problemModel.setRegionCode(null);
        // 将单位类型从code转化为value
        if (!ValidationUtil.isEmpty(problemModel.getPrincipalUnitType())) {
            Collection<DataDictionary> unitTypeList = dataDictionaryMapper.selectList(new QueryWrapper<DataDictionary>()
                    .eq("type", "UNIT_TYPE_NEW")
                    .eq("is_delete", false)
                    .orderByAsc("sort_num"));
            Map<String, String> unitTypeMap = unitTypeList.stream().collect(Collectors.toMap(DataDictionary::getCode, DataDictionary::getName));
            problemModel.setPrincipalUnitType(unitTypeMap.getOrDefault(problemModel.getPrincipalUnitType(), null));
        }
        if (problemModel.getTimeSearchOne() != null) {
            problemModel.setProblemTimeStart(problemModel.getTimeSearchOne().getBeginDate());
            problemModel.setProblemTimeEnd(problemModel.getTimeSearchOne().getEndDate());
        }
        // 前端详情固定给的treeValue,后端进行进行字段转换
        problemModel.setSourceTypeCode(problemModel.getTreeValue());
        return statisticsMapper.queryForSafetyProblemTracingPage(page, problemModel);
    }

    public List<Map<String, Object>> getYhType() {
        List<DataDictionary> dictionaries = dataDictionaryMapper.selectList(new LambdaQueryWrapper<DataDictionary>().eq(DataDictionary::getType, "ISSUE_TYPE"));
        return dictionaries.stream().map(d -> {
            Map<String, Object> item = new HashMap<>();
            item.put("value", d.getCode());
            item.put("label", d.getName());
            return item;
        }).collect(Collectors.toList());
    }
}