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

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.dto.CountDto;
import com.yeejoin.amos.boot.biz.common.dto.JyjcInspectionApplicationDto;
import com.yeejoin.amos.boot.module.common.api.dto.AttachmentDto;
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.enums.AlertCallEnum;
import com.yeejoin.amos.boot.module.common.api.enums.JYJCBusinessTypeEnum;
import com.yeejoin.amos.boot.module.common.api.enums.JYJCResultEnum;
import com.yeejoin.amos.boot.module.common.api.enums.UnitTypeEnum;
import com.yeejoin.amos.boot.module.jyjc.api.dto.InspectTimeCountDto;
import com.yeejoin.amos.boot.module.jyjc.api.dto.InspectionTimelinesDto;
import com.yeejoin.amos.boot.module.jyjc.api.dto.PublicityInspectOrgInfoDto;
import com.yeejoin.amos.boot.module.jyjc.api.enums.BizTypeEnum;
import com.yeejoin.amos.boot.module.jyjc.api.enums.JYJCTypeEnum;
import com.yeejoin.amos.boot.module.jyjc.api.mapper.JyjcInspectionApplicationEquipMapper;
import com.yeejoin.amos.boot.module.jyjc.api.mapper.JyjcInspectionApplicationMapper;
import com.yeejoin.amos.boot.module.jyjc.api.mapper.JyjcInspectionResultMapper;
import com.yeejoin.amos.boot.module.jyjc.api.mapper.JyjcOpeningApplicationMapper;
import com.yeejoin.amos.boot.module.statistics.api.mapper.JYJCStatisticsMapper;
import com.yeejoin.amos.boot.module.ymt.api.dto.EquipmentCategoryDto;
import com.yeejoin.amos.boot.module.ymt.api.enums.EquimentEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.TzsUserInfoMapper;
import com.yeejoin.amos.feign.systemctl.model.RegionModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
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.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
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.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

import static com.yeejoin.amos.boot.module.statistcs.biz.service.impl.ZLDPStatisticsServiceImpl.IS_INTO_MANAGEMENT;

/**
 * 大屏统计实现类
 *
 * @author Administrator
 */
@Service
@Slf4j
public class JYJCDPStatisticsServiceImpl {

    /**
     * 压力容器设备种类
     */
    private final static String EQU_LIST_CYLINDER = "2000";

    /**
     * 气瓶设备类别
     */
    private final static String EQU_CATEGORY_CYLINDER = "2300";

    private static final String EQU_STATE = "EQU_STATE";
    //超期
    private static final String OVERTIME = "OVERTIME";
    //所有
    private static final String ALL = "ALL";
    //临期
    private static final String TEMPORARY = "TEMPORARY";

    private JyjcInspectionApplicationEquipMapper inspectionApplicationEquipMapper;

    private JyjcInspectionApplicationMapper inspectionApplicationMapper;

    private TzsUserInfoMapper tzsUserInfoMapper;

    private JyjcInspectionResultMapper inspectionResultMapper;

    private JyjcOpeningApplicationMapper openingApplicationMapper;

    private RestHighLevelClient restHighLevelClient;

    private StCommonServiceImpl stCommonService;

    private JYJCStatisticsMapper jyjcStatisticsMapper;

    /**
     * 法定检验机构名单
     */
    @Value("${jyjc.legal.companyCode:12610100750228848W,12610300MB2943942F,12610400435630992M,12610200435252143F,126105007326878566,12610600MB29845683,126108004366752362,12610700MB296441XY,12610900353680128G,126110004363154256,126100004352004822}")
    private String legalCompanyCodes;

    public JYJCDPStatisticsServiceImpl(JyjcInspectionApplicationEquipMapper inspectionApplicationEquipMapper, JyjcInspectionApplicationMapper inspectionApplicationMapper, TzsUserInfoMapper tzsUserInfoMapper, JyjcInspectionResultMapper inspectionResultMapper, JyjcOpeningApplicationMapper openingApplicationMapper, RestHighLevelClient restHighLevelClient, StCommonServiceImpl stCommonService, JYJCStatisticsMapper jyjcStatisticsMapper) {
        this.inspectionApplicationEquipMapper = inspectionApplicationEquipMapper;
        this.inspectionApplicationMapper = inspectionApplicationMapper;
        this.tzsUserInfoMapper = tzsUserInfoMapper;
        this.inspectionResultMapper = inspectionResultMapper;
        this.openingApplicationMapper = openingApplicationMapper;
        this.restHighLevelClient = restHighLevelClient;
        this.stCommonService = stCommonService;
        this.jyjcStatisticsMapper = jyjcStatisticsMapper;
    }


    public Map<String, Object> inspectTimeCountByTypeAndEquList(DPFilterParamDto dpFilterParamDto) {
        // 1.查询条件构造未上送时间时，默认查询数据为近一个月数据
        this.setDefaultFilter(dpFilterParamDto);
        // 2.按照前端约定格式返回数据
        Map<String, Object> result = new HashMap<>();
        //2.1 图列数据构造
        List<BizTypeEnum> bizTypeEnums = getBizTypeList();
        result.put("legendData", this.getLegendData(bizTypeEnums));
        // 8大类设备种类
        List<EquipmentCategoryDto> equipmentCategoryDtos = StCommonServiceImpl.getEquipmentCategory();
        //2.2 x轴数据构造
        result.put("xdata", this.getXData(equipmentCategoryDtos));
        //2.3 y轴数据构造
        this.buildYData(result, bizTypeEnums, dpFilterParamDto, equipmentCategoryDtos);
        return result;
    }

    private void buildYData(Map<String, Object> result, List<BizTypeEnum> bizTypeEnums, DPFilterParamDto dpFilterParamDto, List<EquipmentCategoryDto> equipmentCategoryDtos) {
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        // 待统计的数据本来sql可以单独统计，但是要求气瓶单独从压力容器里拎出来，与八大类同级，故java处理
        List<InspectTimeCountDto> inspectTimeCountDtos = inspectionApplicationEquipMapper.countInspectTimeCountByTypeAndEquList(orgCode, dpFilterParamDto);
        bizTypeEnums.forEach(bizTypeEnum -> {
            result.put(bizTypeEnum.getCode(), this.countNumByBizTypeAndEquList(equipmentCategoryDtos, bizTypeEnum.getCode(), inspectTimeCountDtos));
        });
    }

    private List<Integer> countNumByBizTypeAndEquList(List<EquipmentCategoryDto> equipmentCategoryDtos, String bizType, List<InspectTimeCountDto> inspectTimeCountDtos) {
        List<Integer> item = new ArrayList<>();
        // 8大类数据统计数量
        equipmentCategoryDtos.forEach(equipmentCategoryDto -> {
            int num = 0;
            // 压力容器要去掉气瓶2300，气瓶单独统计
            if (EQU_LIST_CYLINDER.equals(equipmentCategoryDto.getCode())) {
                num = inspectTimeCountDtos.stream().filter(c -> c.getBizType().equals(bizType) && c.getEquList().equals(equipmentCategoryDto.getCode()) && !EQU_CATEGORY_CYLINDER.equals(c.getEquCategory())).mapToInt(InspectTimeCountDto::getNum).sum();
            } else {
                num = inspectTimeCountDtos.stream().filter(c -> c.getBizType().equals(bizType) && c.getEquList().equals(equipmentCategoryDto.getCode())).mapToInt(InspectTimeCountDto::getNum).sum();
            }
            item.add(num);
        });
        // 再增加气瓶(设备类别2300)专项
        int num = inspectTimeCountDtos.stream().filter(c -> c.getBizType().equals(bizType) && EQU_CATEGORY_CYLINDER.equals(c.getEquCategory())).mapToInt(InspectTimeCountDto::getNum).sum();
        item.add(num);
        return item;
    }

    private List<String> getXData(List<EquipmentCategoryDto> equipmentCategoryDtos) {
        // 8大类  + 气瓶 注意数据顺序和要和这个x轴一致
        List<String> names = equipmentCategoryDtos.stream().map(EquipmentCategoryDto::getName).collect(Collectors.toList());
        names.add("气瓶");
        return names;
    }

    private List<BizTypeEnum> getBizTypeList() {
        return Arrays.asList(BizTypeEnum.FIRST_INSPECTION, BizTypeEnum.SUPERVISE, BizTypeEnum.DETECTION);
    }

    private List<Map<String, Object>> getLegendData(List<BizTypeEnum> bizTypeEnums) {
        return bizTypeEnums.stream().map(b -> {
            Map<String, Object> item = new HashMap<>();
            item.put("dataKey", b.getCode());
            item.put("value", b.getName());
            return item;
        }).collect(Collectors.toList());
    }

    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(DateUtil.today());
        }
    }

    public Map<String, Object> inspectTimeCount(DPFilterParamDto dpFilterParamDto) {
        Map<String, Object> returnMap = new HashMap<>();
        LocalDate today = LocalDate.now();
        List xDataList = new ArrayList();
        List<Integer> yDataList = new ArrayList();
        DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        for (int i = 2; i >= 0; i--) {
            LocalDate firstDayOfPrevMonth = today.minusMonths(i).with(TemporalAdjusters.firstDayOfMonth());
            LocalDate lastDayOfPrevMonth = today.minusMonths(i).with(TemporalAdjusters.lastDayOfMonth());
            dpFilterParamDto.setBeginDate(LocalDateTime.of(firstDayOfPrevMonth, java.time.LocalTime.MIN).format(sdf));
            dpFilterParamDto.setEndDate(LocalDateTime.of(lastDayOfPrevMonth, java.time.LocalTime.MAX).format(sdf));
            Integer inspectTimeCount = inspectionApplicationEquipMapper.inspectTimeCount(dpFilterParamDto);
            xDataList.add(firstDayOfPrevMonth.getMonthValue() + "月");
            yDataList.add(null == inspectTimeCount ? 0 : inspectTimeCount);
        }
        returnMap.put("xdata", xDataList);
        returnMap.put("ydata", yDataList);
        return returnMap;
    }

    public Map<String, Object> inspectPersonCount(DPFilterParamDto dpFilterParamDto) {
        // 2.按照前端约定格式返回数据
        Map<String, Object> result = new HashMap<>();
        List<RegionModel> childRegion = stCommonService.setRegionIfRootParentAndNoAccessIf3Level(dpFilterParamDto);
        if (childRegion.isEmpty()) {
            return new HashMap<>(0);
        }
        //2.1 x轴数据构造
        result.put("xdata", this.getXDataForInspectPersonCount(childRegion));
        //2.3 y轴数据构造
        this.buildYDataForInspectPersonCount(result, childRegion);
        return result;
    }

    public Page<Map<String, Object>> countPage(Page page, DPFilterParamForDetailDto dpFilterParamDto) {
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        dpFilterParamDto.setOrgCode(orgCode);
        List<String> unitTypeList = new ArrayList<>();
        if(StringUtils.isNotEmpty(dpFilterParamDto.getTreeValue())){
            unitTypeList = UnitTypeEnum.getNameListByType(dpFilterParamDto.getTreeValue());
        }
        Page<Map<String,Object>> pageList = jyjcStatisticsMapper.selectUserList(page,dpFilterParamDto,unitTypeList);
        return pageList;
    }

    public List<Map<String, Object>> personCountType(DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        List<Map<String, String>> typeNameList = UnitTypeEnum.getTypeNameList();
        List<Map<String,Object>> result = new ArrayList<>();
        Map<String,Object> map = new HashMap<>();
        map.put("title","人员全部类型");
        map.put("value","all");
        map.put("children",typeNameList);
        result.add(map);
        return result;
    }

    private void buildYDataForInspectPersonCount(Map<String, Object> result, List<RegionModel> childRegion) {
        List<Long> yData = new ArrayList<>();
        childRegion.forEach(regionModel -> {
            String orgCode = stCommonService.getAndSetOrgCode(regionModel.getRegionCode() + "");
            if (StringUtils.isEmpty(orgCode)) {
                yData.add(0L);
            } else {
                Long num = tzsUserInfoMapper.countUserByPostAndAreaCode(orgCode, "6615", regionModel.getRegionCode() + "");
                yData.add(num);
            }
        });
        result.put("ydata", yData);
    }


    private List<String> getXDataForInspectPersonCount(List<RegionModel> childRegion) {
        return childRegion.stream().map(RegionModel::getRegionName).collect(Collectors.toList());
    }


    public Map<String, Object> queryAllFlowingAndFinishedInspectApp(DPFilterParamDto dpFilterParamDto) {
        // 1.查询条件构造未上送时间时，默认查询数据为近一个月数据
        this.setDefaultFilter(dpFilterParamDto);
        // 2.按照前端约定格式返回数据
        Map<String, Object> result = new HashMap<>();
        JYJCTypeEnum[] jyjcTypeEnums = JYJCTypeEnum.values();
        //2.1 x轴数据构造
        result.put("xdata", this.getXDataForInspectBizNumCount(jyjcTypeEnums));
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if(orgCode == null){
            return result;
        }
        //2.3 y轴数据构造
        this.buildYDataForFlowingAndFinishedInspectApp(result, jyjcTypeEnums, dpFilterParamDto);
        return result;
    }

    public Map<String, Object> queryAllPendingResultInspectApp(DPFilterParamDto dpFilterParamDto) {
        // 1.查询条件构造未上送时间时，默认查询数据为近一个月数据
        this.setDefaultFilter(dpFilterParamDto);
        // 2.按照前端约定格式返回数据
        Map<String, Object> result = new HashMap<>();
        JYJCTypeEnum[] jyjcTypeEnums = JYJCTypeEnum.values();
        //2.1 x轴数据构造
        result.put("xdata", this.getXDataForInspectBizNumCount(jyjcTypeEnums));
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if(orgCode == null){
            return result;
        }
        //2.3 y轴数据构造
        this.buildYDataForPendingResultInspectApp(result, jyjcTypeEnums, dpFilterParamDto, orgCode);
        return result;
    }

    public Map<String, Object> queryAllInspectApp(DPFilterParamDto dpFilterParamDto) {
        // 1.查询条件构造未上送时间时，默认查询数据为近一个月数据
        this.setDefaultFilter(dpFilterParamDto);
        // 2.按照前端约定格式返回数据
        Map<String, Object> result = new HashMap<>();
        JYJCTypeEnum[] jyjcTypeEnums = JYJCTypeEnum.values();
        //2.1 x轴数据构造
        result.put("xdata", this.getXDataForInspectBizNumCount(jyjcTypeEnums));
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if(orgCode == null){
            return result;
        }
        //待检数量
        List<CountDto> pendingList = inspectionApplicationMapper.queryAllPendingResultInspectApp(orgCode, dpFilterParamDto);
        //业务数量
        List<CountDto> countDtoList = inspectionApplicationMapper.queryAllFlowingAndFinishedInspectApp(orgCode, dpFilterParamDto);

        List<Long> pending = new ArrayList<>();
        for (JYJCTypeEnum jyjcTypeEnum : jyjcTypeEnums) {
            Long num = pendingList.stream().filter(c -> c.getKeyStr().equals(jyjcTypeEnum.getCode())).mapToLong(CountDto::getLongValue).sum();
            pending.add(num);
        }
        result.put("pending", pending);

        List<Long> business = new ArrayList<>();
        for (JYJCTypeEnum jyjcTypeEnum : jyjcTypeEnums) {
            Long num = countDtoList.stream().filter(c -> c.getKeyStr().equals(jyjcTypeEnum.getCode())).mapToLong(CountDto::getLongValue).sum();
            business.add(num);
        }
        result.put("business", business);
        List legendData = new ArrayList<>();
        for(int i = 0; i < 2; i++){
            Map<String, Object> map = new HashMap<>();
            if(i == 0){
                map.put("dataKey", "business");
                map.put("value", "业务数量");
            }else {
                map.put("dataKey", "pending");
                map.put("value", "待检数量");
            }
            legendData.add(map);
        }
        result.put("legendData", legendData);
        result.put("unit", "台套");

        return result;
    }

    private void buildYDataForPendingResultInspectApp(Map<String, Object> result, JYJCTypeEnum[] jyjcTypeEnums, DPFilterParamDto dpFilterParamDto, String orgCode) {
        List<CountDto> countDtoList = inspectionApplicationMapper.queryAllPendingResultInspectApp(orgCode, dpFilterParamDto);
        fillJYJCYData(result, jyjcTypeEnums, countDtoList);
    }

    private void fillJYJCYData(Map<String, Object> result, JYJCTypeEnum[] jyjcTypeEnums, List<CountDto> countDtoList) {
        List<Long> yData = new ArrayList<>();
        for (JYJCTypeEnum jyjcTypeEnum : jyjcTypeEnums) {
            Long num = countDtoList.stream().filter(c -> c.getKeyStr().equals(jyjcTypeEnum.getCode())).mapToLong(CountDto::getLongValue).sum();
            yData.add(num);
        }
        result.put("ydata", yData);
    }

    private void buildYDataForFlowingAndFinishedInspectApp(Map<String, Object> result, JYJCTypeEnum[] jyjcTypeEnums, DPFilterParamDto dpFilterParamDto) {
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        List<CountDto> countDtoList = inspectionApplicationMapper.queryAllFlowingAndFinishedInspectApp(orgCode, dpFilterParamDto);
        fillJYJCYData(result, jyjcTypeEnums, countDtoList);
    }

    private List<String> getXDataForInspectBizNumCount(JYJCTypeEnum[] jyjcTypeEnums) {
        return Arrays.stream(jyjcTypeEnums).map(JYJCTypeEnum::getName).collect(Collectors.toList());
    }

    public List<InspectionTimelinesDto> queryInspectionTimelinessTopXX(String top, DPFilterParamDto dpFilterParamDto) {
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if(orgCode == null){
            return new ArrayList<>();
        }
        return inspectionResultMapper.queryInspectionTimelinessTopXX(top, orgCode, dpFilterParamDto);
    }

    public Map<String, Object> inspectionTimelinessTopXXChart(DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        List<RegionModel> regionModels = stCommonService.setRegionIfRootParent(dpFilterParamForDetailDto.getCityCode());
        List<Map<String,Object>> result =  regionModels.parallelStream().map(r -> {
            String orgCode = stCommonService.getAndSetOrgCode(r.getRegionCode()+"");
            DPFilterParamForDetailDto dpFilterParamForDetailDtoForSearch = new DPFilterParamForDetailDto();
            dpFilterParamForDetailDtoForSearch.setOrgCode(orgCode);
            dpFilterParamForDetailDtoForSearch.setCityCode(r.getRegionCode()+"");
            Map<String, Object> itemResult = new HashMap<>();
            itemResult.put("xdata",r.getRegionName());
            getInspectionTimelinessTopXXChart(itemResult,dpFilterParamForDetailDtoForSearch);
            return itemResult;
        }).collect(Collectors.toList());

        Map<String,Object> returnMap = new HashMap<>();
        List<Map<String,Object>> legendData = new ArrayList<>();
        for(int i = 0;i<2; i++){
            Map<String,Object> map = new HashMap<>();
            if(i == 0){
                map.put("dataKey","inspectionCount");
                map.put("value","报检设备数量");
                map.put("chartType","bar");
            }else{
                map.put("dataKey","inspectionFinishCount");
                map.put("value","已检设备数量");
                map.put("chartType","bar");
            }
            legendData.add(map);
        }
        returnMap.put("legendData",legendData);

        List xdata = new ArrayList();
        List inspectionCount = new ArrayList();
        List inspectionFinishCount = new ArrayList();

        for(int i = 0;i<result.size();i++){
            xdata.add(result.get(i).get("xdata"));
            inspectionCount.add(result.get(i).get("inspectionCount") == null ? "0" : result.get(i).get("inspectionCount"));
            inspectionFinishCount.add(result.get(i).get("inspectionFinishCount") == null ? "0" : result.get(i).get("inspectionFinishCount"));
        }

        returnMap.put("xdata",xdata);
        returnMap.put("inspectionCount",inspectionCount);
        returnMap.put("inspectionFinishCount",inspectionFinishCount);

        return returnMap;
    }

    public Page<Map<String, Object>> inspectionTimelinessTopXXPage(Page<Map<String, Object>> page, DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamForDetailDto.getCityCode());
        dpFilterParamForDetailDto.setOrgCode(orgCode);
        Page<Map<String, Object>> returnPage = jyjcStatisticsMapper.inspectionTimelinessTopXXPage(page,dpFilterParamForDetailDto);
        return returnPage;
    }

    public List<Map<String, Object>> inspectionTimelinessTopXXType(DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        List<Map<String,Object>> result = new ArrayList<>();
        List<HashMap<String, Object>> list = new ArrayList<>();
        HashMap<String, Object> map = new HashMap<>();
        map.put("title", "检验检测机构");
        map.put("value", "检验检测机构");
        list.add(map);
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("title","企业类型");
        resultMap.put("value","0");
        resultMap.put("children",list);
        result.add(resultMap);
        return result;
    }

    private void getInspectionTimelinessTopXXChart(Map<String, Object> itemResult, DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        //报检数量
        Long inspectionCount = jyjcStatisticsMapper.inspectionCount(dpFilterParamForDetailDto);
        //已检数量
        Long inspectionFinishCount = jyjcStatisticsMapper.inspectionFinishCount(dpFilterParamForDetailDto);

        itemResult.put("inspectionCount", inspectionCount);
        itemResult.put("inspectionFinishCount", inspectionFinishCount);
    }

    public List<PublicityInspectOrgInfoDto> queryInspectionOrgListForPublicity(DPFilterParamDto dpFilterParamDto) {
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if(orgCode == null){
            return new ArrayList<>();
        }
        return openingApplicationMapper.queryInspectionOrgListForPublicity(orgCode, dpFilterParamDto);
    }

    public Map<String, Object> queryInspectionEquipByEquList(DPFilterParamDto dpFilterParamDto) {
        Map<String, Object> result = new HashMap<>();
        // 1.查询条件构造未上送时间时，默认查询数据为近一个月数据
        this.setDefaultFilter(dpFilterParamDto);
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        // 2.x轴数据构建
        List<EquipmentCategoryDto> equipmentCategoryDtos = StCommonServiceImpl.getEquipmentCategory();
        this.setXDataForInspectionEquipByEquList(result, equipmentCategoryDtos);
        // 3.图列数据设置
        this.setLegendDataForInspectionEquipByEquList(result);
        if(orgCode == null){
            return result;
        }
        // 4.y轴数据设置
        // 目前都单设备报检故统计主表即可
        List<CountDto> countDtos = inspectionApplicationMapper.queryAppByEquListForDP(orgCode, dpFilterParamDto);
        Map<String, List<CountDto>> groupByMap = countDtos.stream().collect(Collectors.groupingBy(CountDto::getLabel));
        this.setYDataForInspectionEquipByEquList(result, groupByMap, equipmentCategoryDtos);
        result.put("unit", "台套");
        return result;
    }

    private void setYDataForInspectionEquipByEquList(Map<String, Object> result, Map<String, List<CountDto>> groupByMap, List<EquipmentCategoryDto> equipmentCategoryDtos) {
        groupByMap.forEach((key, value) -> result.put(key, this.setInspectionEquipData(value, equipmentCategoryDtos)));
    }

    private List<Long> setInspectionEquipData(List<CountDto> countDtos, List<EquipmentCategoryDto> equipmentCategoryDtos) {
        return equipmentCategoryDtos.stream().map(e -> countDtos.stream().filter(c -> c.getKeyStr().equals(e.getCode())).mapToLong(CountDto::getLongValue).sum()).collect(Collectors.toList());
    }

    private void setLegendDataForInspectionEquipByEquList(Map<String, Object> result) {
        Map<String, Object> item1 = new LinkedHashMap<>();
        item1.put("dataKey", "pending");
        item1.put("value", "待检数量");
        Map<String, Object> item2 = new LinkedHashMap<>();
        item2.put("dataKey", "reporting");
        item2.put("value", "报检数量");
        result.put("legendData", Arrays.asList(item1, item2));
    }

    private void setXDataForInspectionEquipByEquList(Map<String, Object> result, List<EquipmentCategoryDto> equipmentCategoryDtos) {
        // 8大类
        List<String> names = equipmentCategoryDtos.stream().map(EquipmentCategoryDto::getName).collect(Collectors.toList());
        result.put("xdata", names);
    }


    private List<String> getEquListXDataCommon(List<EquipmentCategoryDto> equipmentCategoryDtos) {
        // 8大类
        return equipmentCategoryDtos.stream().map(EquipmentCategoryDto::getName).collect(Collectors.toList());
    }


    public Map<String, Object> getCenterMapCountDataForGlobal(DPFilterParamDto dpFilterParamDto) {
        Map<String, Object> result = new HashMap<>();
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if (StringUtils.isEmpty(orgCode)) {
            return result;
        }
        // 1.气瓶统计
        long cylinderNum = stCommonService.staticsCenterMapCountDataForCylinder(result, orgCode,true);
        // 2.8大类统计
        stCommonService.staticsCenterMapCountDataForEquip(result, cylinderNum, orgCode,true);
        // 3.压力管道统计
        stCommonService.staticsCenterMapCountDataForPipeline(result, orgCode,true);
        // 4.报检数量统计
        this.staticsCenterMapCountDataReporting(result, dpFilterParamDto);
        // 5.检验检测临期设备数数量统计
        this.staticsCenterMapCountDataTemporary(result, dpFilterParamDto);
        // 6.检验检测超期设备数数量统计
        this.staticsCenterMapCountDataOverdue(result, dpFilterParamDto);
        // 7.检验机构总量 inspectionAgencyCount
        this.countAllRegInspectCompany(result, orgCode,dpFilterParamDto.getCityCode());
        // 8.第三方检验机构数量  thirdInspectionAgencyCount
        this.countAllRegThirdInspectCompany(result, orgCode,dpFilterParamDto.getCityCode());
        // 7.业务开通机构数量  bizKtCount
        this.countAllOpenBizInspectCompany(result, orgCode,dpFilterParamDto.getCityCode());
        return result;
    }

    private void countAllRegInspectCompany(Map<String, Object> result, String orgCode, String regionCode) {
        Long num = jyjcStatisticsMapper.countAllRegInspectCompany(orgCode,regionCode);
        result.put("inspectionAgencyCount", num);
    }

    private void countAllRegThirdInspectCompany(Map<String, Object> result, String orgCode, String regionCode) {
        Long num = jyjcStatisticsMapper.countAllRegThirdInspectCompany(orgCode, Arrays.asList(legalCompanyCodes.split(",")), regionCode);
        result.put("thirdInspectionAgencyCount", num);
    }

    private void countAllOpenBizInspectCompany(Map<String, Object> result, String orgCode, String regionCode) {
        Long num = jyjcStatisticsMapper.countAllOpenBizInspectCompany(orgCode, regionCode);
        result.put("bizKtCount", num);
    }

    private void staticsCenterMapCountDataTemporary(Map<String, Object> result, DPFilterParamDto dpFilterParamDto) {
        long num = 0;
        CountRequest request = new CountRequest();
        request.indices("idx_biz_view_jg_all");
        BoolQueryBuilder boolMust = QueryBuilders.boolQuery();
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        // 按照管辖机构区域信息模糊查询
        boolMust.must(QueryBuilders.wildcardQuery("ORG_BRANCH_CODE.keyword", QueryParser.escape(orgCode) + "*"));
        // 只统计已纳管设备
        boolMust.must(QueryBuilders.termQuery("IS_INTO_MANAGEMENT", Boolean.TRUE));
        // 且下次检验日期大于等于当天
        long currentDayTime = DateUtil.parse(DateUtil.today(), "yyy-MM-dd").getTime();
        // 且查询 下次检验日期 <= 当前天+30天 极为临期
        long currentDayAfter30DayTime = DateUtil.offsetDay(DateUtil.parse(DateUtil.today(), "yyy-MM-dd"), 30).getTime();
        boolMust.must(QueryBuilders.rangeQuery("NEXT_INSPECT_DATE").gte(currentDayTime).lte(currentDayAfter30DayTime));
        // 且8大类，目的去掉脏数据
        boolMust.must(QueryBuilders.termsQuery("EQU_LIST_CODE",StCommonServiceImpl.getEquipmentCategory().stream().map(EquipmentCategoryDto::getCode).collect(Collectors.toList())));
        request.query(boolMust);
        try {
            CountResponse response = restHighLevelClient.count(request, RequestOptions.DEFAULT);
            num = response.getCount();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        result.put("jyjclqsbCount", num);
    }

    private void staticsCenterMapCountDataOverdue(Map<String, Object> result, DPFilterParamDto dpFilterParamDto) {
        long num = 0;
        CountRequest request = new CountRequest();
        request.indices("idx_biz_view_jg_all");
        BoolQueryBuilder boolMust = QueryBuilders.boolQuery();
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        // 按照管辖机构区域信息模糊查询
        boolMust.must(QueryBuilders.wildcardQuery("ORG_BRANCH_CODE.keyword", QueryParser.escape(orgCode) + "*"));
        // 只统计已纳管设备
        boolMust.must(QueryBuilders.termQuery("IS_INTO_MANAGEMENT", Boolean.TRUE));
        // 查询下次检验日期小于当前天的设备，即为超期检验超期设备
        long currentDayTime = DateUtil.parse(DateUtil.now(), "yyy-MM-dd").getTime();
        boolMust.must(QueryBuilders.rangeQuery("NEXT_INSPECT_DATE").lt(currentDayTime));
        // 且8大类，目的去掉脏数据
        boolMust.must(QueryBuilders.termsQuery("EQU_LIST_CODE",StCommonServiceImpl.getEquipmentCategory().stream().map(EquipmentCategoryDto::getCode).collect(Collectors.toList())));
        request.query(boolMust);
        try {
            CountResponse response = restHighLevelClient.count(request, RequestOptions.DEFAULT);
            num = response.getCount();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        result.put("jyjccqsbCount", num);
    }


    private void staticsCenterMapCountDataReporting(Map<String, Object> result, DPFilterParamDto dpFilterParamDto) {
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        CountDto countDto = inspectionApplicationMapper.queryAppByEquListForReporting(orgCode, dpFilterParamDto);
        result.put("bjCount", countDto.getLongValue());
    }


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


    public Map<String, Object> equipInspectTimeCountByEquList(DPFilterParamDto dpFilterParamDto) {
        // 1.按照前端约定格式返回数据
        Map<String, Object> result = new HashMap<>();
        // 1.1 图列数据构造
        result.put("legendData", this.getLegendDataForJyTime());
        // 8大类设备种类
        List<EquipmentCategoryDto> equipmentCategoryDtos = StCommonServiceImpl.getEquipmentCategory();
        // 2.x轴数据构造
        result.put("xdata", this.getEquListXDataCommon(equipmentCategoryDtos));
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if(orgCode == null){
            return result;
        }
        // 3.y轴数据构造
        this.buildYDataForJyTime(result, dpFilterParamDto, equipmentCategoryDtos);
        return result;
    }

    public Map<String,Object> equipInspectTimeCountListDetail(DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        //查询子区域
        List<RegionModel> regionModels = stCommonService.setRegionIfRootParent(dpFilterParamForDetailDto.getCityCode());

        List<Map<String, Object>> result = regionModels.parallelStream().map(r -> {
            DPFilterParamForDetailDto filterParamDto = new DPFilterParamForDetailDto();
            filterParamDto.setCityCode(r.getRegionCode().toString());
            filterParamDto.setTreeValue(dpFilterParamForDetailDto.getTreeValue());
            filterParamDto.setEquCategoryCode(dpFilterParamForDetailDto.getEquCategoryCode());
            Map<String, Object> itemResult = new HashMap<>();
            itemResult.put("xdata", r.getRegionName());
            Long timeTemporaryCount = staticsCenterMapCountDataForJyTimeTemporaryForDetail(filterParamDto);
            Long timeOverdueCount = staticsCenterMapCountDataForJyTimeOverdueForDetail(filterParamDto);
            itemResult.put("timeTemporaryCount",timeTemporaryCount);
            itemResult.put("timeOverdueCount",timeOverdueCount);
            return itemResult;
        }).collect(Collectors.toList());

        Map<String,Object> returnMap = new HashMap<>();
        List<Map<String,Object>> legendData = new ArrayList<>();
        for(int i = 0;i<2; i++){
            Map<String,Object> map = new HashMap<>();
            if(i == 0){
                map.put("dataKey","timeTemporaryCount");
                map.put("value","临期数量");
                map.put("chartType","bar");
            }else{
                map.put("dataKey","timeOverdueCount");
                map.put("value","超期数量");
                map.put("chartType","bar");
            }
            legendData.add(map);
        }
        returnMap.put("legendData",legendData);

        List xdata = new ArrayList();
        List timeTemporaryCount = new ArrayList();
        List timeOverdueCount = new ArrayList();

        for(int i = 0;i<result.size();i++){
            xdata.add(result.get(i).get("xdata"));
            timeTemporaryCount.add(result.get(i).get("timeTemporaryCount"));
            timeOverdueCount.add(result.get(i).get("timeOverdueCount"));
        }

        returnMap.put("xdata",xdata);
        returnMap.put("timeTemporaryCount",timeTemporaryCount);
        returnMap.put("timeOverdueCount",timeOverdueCount);

        return returnMap;
    }

    private Long staticsCenterMapCountDataForJyTimeTemporaryForDetail(DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        Long value = 0L;
        SearchRequest request = new SearchRequest();
        request.indices("idx_biz_view_jg_all");
        BoolQueryBuilder boolMust = QueryBuilders.boolQuery();
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamForDetailDto.getCityCode());
        // 按照管辖机构区域信息模糊查询
        boolMust.must(QueryBuilders.wildcardQuery("ORG_BRANCH_CODE.keyword", QueryParser.escape(orgCode) + "*"));
        // 只统计已纳管设备
        boolMust.must(QueryBuilders.termQuery("IS_INTO_MANAGEMENT", Boolean.TRUE));
        // 且下次检验日期大于等于当天 且查询 下次检验日期 <= 当前天+30天 即为临期
        long currentDayTime = DateUtil.parse(DateUtil.today(), "yyy-MM-dd").getTime();
        long currentDayAfter30DayTime = DateUtil.offsetDay(DateUtil.parse(DateUtil.today(), "yyy-MM-dd"), 30).getTime();
        boolMust.must(QueryBuilders.rangeQuery("NEXT_INSPECT_DATE").gte(currentDayTime).lte(currentDayAfter30DayTime));

        if(StrUtil.isNotEmpty(dpFilterParamForDetailDto.getTreeValue()) && !"0".equals(dpFilterParamForDetailDto.getTreeValue())) {
            boolMust.must(QueryBuilders.termQuery("EQU_LIST_CODE", dpFilterParamForDetailDto.getTreeValue()));
        }else{
            // 且8大类，目的去掉脏数据
            boolMust.must(QueryBuilders.termsQuery("EQU_LIST_CODE", StCommonServiceImpl.getEquipmentCategory().stream().map(EquipmentCategoryDto::getCode).collect(Collectors.toList())));
        }

        if(StrUtil.isNotEmpty(dpFilterParamForDetailDto.getEquCategoryCode())){
            boolMust.must(QueryBuilders.termQuery("EQU_CATEGORY_CODE", dpFilterParamForDetailDto.getEquCategoryCode()));
        }

        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(boolMust);
        request.source(builder);
        try {
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            value = response.getHits().getTotalHits().value;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return value;
    }

    private Long staticsCenterMapCountDataForJyTimeOverdueForDetail(DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        Long value = 0L;
        SearchRequest request = new SearchRequest();
        request.indices("idx_biz_view_jg_all");
        BoolQueryBuilder boolMust = QueryBuilders.boolQuery();
        // 区域信息模糊查询
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamForDetailDto.getCityCode());
        // 按照管辖机构区域信息模糊查询
        boolMust.must(QueryBuilders.wildcardQuery("ORG_BRANCH_CODE.keyword", QueryParser.escape(orgCode) + "*"));
        // 只统计已纳管设备
        boolMust.must(QueryBuilders.termQuery("IS_INTO_MANAGEMENT", Boolean.TRUE));
        // 查询下次检验日期小于当前天的设备，即为超期检验超期设备
        long currentDayTime = DateUtil.parse(DateUtil.now(), "yyy-MM-dd").getTime();
        boolMust.must(QueryBuilders.rangeQuery("NEXT_INSPECT_DATE").lt(currentDayTime));

        if(StrUtil.isNotEmpty(dpFilterParamForDetailDto.getTreeValue()) && !"0".equals(dpFilterParamForDetailDto.getTreeValue())) {
            boolMust.must(QueryBuilders.termQuery("EQU_LIST_CODE", dpFilterParamForDetailDto.getTreeValue()));
        }else{
            // 且8大类，目的去掉脏数据
            boolMust.must(QueryBuilders.termsQuery("EQU_LIST_CODE", StCommonServiceImpl.getEquipmentCategory().stream().map(EquipmentCategoryDto::getCode).collect(Collectors.toList())));
        }

        if(StrUtil.isNotEmpty(dpFilterParamForDetailDto.getEquCategoryCode())){
            boolMust.must(QueryBuilders.termQuery("EQU_CATEGORY_CODE", dpFilterParamForDetailDto.getEquCategoryCode()));
        }
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(boolMust);
        request.source(builder);
        try {
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            value = response.getHits().getTotalHits().value;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return value;
    }

    private void buildYDataForJyTime(Map<String, Object> result, DPFilterParamDto dpFilterParamDto, List<EquipmentCategoryDto> equipmentCategoryDtos) {
        // 1.检验检测临期设备数数量统计
        result.put("approach", staticsCenterMapCountDataForJyTimeTemporary(dpFilterParamDto, equipmentCategoryDtos));
        // 2.检验检测超期设备数数量统计
        result.put("overdue", staticsCenterMapCountDataForJyTimeOverdue(dpFilterParamDto, equipmentCategoryDtos));
    }

    private List<Long> staticsCenterMapCountDataForJyTimeTemporary(DPFilterParamDto dpFilterParamDto, List<EquipmentCategoryDto> equipmentCategoryDtos) {
        List<Long> seresData = new ArrayList<>();
        SearchRequest request = new SearchRequest();
        request.indices("idx_biz_view_jg_all");
        BoolQueryBuilder boolMust = QueryBuilders.boolQuery();
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        // 按照管辖机构区域信息模糊查询
        boolMust.must(QueryBuilders.wildcardQuery("ORG_BRANCH_CODE.keyword", QueryParser.escape(orgCode) + "*"));
        // 只统计已纳管设备
        boolMust.must(QueryBuilders.termQuery("IS_INTO_MANAGEMENT", Boolean.TRUE));
        // 且下次检验日期大于等于当天 且查询 下次检验日期 <= 当前天+30天 即为临期
        long currentDayTime = DateUtil.parse(DateUtil.today(), "yyy-MM-dd").getTime();
        long currentDayAfter30DayTime = DateUtil.offsetDay(DateUtil.parse(DateUtil.today(), "yyy-MM-dd"), 30).getTime();
        boolMust.must(QueryBuilders.rangeQuery("NEXT_INSPECT_DATE").gte(currentDayTime).lte(currentDayAfter30DayTime));
        // 且8大类，目的去掉脏数据
        boolMust.must(QueryBuilders.termsQuery("EQU_LIST_CODE",StCommonServiceImpl.getEquipmentCategory().stream().map(EquipmentCategoryDto::getCode).collect(Collectors.toList())));
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(boolMust);
        TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("count_by_equ_list_code").field("EQU_LIST_CODE");
        builder.aggregation(aggregationBuilder);
        request.source(builder);
        try {
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            Terms terms = response.getAggregations().get("count_by_equ_list_code");
            Map<String, Long> countMap = new HashMap<>();
            for (Terms.Bucket bucket : terms.getBuckets()) {
                countMap.put(bucket.getKeyAsString(), bucket.getDocCount());
            }
            // 按照8大类枚举，进行加工。目的：固定八大类防止没统计数据导致缺少分类、将设备种类的code换成前端定义的key
            equipmentCategoryDtos.forEach(c -> {
                seresData.add(countMap.getOrDefault(c.getCode(), 0L));
            });
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return seresData;
    }

    private List<Long> staticsCenterMapCountDataForJyTimeOverdue(DPFilterParamDto dpFilterParamDto, List<EquipmentCategoryDto> equipmentCategoryDtos) {
        List<Long> seresData = new ArrayList<>();
        SearchRequest request = new SearchRequest();
        request.indices("idx_biz_view_jg_all");
        BoolQueryBuilder boolMust = QueryBuilders.boolQuery();
        // 区域信息模糊查询
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        // 按照管辖机构区域信息模糊查询
        boolMust.must(QueryBuilders.wildcardQuery("ORG_BRANCH_CODE.keyword", QueryParser.escape(orgCode) + "*"));
        // 只统计已纳管设备
        boolMust.must(QueryBuilders.termQuery("IS_INTO_MANAGEMENT", Boolean.TRUE));
        // 查询下次检验日期小于当前天的设备，即为超期检验超期设备
        long currentDayTime = DateUtil.parse(DateUtil.now(), "yyy-MM-dd").getTime();
        boolMust.must(QueryBuilders.rangeQuery("NEXT_INSPECT_DATE").lt(currentDayTime));
        // 且8大类，目的去掉脏数据
        boolMust.must(QueryBuilders.termsQuery("EQU_LIST_CODE",StCommonServiceImpl.getEquipmentCategory().stream().map(EquipmentCategoryDto::getCode).collect(Collectors.toList())));
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(boolMust);
        TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("count_by_equ_list_code").field("EQU_LIST_CODE");
        builder.aggregation(aggregationBuilder);
        request.source(builder);
        try {
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            Terms terms = response.getAggregations().get("count_by_equ_list_code");
            Map<String, Long> countMap = new HashMap<>();
            for (Terms.Bucket bucket : terms.getBuckets()) {
                countMap.put(bucket.getKeyAsString(), bucket.getDocCount());
            }
            // 按照8大类枚举，进行加工。目的：固定八大类防止没统计数据导致缺少分类、将设备种类的code换成前端定义的key
            equipmentCategoryDtos.forEach(c -> {
                seresData.add(countMap.getOrDefault(c.getCode(), 0L));
            });
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return seresData;
    }

    private Object getLegendDataForJyTime() {
        Map<String, Object> item1 = new LinkedHashMap<>();
        item1.put("dataKey", "approach");
        item1.put("value", "临期");
        Map<String, Object> item2 = new LinkedHashMap<>();
        item2.put("dataKey", "overdue");
        item2.put("value", "超期");
        return Arrays.asList(item1, item2);
    }



    public Page<JyjcInspectionApplicationDto> queryForInspectAppPageList(Page<JyjcInspectionApplicationDto> page, JyjcInspectionApplicationDto model) {
        String orgCode = stCommonService.getAndSetOrgCode(model.getCityCode());
        if(orgCode == null){
            page.setTotal(0);
            return page;
        }
        return jyjcStatisticsMapper.queryForInspectAppPageList(page, model, orgCode);
    }

    public JSONObject queryDetailsMatui(Long sequenceNbr, JSONObject jsonObject) {
        List<Map<String, Object>> dataByApplicationSeq = jyjcStatisticsMapper.getDataByApplicationSeq(sequenceNbr);
        Map<String, Object> attMap = new HashMap<>();
        for (Map<String, Object> maps : dataByApplicationSeq) {
            List<AttachmentDto> data = JSONArray.parseArray(maps.get("attachment_url").toString(), AttachmentDto.class);
            attMap.put(maps.get("attachment_type").toString(), data);
        }
        JSONArray subs = jsonObject.getJSONArray("subs");
        subs.stream().forEach(x -> {
            JSONObject xObj = (JSONObject) x;
            JSONArray datas = xObj.getJSONArray("datas");
            datas.stream().forEach(y -> {
                JSONObject yObj = (JSONObject) y;
                yObj.put("value", !ValidationUtil.isEmpty(attMap.get(yObj.getString("key"))) ? attMap.get(yObj.getString("key")) : new JSONArray());
            });
        });
        return jsonObject;
    }

    public Map<String,Object> endRate(DPFilterParamDto dpFilterParamDto) {
// 1.查询条件构造未上送时间时，默认查询数据为近一个月数据
        this.setDefaultFilter(dpFilterParamDto);
        // 2.按照前端约定格式返回数据
        Map<String, Object> result = new HashMap<>();
        JYJCTypeEnum[] jyjcTypeEnums = JYJCTypeEnum.values();
        //2.1 x轴数据构造
        result.put("xdata", this.getXDataForInspectBizNumCount(jyjcTypeEnums));
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if(orgCode == null){
            return result;
        }
        List ydata = new ArrayList();
        //报检数量
        Long allCount = inspectionApplicationMapper.queryAllFlowingAndFinishedCount(orgCode, dpFilterParamDto);
        ydata.add(allCount);
        //受理数量
        Long pendingCount = inspectionApplicationMapper.queryAllPendingAndFinishedCount(orgCode, dpFilterParamDto);
        ydata.add(pendingCount);
        //检验完成
        Long finshCount = inspectionApplicationMapper.queryAllFinishedCount(orgCode, dpFilterParamDto);
        ydata.add(finshCount);
        //检验合格数量
        Long qualifiedCount = inspectionApplicationMapper.queryQualifiedCount(orgCode, dpFilterParamDto);

        // 计算比率
        double completionRate = 0.0;
        if (pendingCount != 0 && finshCount != 0) {
            completionRate = (double) finshCount / pendingCount;
        }
        double qualifiedRate = 0.0;
        if (finshCount != 0 && qualifiedCount != 0) {
            qualifiedRate = (double) qualifiedCount / finshCount;
        }
        String[] xdata = {
                "报检",
                "受理",
                "检验完成"
        };

        // 格式化比率
        DecimalFormat df = new DecimalFormat("#,##0.00");
        String formattedCompletionRate = df.format(completionRate);
        String formattedQualifiedRate = df.format(qualifiedRate);

        result.put("xdata",xdata);
        result.put("ydata",ydata);
        result.put("completionRate",formattedCompletionRate);
        result.put("qualifiedRate",formattedQualifiedRate);
        return result;
    }

    public Map<String,Object> endRateDetail(DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        List<RegionModel> regionModels = stCommonService.setRegionIfRootParent(dpFilterParamForDetailDto.getCityCode());
        List<Map<String,Object>> result =  regionModels.parallelStream().map(r -> {
            String orgCode = stCommonService.getAndSetOrgCode(r.getRegionCode()+"");
            DPFilterParamForDetailDto filterParamDto = new DPFilterParamForDetailDto();
            BeanUtils.copyProperties(dpFilterParamForDetailDto, filterParamDto);
            filterParamDto.setCityCode(r.getRegionCode()+"");
            filterParamDto.setOrgCode(orgCode);
            Map<String, Object> itemResult = endRateForDetail(filterParamDto);
            itemResult.put("xdata",r.getRegionName());
            return itemResult;
        }).collect(Collectors.toList());

        Map<String,Object> returnMap = new HashMap<>();
        List<Map<String,Object>> legendData = new ArrayList<>();
        for(int i = 0;i<2; i++){
            Map<String,Object> map = new HashMap<>();
            if(i == 0){
                map.put("dataKey","allCount");
                map.put("value","总数");
                map.put("chartType","bar");
            }else{
                map.put("dataKey","completionRate");
                map.put("value","完结率");
                map.put("chartType","line");
            }
            legendData.add(map);
        }
        returnMap.put("legendData",legendData);

        List xdata = new ArrayList();
        List allCount = new ArrayList();
        List completionRate = new ArrayList();

        for(int i = 0;i<result.size();i++){
            xdata.add(result.get(i).get("xdata"));
            allCount.add(result.get(i).get("allCount"));
            completionRate.add(result.get(i).get("completionRate"));
        }

        returnMap.put("xdata",xdata);
        returnMap.put("finishedNum",allCount);
        returnMap.put("percentData",completionRate);

        return returnMap;
    }

    private Map<String, Object> endRateForDetail(DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        Map<String,Object> result = new HashMap<>();
        //报检数量
        Long allCount = inspectionApplicationMapper.queryAllFlowingAndFinishedCountForDetail(dpFilterParamForDetailDto);
        //受理数量
        Long pendingCount = inspectionApplicationMapper.queryAllPendingAndFinishedCountForDetail(dpFilterParamForDetailDto);
        //检验完成
        Long finshCount = inspectionApplicationMapper.queryAllFinishedCountForDetail(dpFilterParamForDetailDto);

        // 计算比率
        double completionRate = 0.0;
        if (pendingCount != 0 && finshCount != 0) {
            completionRate = (double) finshCount / pendingCount;
        }
        // 格式化比率
        DecimalFormat df = new DecimalFormat("#,##0.00");
        String formattedCompletionRate = df.format(completionRate);

        result.put("allCount",allCount);
        result.put("completionRate",formattedCompletionRate);
        return result;
    }


    public Page<Map<String,Object>> endRateList(DPFilterParamForDetailDto dpFilterParamForDetailDto,Page page){
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamForDetailDto.getCityCode());
        if(orgCode == null){
            return null;
        }
        //报检数量
        Page<Map<String,Object>> result = inspectionApplicationMapper.queryAllList(page,orgCode, dpFilterParamForDetailDto);
        return result;
    }

    public Map<String,List<Map<String,Object>>> endRateSearch(DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        Map<String,List<Map<String,Object>>> enumMap = JYJCResultEnum.getSearchEnumList();
        return enumMap;
    }
    public List<Map<String, Object>> endRateType(DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        List<HashMap<String, Object>> enumList = JYJCTypeEnum.getTypeEnumList();
        List<Map<String,Object>> result = new ArrayList<>();
        Map<String,Object> map = new HashMap<>();
        map.put("title","业务类型");
        map.put("value","0");
        map.put("children",enumList);
        result.add(map);
        return result;
    }

    public List<Map<String, Object>> handleStatus() {
        FlowStatusEnum[] values = FlowStatusEnum.values();
        List<Map<String, Object>> result = new ArrayList<>();
        for (FlowStatusEnum value : values) {
            Map<String, Object> map = new HashMap<>();
            if (value.getCode() != 6617 && value.getCode() != 6621 && value.getCode() != 6610 && value.getCode() != 6615 && value.getCode() != 6612) {
                map.put("name", value.getName());
                map.put("code", value.getCode());
                result.add(map);
            }
        }
        result =  result.stream().sorted(Comparator.comparing(map -> (Integer) map.get("code"))).collect(Collectors.toList());
        return result;
    }

    public List<Map<String, Object>> getBusinessType(DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        List<HashMap<String, Object>> enumList = JYJCBusinessTypeEnum.getEnumList();
        List<Map<String, Object>> result = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        map.put("title", "all".equals(dpFilterParamForDetailDto.getBusinessTypeCode()) ? "检验检测全部业务" : "业务类型");
        map.put("value", "0");
        map.put("children", enumList);
        result.add(map);
        return result;
    }

    public Map<String,Object> getInspectDetail(DPFilterParamForDetailDto dpFilterParamForDetailDto) {
        //查询子区域
        List<RegionModel> regionModels = stCommonService.setRegionIfRootParent(dpFilterParamForDetailDto.getCityCode());

        List<Map<String, Object>> result = regionModels.parallelStream().map(r -> {
            DPFilterParamDto filterParamDto = new DPFilterParamDto();
            filterParamDto.setCityCode(r.getRegionCode().toString());
            if (null != dpFilterParamForDetailDto.getTimeSearchOne()) {
                filterParamDto.setBeginDate(dpFilterParamForDetailDto.getTimeSearchOne().getBeginDate());
                filterParamDto.setEndDate(dpFilterParamForDetailDto.getTimeSearchOne().getEndDate());
            }
            Map<String, Object> itemResult = new HashMap<>();
            itemResult.put("xdata", r.getRegionName());
            Long ydata = this.countBizFinishedNumForDetail(filterParamDto, dpFilterParamForDetailDto.getTreeValue());
            BigDecimal finishedNum = BigDecimal.valueOf(ydata);
            Long everyInFlow = this.countBizDataInFlowingForDetail(filterParamDto,dpFilterParamForDetailDto.getTreeValue());
            BigDecimal everyNum = BigDecimal.valueOf(everyInFlow);
            BigDecimal all = everyNum.add(finishedNum);
            if (all.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal percent = finishedNum.divide(all, 2, RoundingMode.HALF_UP);
                BigDecimal percentX100 = percent.multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_UP);
                itemResult.put("percentData", percentX100.toPlainString());
            } else {
                itemResult.put("percentData", "0");
            }
            itemResult.put("finishedNum", finishedNum);
            return itemResult;
        }).collect(Collectors.toList());

        Map<String,Object> returnMap = new HashMap<>();
        List<Map<String,Object>> legendData = new ArrayList<>();
        for(int i = 0;i<2; i++){
            Map<String,Object> map = new HashMap<>();
            if(i == 0){
                map.put("dataKey","finishedNum");
                map.put("value","总数");
                map.put("chartType","bar");
            }else{
                map.put("dataKey","percentData");
                map.put("value","完结率");
                map.put("chartType","line");
            }
            legendData.add(map);
        }
        returnMap.put("legendData",legendData);

        List xdata = new ArrayList();
        List finishedNum = new ArrayList();
        List percentData = new ArrayList();

        for(int i = 0;i<result.size();i++){
            xdata.add(result.get(i).get("xdata"));
            finishedNum.add(result.get(i).get("finishedNum"));
            percentData.add(result.get(i).get("percentData"));
        }

        returnMap.put("xdata",xdata);
        returnMap.put("finishedNum",finishedNum);
        returnMap.put("percentData",percentData);

        return returnMap;
    }

    private Long countBizFinishedNumForDetail(DPFilterParamDto dpFilterParamDto,String businessType) {
        // 1.统计各业务办理量注意要和x轴顺序一致
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        // 省、市、区县为按照行政区划进行编码的，公司的code为行政区划编码
        if (orgCode == null) {
            return 0L;
        }
        if(null != businessType){
            if("0".equals(businessType)){
                return inspectionApplicationMapper.countBizFinishedNumForDP(orgCode, dpFilterParamDto,null);
            }
        }
        return inspectionApplicationMapper.countBizFinishedNumForDP(orgCode, dpFilterParamDto,businessType);
    }

    private Long countBizDataInFlowingForDetail(DPFilterParamDto dpFilterParamDto,String businessType) {
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if (orgCode == null) {
            return 0L;
        }
        if(null != businessType){
            if("0".equals(businessType)){
                return inspectionApplicationMapper.countBizFinishedNumForDP(orgCode, dpFilterParamDto,null);
            }
        }
        return inspectionApplicationMapper.countAllInFlowingForDPNoFinishedBizData(orgCode, dpFilterParamDto,businessType);
    }

    public Page<Map<String, Object>> getInspectDetailList(DPFilterParamForDetailDto dpFilterParamForDetailDto, Page<Map<String, Object>> page) {
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamForDetailDto.getCityCode());
        DPFilterParamDto filterParamDto = new DPFilterParamDto();
        filterParamDto.setCityCode(dpFilterParamForDetailDto.getCityCode());
        filterParamDto.setCompanyName(dpFilterParamForDetailDto.getCompanyName());
        filterParamDto.setSuperviseUnitName(dpFilterParamForDetailDto.getSuperviseUnitName());
        if (null != dpFilterParamForDetailDto.getTimeSearchOne()) {
            filterParamDto.setBeginDate(dpFilterParamForDetailDto.getTimeSearchOne().getBeginDate());
            filterParamDto.setEndDate(dpFilterParamForDetailDto.getTimeSearchOne().getEndDate());
        }
        if(null != dpFilterParamForDetailDto.getTreeValue()){
            if("0".equals(dpFilterParamForDetailDto.getTreeValue())){
                Page<Map<String, Object>> maps = inspectionApplicationMapper.getInspectDetailList(page, orgCode, filterParamDto, null);
                return maps;
            }
        }
        Page<Map<String, Object>> maps = inspectionApplicationMapper.getInspectDetailList(page, orgCode, filterParamDto, dpFilterParamForDetailDto.getTreeValue());
        return maps;
    }


    public Page<JSONObject> equipInspectTimeCountListDetailList(DPFilterParamForDetailDto paramDto) {
        Page<JSONObject> result = new Page<>(paramDto.getCurrent(), paramDto.getSize());
        SearchRequest request = new SearchRequest();
        request.indices("idx_biz_view_jg_all");
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.trackTotalHits(true);
        BoolQueryBuilder boolMust = QueryBuilders.boolQuery();

        if (!ObjectUtils.isEmpty(paramDto.getCityCode())) {
            String orgCode = stCommonService.getAndSetOrgCode(paramDto.getCityCode());
            boolMust.must(QueryBuilders.wildcardQuery("ORG_BRANCH_CODE.keyword", QueryParser.escape(orgCode) + "*"));
        }

        if (!ObjectUtils.isEmpty(paramDto.getSuperviseUnitName())) {
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            String test = QueryParser.escape(paramDto.getSuperviseUnitName());
            query.must(QueryBuilders.matchPhraseQuery("ORG_BRANCH_NAME", "*" + test + "*"));
            boolMust.must(query);
        }

        if (!ObjectUtils.isEmpty(paramDto.getCompanyName())) {
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            String test = QueryParser.escape(paramDto.getCompanyName());
            query.must(QueryBuilders.matchPhraseQuery("USE_UNIT_NAME", "*" + test + "*"));
            boolMust.must(query);
        }

        if (!ObjectUtils.isEmpty(paramDto.getTreeValue())) {
            BoolQueryBuilder meBuilder = QueryBuilders.boolQuery();
            String test = QueryParser.escape(paramDto.getTreeValue());
            meBuilder.must(QueryBuilders.matchPhraseQuery("EQU_LIST_CODE", test));
            boolMust.must(meBuilder);
        }

        if (!ObjectUtils.isEmpty(paramDto.getEquCategoryCode())) {
            BoolQueryBuilder meBuilder = QueryBuilders.boolQuery();
            String test = QueryParser.escape(paramDto.getEquCategoryCode());
            meBuilder.must(QueryBuilders.matchPhraseQuery("EQU_CATEGORY_CODE", test));
            boolMust.must(meBuilder);
        }

        long currentDayTime = DateUtil.parse(DateUtil.today(), "yyy-MM-dd").getTime();
        long currentDayAfter30DayTime = DateUtil.offsetDay(DateUtil.parse(DateUtil.today(), "yyy-MM-dd"), 30).getTime();
        if(OVERTIME.equals(paramDto.getBusinessType())){
            // 查询下次检验日期小于当前天的设备，即为超期检验超期设备
            boolMust.must(QueryBuilders.rangeQuery("NEXT_INSPECT_DATE").lt(currentDayTime));
        }else if(TEMPORARY.equals(paramDto.getBusinessType())){
            // 且下次检验日期大于等于当天 且查询 下次检验日期 <= 当前天+30天 即为临期
            boolMust.must(QueryBuilders.rangeQuery("NEXT_INSPECT_DATE").gte(currentDayTime).lte(currentDayAfter30DayTime));
        }else{
            BoolQueryBuilder shouldBuilder = QueryBuilders.boolQuery();
            // 且下次检验日期大于等于当天 且查询 下次检验日期 <= 当前天+30天 即为临期
            shouldBuilder.should().add(QueryBuilders.rangeQuery("NEXT_INSPECT_DATE").gte(currentDayTime).lte(currentDayAfter30DayTime));
            shouldBuilder.should().add(QueryBuilders.rangeQuery("NEXT_INSPECT_DATE").lt(currentDayTime));
            boolMust.must(shouldBuilder);
        }

        BoolQueryBuilder pBuilder = QueryBuilders.boolQuery();
        String param = QueryParser.escape("true");
        pBuilder.must(QueryBuilders.matchQuery(IS_INTO_MANAGEMENT, param));
        boolMust.must(pBuilder);

        builder.query(boolMust);
        builder.sort("REC_DATE", SortOrder.DESC);
        builder.from((paramDto.getCurrent() - 1) * paramDto.getSize());
        builder.size(paramDto.getSize());
        request.source(builder);
        List<JSONObject> list = new LinkedList<>();
        long totle = 0;
        try {
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            for (SearchHit hit : response.getHits().getHits()) {
                System.out.println(hit);
                JSONObject jsonObject = (JSONObject) JSONObject.toJSON(hit);
                JSONObject dto2 = jsonObject.getJSONObject("sourceAsMap");
                if (!ValidationUtil.isEmpty(dto2.get(EQU_STATE))) {
                    Integer integer = Integer.valueOf(dto2.get(EQU_STATE).toString());
                    String status = EquimentEnum.getName.get(integer);
                    dto2.put(EQU_STATE, status);
                }
//                if(dto2.get("NEXT_INSPECT_DATE") != null){
//                    if(Long.valueOf(dto2.get("NEXT_INSPECT_DATE").toString()) < currentDayTime){
//                        dto2.put("PROBLEM_TYPE", "超期");
//                    }else{
//                        dto2.put("PROBLEM_TYPE","临期");
//                    }
//                }
                list.add(dto2);
            }
            totle = response.getInternalResponse().hits().getTotalHits().value;
            result.setRecords(list);
            result.setTotal(totle);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    public List<Map<String,Object>> equipInspectTimeCountListDetailSearch(DPFilterParamForDetailDto dpFilterParamDto) {
        List<Map<String,Object>> list = new ArrayList<>();
        for(int i = 0; i < 3; i++){
            Map<String,Object> map = new HashMap<>();
            if(i == 0){
                map.put("label","所有");
                map.put("value",ALL);
            }else if(i == 1){
                map.put("label","临期");
                map.put("value",TEMPORARY);
            }else{
                map.put("label","超期");
                map.put("value",OVERTIME);
            }
            list.add(map);
        }
        return list;
    }

    public Page<Map<String, Object>> getInspectBusinessList(DPFilterParamForDetailDto dpFilterParamForDetailDto, Page<Map<String, Object>> page) {
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamForDetailDto.getCityCode());
        DPFilterParamDto filterParamDto = new DPFilterParamDto();
        filterParamDto.setCityCode(dpFilterParamForDetailDto.getCityCode());
        filterParamDto.setCompanyName(dpFilterParamForDetailDto.getCompanyName());
        filterParamDto.setSuperviseUnitName(dpFilterParamForDetailDto.getSuperviseUnitName());
        filterParamDto.setEquListCode(dpFilterParamForDetailDto.getEquListCode());
        filterParamDto.setEquCategoryCode(dpFilterParamForDetailDto.getEquCategoryCode());
        filterParamDto.setStatus(dpFilterParamForDetailDto.getStatus());
        if (null != dpFilterParamForDetailDto.getTimeSearchOne()) {
            filterParamDto.setBeginDate(dpFilterParamForDetailDto.getTimeSearchOne().getBeginDate());
            filterParamDto.setEndDate(dpFilterParamForDetailDto.getTimeSearchOne().getEndDate());
        }
        if(null != dpFilterParamForDetailDto.getTreeValue()){
            if("0".equals(dpFilterParamForDetailDto.getTreeValue())){
                Page<Map<String, Object>> maps = inspectionApplicationMapper.getInspectBusinessList(page, orgCode, filterParamDto, null);
                return maps;
            }
        }
        Page<Map<String, Object>> maps = inspectionApplicationMapper.getInspectBusinessList(page, orgCode, filterParamDto, dpFilterParamForDetailDto.getTreeValue());
        return maps;
    }

}
