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

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Sets;
import com.yeejoin.amos.boot.biz.common.dto.CountDto;
import com.yeejoin.amos.boot.biz.common.entity.DataDictionary;
import com.yeejoin.amos.boot.biz.common.service.impl.DataDictionaryServiceImpl;
import com.yeejoin.amos.boot.module.common.api.dto.DPFilterParamDto;
import com.yeejoin.amos.boot.module.common.api.dto.DPFilterParamForDateDto;
import com.yeejoin.amos.boot.module.common.api.dto.DPFilterParamForDetailDto;
import com.yeejoin.amos.boot.module.common.api.entity.AlertRescueStatistics;
import com.yeejoin.amos.boot.module.common.api.entity.AlertUseUnitStatistics;
import com.yeejoin.amos.boot.module.statistics.api.dto.AlertUseUnitStatisticsDto;
import com.yeejoin.amos.boot.module.statistics.api.mapper.AlertRescueStatisticsMapper;
import com.yeejoin.amos.boot.module.statistics.api.mapper.AlertStatisticsMapper;
import com.yeejoin.amos.boot.module.statistics.api.mapper.AlertUseUnitStatisticsMapper;
import com.yeejoin.amos.boot.module.ymt.api.dto.AlertPaperInfoDto;
import com.yeejoin.amos.boot.module.ymt.api.enums.DispatchPaperEnums;
import com.yeejoin.amos.boot.module.ymt.api.enums.EquipmentClassifityEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.AlertCalledMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.DispatchTaskMapper;
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.springframework.stereotype.Service;
import org.typroject.tyboot.core.foundation.utils.Bean;
import org.typroject.tyboot.core.foundation.utils.DateTimeUtil;
import org.typroject.tyboot.core.foundation.utils.DateUtil;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.restful.utils.ResponseHelper;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

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

    private AlertCalledMapper alertCalledMapper;

    private AlertRescueStatisticsMapper alertRescueStatisticsMapper;

    private AlertUseUnitStatisticsMapper alertUseUnitStatisticsMapper;

    private AlertStatisticsMapper alertStatisticsMapper;

    private DispatchTaskMapper dispatchTaskMapper;

    private RestHighLevelClient restHighLevelClient;

    private StCommonServiceImpl stCommonService;

    private DataDictionaryServiceImpl dataDictionaryService;

    private static final Map<String, String> BLL_LX_LEGEND = new LinkedHashMap<>();

    static {
        BLL_LX_LEGEND.put("trapped", "困人");
        BLL_LX_LEGEND.put("complaint", "投诉");
        BLL_LX_LEGEND.put("fault", "故障");
    }

    /**
     * 电梯设备品种
     */
    private final static String ELEVATOR_EQU_DEFINE_CODES = "3410,3420,3430,3310,3320,3210,3220,3120,3130,3110";


    public YJDPStatisticsServiceImpl(AlertCalledMapper alertCalledMapper, AlertRescueStatisticsMapper alertRescueStatisticsMapper, AlertUseUnitStatisticsMapper alertUseUnitStatisticsMapper, AlertStatisticsMapper alertStatisticsMapper, DispatchTaskMapper dispatchTaskMapper, RestHighLevelClient restHighLevelClient, StCommonServiceImpl stCommonService, DataDictionaryServiceImpl dataDictionaryService) {
        this.alertCalledMapper = alertCalledMapper;
        this.alertRescueStatisticsMapper = alertRescueStatisticsMapper;
        this.alertUseUnitStatisticsMapper = alertUseUnitStatisticsMapper;
        this.alertStatisticsMapper = alertStatisticsMapper;
        this.dispatchTaskMapper = dispatchTaskMapper;
        this.restHighLevelClient = restHighLevelClient;
        this.stCommonService = stCommonService;
        this.dataDictionaryService = dataDictionaryService;
    }

    public JSONObject eventStatByDay(DPFilterParamDto dpFilterParamDto) throws Exception {
        String beginDate = DateUtil.formatDate(DateTimeUtil.addDays(new Date(), -6), DateUtil.Y_M_D);
        String endDate = DateUtil.getNow(DateUtil.Y_M_D);
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto);

        JSONObject jsonObject = new JSONObject();
        List<String> everyDay = this.getEveryDay(beginDate, endDate);
        this.buildLegendData(jsonObject);
        List<String> xdata = new ArrayList<>();
        List<Object> trapped = new ArrayList<>();
        List<Object> complaint = new ArrayList<>();
        List<Object> fault = new ArrayList<>();
        List<Map<String, Object>> maps = new ArrayList<>();
        if (orgCode != null) {
            maps = alertCalledMapper.queryNearlyList(beginDate, endDate, orgCode);
        }
        List<Map<String, Object>> finalMaps = maps;
        everyDay.forEach(day -> {
            try {
                xdata.add(DateUtil.formatDate(DateUtil.formatStringToDate(day, DateUtil.Y_M_D), "MM.dd"));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            Map<String, Object> map = finalMaps.stream().filter(x -> day.equals(x.get("day"))).collect(Collectors.toMap(
                    item -> (String) item.get("alarmType"),
                    item -> item.get("majorAlertCount")));
            trapped.add(!ValidationUtil.isEmpty(map.get("困人救援")) ? Integer.parseInt(map.get("困人救援").toString()) : 0);
            complaint.add(!ValidationUtil.isEmpty(map.get("投诉咨询")) ? Integer.parseInt(map.get("投诉咨询").toString()) : 0);
            fault.add(!ValidationUtil.isEmpty(map.get("故障维修")) ? Integer.parseInt(map.get("故障维修").toString()) : 0);
        });
        jsonObject.put("xdata", xdata);
        jsonObject.put("trapped", trapped);
        jsonObject.put("complaint", complaint);
        jsonObject.put("fault", fault);
        return jsonObject;
    }

    public JSONObject elevatorCountStat(DPFilterParamDto dpFilterParamDto) {
        List<RegionModel> regionList = stCommonService.setRegionIfRootParentAndNoAccessIf3Level(dpFilterParamDto);
        List<String> xdata = regionList.stream().map(RegionModel::getRegionName).collect(Collectors.toList());

        List<Long> ydata = new ArrayList<>();
        regionList.forEach(x -> {
            String orgCode = stCommonService.getAndSetOrgCode(x.getRegionCode().toString());
            if (!ValidationUtil.isEmpty(orgCode)) {
                ydata.add(elevatorCountByES(orgCode));
            } else {
                ydata.add(0L);
            }
        });
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("xdata", xdata);
        jsonObject.put("ydata", ydata);
        return jsonObject;
    }

    public JSONObject eventStatByLocation(DPFilterParamDto dpFilterParamDto) throws Exception {
        dpFilterParamDto.setBeginDate(DateUtil.formatDate(DateTimeUtil.getMinValueOfOneDay(DateTimeUtil.addMonths(new Date(), -1)), DateUtil.Y_M_D_HMS));
        dpFilterParamDto.setEndDate(DateUtil.formatDate(DateTimeUtil.getMaxValueOfOneDay(new Date()), DateUtil.Y_M_D_HMS));
        // 查询字典 ADDRESS id name
        List<DataDictionary> dataDictionaries = dataDictionaryService.getByType("ADDRESS");
        List<Object> xdata = dataDictionaries.stream().map(DataDictionary::getName).collect(Collectors.toList());
        List<Object> ydata;
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto);
        if (orgCode == null) {
            ydata = dataDictionaries.stream().map(d -> 0L).collect(Collectors.toList());
        } else {
            List<CountDto> maps = alertCalledMapper.queryListByLocation(orgCode, dpFilterParamDto);
            Map<String, Long> addressNumMap = maps.stream().collect(Collectors.toMap(CountDto::getKeyStr, CountDto::getLongValue));
            ydata = dataDictionaries.stream().map(d -> {
                Long num = 0L;
                // 目前USE_PLACE字段存放字典的code
                if (addressNumMap.get(d.getCode()) != null) {
                    num = addressNumMap.get(d.getCode());
                }
                // 数据库中老数据历史问题存放字典的name,兼容对老数据的统计
                if (addressNumMap.get(d.getName()) != null) {
                    num = num + addressNumMap.get(d.getName());
                }
                return num;
            }).collect(Collectors.toList());
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("xdata", xdata);
        jsonObject.put("ydata", ydata);
        return jsonObject;
    }

    public JSONObject faultCauseRatio(DPFilterParamDto dpFilterParamDto) {
        JSONObject jsonObject = new JSONObject();
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto);
        if (orgCode == null) {
            return jsonObject;
        }
        List<CountDto> maps = alertCalledMapper.faultCauseRatio(orgCode);
        List<Object> xdata = maps.stream().map(CountDto::getKeyStr).collect(Collectors.toList());
        List<Object> ydata = maps.stream().map(CountDto::getLongValue).collect(Collectors.toList());
        jsonObject.put("xdata", xdata);
        jsonObject.put("ydata", ydata);
        return jsonObject;
    }

    public List<AlertPaperInfoDto> instantAlert(DPFilterParamDto dpFilterParamDto) {
        List<String> regionCodes = new ArrayList<>();
        regionCodes.add(dpFilterParamDto.getCityCode());
        return alertCalledMapper.getAlertPaperInfoList(regionCodes, false);
    }

    public JSONObject trappedUserCount(DPFilterParamDto dpFilterParamDto) throws Exception {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("xdata", Arrays.asList("30分钟内到达次数", "超过30分钟到次数", "一级救援次数", "二级救援次数", "三级救援次数"));
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if (orgCode == null) {
            jsonObject.put("ydata", Arrays.asList(0L, 0L, 0L, 0L, 0L));
            return jsonObject;
        }
        String date = DateUtil.formatDate(DateTimeUtil.addMonths(new Date(), -1), "yyyy-MM");
        LambdaQueryWrapper<AlertRescueStatistics> lambda = new QueryWrapper<AlertRescueStatistics>().lambda();
        lambda.likeRight(AlertRescueStatistics::getSupervisoryUnitOrgCode, orgCode);
        lambda.eq(AlertRescueStatistics::getStatisticsDate, date);
        List<AlertRescueStatistics> alertRescueStatistics = alertRescueStatisticsMapper.selectList(lambda);
        List<Long> ydata = new ArrayList<>();
        ydata.add(alertRescueStatistics.stream().mapToLong(AlertRescueStatistics::getLessNum).sum());
        ydata.add(alertRescueStatistics.stream().mapToLong(AlertRescueStatistics::getGreaterNum).sum());
        ydata.add(alertRescueStatistics.stream().mapToLong(AlertRescueStatistics::getLevelOne).sum());
        ydata.add(alertRescueStatistics.stream().mapToLong(AlertRescueStatistics::getLevelTwo).sum());
        ydata.add(alertRescueStatistics.stream().mapToLong(AlertRescueStatistics::getLevelThree).sum());
        jsonObject.put("ydata", ydata);
        return jsonObject;
    }

    public List<AlertUseUnitStatisticsDto> trappedUserHighCompanyCount(DPFilterParamDto dpFilterParamDto) throws Exception {
        String date = DateUtil.formatDate(DateTimeUtil.addMonths(new Date(), -1), "yyyy-MM");
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto);
        if (orgCode == null) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<AlertUseUnitStatistics> lambda = new QueryWrapper<AlertUseUnitStatistics>().lambda();
        lambda.likeRight(AlertUseUnitStatistics::getSupervisoryUnitOrgCode, orgCode);
        lambda.eq(AlertUseUnitStatistics::getStatisticsDate, date);
        lambda.isNotNull(AlertUseUnitStatistics::getUseUnitCode);
        List<AlertUseUnitStatistics> alertUseUnitStatistics = alertUseUnitStatisticsMapper.selectList(lambda);
        return Bean.toModels(alertUseUnitStatistics, AlertUseUnitStatisticsDto.class);
    }

    public List<Map<String, Object>> rankUnitByRescueTime(DPFilterParamDto dpFilterParamDto) {
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto);
        if (orgCode == null) {
            return new ArrayList<>();
        }
        List<Map<String, Object>> maps = dispatchTaskMapper.rankUnitByRescueTime(orgCode);
        maps.forEach(x -> {
            String avgTime = "";
            Long seconds = Long.valueOf(x.get("avgTime").toString());
            long days = TimeUnit.SECONDS.toDays(seconds);
            long hours = TimeUnit.SECONDS.toHours(seconds) - TimeUnit.DAYS.toHours(days);
            long minutes = TimeUnit.SECONDS.toMinutes(seconds) - TimeUnit.HOURS.toMinutes(hours) - TimeUnit.SECONDS.toMinutes(days);
            long sec = seconds - (TimeUnit.DAYS.toSeconds(days) + TimeUnit.HOURS.toSeconds(hours) + TimeUnit.MINUTES.toSeconds(minutes));
            if (days > 0) {
                avgTime = avgTime + days + "天";
            }
            if (hours > 0) {
                avgTime = avgTime + hours + "小时";
            }
            if (minutes > 0) {
                avgTime = avgTime + minutes + "分钟";
            }
            if (sec > 0) {
                avgTime = avgTime + sec + "秒";
            }
            x.put("avgTime", avgTime);
        });
        return maps;
    }

    public JSONObject regionEventRank(DPFilterParamDto dpFilterParamDto) {
        JSONObject jsonObject = new JSONObject();
        String orgCodeParent = stCommonService.getAndSetOrgCode(dpFilterParamDto.getCityCode());
        if (orgCodeParent == null) {
            return jsonObject;
        }
        List<RegionModel> childRegion = stCommonService.setRegionIfRootParentAndNoAccessIf3Level(dpFilterParamDto);
        Map<String, Long> map = new HashMap<>();
        childRegion.forEach(x -> {
            String orgCode = stCommonService.getAndSetOrgCode(x.getRegionCode().toString());
            if (ValidationUtil.isEmpty(orgCode)) {
                map.put(x.getRegionName(), 0L);
            } else {
                Long num = alertStatisticsMapper.countEmergencyEventsByOrgCodeAndDate(orgCode, dpFilterParamDto);
                map.put(x.getRegionName(), num);
            }
        });
        List<String> xdata = new ArrayList<>(map.keySet());
        List<Long> ydata = new ArrayList<>();
        xdata.sort(Comparator.comparingLong(map::get).reversed());
        xdata.forEach(x -> ydata.add(map.get(x)));
        jsonObject.put("xdata", xdata);
        jsonObject.put("ydata", ydata);
        return jsonObject;
    }


    /**
     * 获取两个时间段之间的每一天
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 结果
     */
    public List<String> getEveryDay(String startTime, String endTime) {
        List<String> dateList = new ArrayList<>();
        LocalDate startDate = LocalDate.parse(startTime);
        LocalDate endDate = LocalDate.parse(endTime);
        long numOfDays = ChronoUnit.DAYS.between(startDate, endDate);
        for (int i = 0; i <= numOfDays; i++) {
            LocalDate currentDate = startDate.plusDays(i);
            String format = currentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            dateList.add(format);
        }
        return dateList;
    }

    public List<Map<String, Object>> getCenterMapCountDataForOverview(DPFilterParamDto dpFilterParamDto) {
        return stCommonService.setRegionIfRootParent(dpFilterParamDto).stream().map(r -> {
            DPFilterParamDto filterParamDto = new DPFilterParamDto();
            filterParamDto.setCityCode(r.getRegionCode().toString());
            String orgCode = stCommonService.getAndSetOrgCode(filterParamDto);
            Map<String, Object> itemResult = new HashMap<>();
            if (StringUtils.isNotEmpty(orgCode)) {
                this.setDefaultFilter(filterParamDto);
                itemResult = getCenterMapOverviewData(orgCode, filterParamDto);
            }
            itemResult.put("regionCode", r.getRegionCode());
            itemResult.put("regionName", r.getRegionName());
            return itemResult;
        }).collect(Collectors.toList());
    }


    private void buildLegendData(JSONObject jsonObject) {
        JSONArray jsonArray = new JSONArray();
        BLL_LX_LEGEND.forEach((k, v) -> {
            JSONObject item = new JSONObject();
            item.put("dataKey", k);
            item.put("value", v);
            jsonArray.add(item);
        });
        jsonObject.put("legendData", jsonArray);
    }

    private Map<String, Object> getCenterMapOverviewData(String orgCode, DPFilterParamDto filterParamDto) {
        Map<String, Object> result = new HashMap<>();
        // 统计完成的事件包括困人、故障、投诉咨询
        List<CountDto> countDtos = alertStatisticsMapper.countEmergencyEventsByOrgCodeAndDate2(orgCode, filterParamDto);
        Map<String, Long> alertTypeNumMap = countDtos.stream().collect(Collectors.toMap(CountDto::getKeyStr, CountDto::getLongValue));
        Map<String, Long> equDefineNumMap = staticsElevatorByEquDefine(filterParamDto.getCityCode());
        // 电梯总量(台)
        result.put("dtCount", equDefineNumMap.values().stream().mapToLong(e -> e).sum());
        // 曳引驱动乘客电梯(台)
        result.put("zyqdcjdtCount", equDefineNumMap.getOrDefault("3110", 0L));
        // 曳引驱动载货电梯(台)
        result.put("zyqdzhdtCount", equDefineNumMap.getOrDefault("3120", 0L));
        // 强制驱动载货电梯(台)
        result.put("qzqdzgdtCount", equDefineNumMap.getOrDefault("3130", 0L));
        // 液压乘客电梯(台)
        result.put("yackdtount", equDefineNumMap.getOrDefault("3210", 0L));
        // 液压载货电梯(台)
        result.put("yyzhdtCount", equDefineNumMap.getOrDefault("3220", 0L));
        // 自动扶梯(台)
        result.put("zdftCount", equDefineNumMap.getOrDefault("3310", 0L));
        // 自动人行道(台)
        result.put("zdrxdCount", equDefineNumMap.getOrDefault("3320", 0L));
        // 防爆电梯(台)
        result.put("fbdtCount", equDefineNumMap.getOrDefault("3410", 0L));
        // 消防员电梯(台)
        result.put("xfydtCount", equDefineNumMap.getOrDefault("3420", 0L));
        // 杂物电梯(台)
        result.put("zhdtCount", equDefineNumMap.getOrDefault("3430", 0L));
        // 应急事件(起) = 困人救援事件(起) + 故障维修(起) + 投诉咨询(起)
        result.put("alarmCount", alertTypeNumMap.getOrDefault(DispatchPaperEnums.KRJY.getId(), 0L) +
                alertTypeNumMap.getOrDefault(DispatchPaperEnums.GZWX.getId(), 0L) +
                alertTypeNumMap.getOrDefault(DispatchPaperEnums.TSZX.getId(), 0L));
        // 困人救援事件(起)
        result.put("krjysjCount", alertTypeNumMap.getOrDefault(DispatchPaperEnums.KRJY.getId(), 0L));
        // 故障维修(起)
        result.put("gzwxCount", alertTypeNumMap.getOrDefault(DispatchPaperEnums.GZWX.getId(), 0L));
        // 投诉咨询(起)
        result.put("tszxCount", alertTypeNumMap.getOrDefault(DispatchPaperEnums.TSZX.getId(), 0L));
        // 解救被困乘客数(人)
        result.put("jjbkcksCount", alertStatisticsMapper.countRescuedPersonNum(orgCode, filterParamDto));
        return result;
    }


    public Map<String, Object> getCenterMapCountDataForGlobal(DPFilterParamDto dpFilterParamDto) {
        // this.setDefaultFilter(dpFilterParamDto);
        String orgCode = stCommonService.getAndSetOrgCode(dpFilterParamDto);
        if (StringUtils.isNotEmpty(orgCode)) {
            return this.getCenterMapOverviewData(orgCode, dpFilterParamDto);
        }
        return new HashMap<>();
    }

    private void setDefaultFilter(DPFilterParamDto dpFilterParamDto) {
        if (StringUtils.isEmpty(dpFilterParamDto.getBeginDate())) {
            dpFilterParamDto.setBeginDate(cn.hutool.core.date.DateUtil.offsetDay(new Date(), -30).toString("yyyy-MM-dd HH:mm:ss"));
        }
        if (StringUtils.isEmpty(dpFilterParamDto.getEndDate())) {
            dpFilterParamDto.setEndDate(cn.hutool.core.date.DateUtil.now());
        }
    }

    private long elevatorCountByES(String orgCode) {
        long num = 0L;
        CountRequest request = new CountRequest();
        request.indices("idx_biz_view_jg_all");
        BoolQueryBuilder boolMust = QueryBuilders.boolQuery();
        // 按照管辖机构区域信息模糊查询
        boolMust.must(QueryBuilders.wildcardQuery("ORG_BRANCH_CODE.keyword", QueryParser.escape(orgCode) + "*"));
        // 只统计已纳管设备
        boolMust.must(QueryBuilders.termQuery("IS_INTO_MANAGEMENT", Boolean.TRUE));
        // 设备种类是电梯的
        boolMust.must(QueryBuilders.termQuery("EQU_LIST_CODE", EquipmentClassifityEnum.DT.getCode()));
        request.query(boolMust);
        try {
            CountResponse response = restHighLevelClient.count(request, RequestOptions.DEFAULT);
            num = response.getCount();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return num;
    }

    private Map<String, Long> staticsElevatorByEquDefine(String regionCode) {
        String orgCode = stCommonService.getAndSetOrgCode(regionCode);
        Map<String, Long> countMap = new HashMap<>();
        SearchRequest request = new SearchRequest();
        request.indices("idx_biz_view_jg_all");
        BoolQueryBuilder boolMust = QueryBuilders.boolQuery();
        // 按照管辖机构区域信息模糊查询
        boolMust.must(QueryBuilders.wildcardQuery("ORG_BRANCH_CODE.keyword", QueryParser.escape(orgCode) + "*"));
        // 只统计已纳管设备
        boolMust.must(QueryBuilders.termQuery("IS_INTO_MANAGEMENT", Boolean.TRUE));
        // 且设备品种3级,按照真实的过滤，防止有脏数据
        boolMust.must(QueryBuilders.termsQuery("EQU_DEFINE_CODE.keyword", ELEVATOR_EQU_DEFINE_CODES.split(",")));
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(boolMust);
        // 原因默认10个，由于业务最多有10个，担心有脏数据，故多查询
        TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("count_by_equ_define_code").field("EQU_DEFINE_CODE.keyword").size(20);
        builder.aggregation(aggregationBuilder);
        request.source(builder);
        try {
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            Terms terms = response.getAggregations().get("count_by_equ_define_code");
            for (Terms.Bucket bucket : terms.getBuckets()) {
                countMap.put(bucket.getKeyAsString(), bucket.getDocCount());
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return countMap;
    }

    public JSONObject alertRecordBarChartForDP(DPFilterParamForDetailDto recordFilterVo) {

        JSONObject res = new JSONObject();
        JSONArray legendData = new JSONArray();

        legendData.add(createLegendData());

        List<RegionModel> regionList = stCommonService.setRegionIfRootParentAndNoAccessIf3Level(ValidationUtil.isEmpty(recordFilterVo.getCityCode()) ? "610000" : recordFilterVo.getCityCode());

        // 获取区域名称并过滤
        List<String> xData = regionList.stream()
                .map(RegionModel::getRegionName)
                .filter(regionName -> !"西咸新区".equals(regionName))
                .collect(Collectors.toList());

        List<Long> alertRecordTotal = regionList.stream().map(region -> {
            String orgCode = stCommonService.getAndSetOrgCode(String.valueOf(region.getRegionCode()));
            if (ValidationUtil.isEmpty(orgCode)) {
                return 0L;
            }
            if (recordFilterVo.getTimeSearchOne() == null) {
                recordFilterVo.setTimeSearchOne(new DPFilterParamForDateDto());
            }
            if (!ValidationUtil.isEmpty(recordFilterVo.getTreeValue())){
                recordFilterVo.setAlertTypeCode(recordFilterVo.getTreeValue());
            }
            return alertStatisticsMapper.countAlertRecordByOrgCodeAndDate(orgCode, recordFilterVo);
        }).collect(Collectors.toList());
        res.put("legendData", legendData);
        res.put("xdata", xData);
        res.put("alertRecordTotal", alertRecordTotal);
        return res;
    }

    private JSONObject createLegendData() {
        JSONObject legendSubData = new JSONObject();
        legendSubData.put("dataKey", "alertRecordTotal");
        legendSubData.put("value", "应急事件总数");
        legendSubData.put("chartType", "bar");
        return legendSubData;
    }


    public JSONObject alertOperations() {
        Collection<DataDictionary> JQLXList = dataDictionaryService.list(
                new QueryWrapper<DataDictionary>()
                        .eq("type", "JQLX")
                        .eq("is_delete", false)
                        .orderByAsc("sort_num")
        );
        List<JSONObject> subList = JQLXList.stream()
                .map(jq -> {
                    JSONObject obj = new JSONObject();
                    obj.put("value", jq.getCode());
                    obj.put("title", jq.getName());
                    return obj;
                }).collect(Collectors.toList());

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("title", "应急事件");
        jsonObject.put("value", "yjsj");
        jsonObject.put("children", subList);
        return jsonObject;
    }

    public ResponseModel<IPage<Map<String, Object>>> alertRecordTableForDP(DPFilterParamForDetailDto recordFilterVo) {
        String orgCode = stCommonService.getAndSetOrgCode(recordFilterVo.getCityCode());
        if (orgCode == null) {
            return ResponseHelper.buildResponse(new Page<>());
        }
        if (!ValidationUtil.isEmpty(recordFilterVo.getTreeValue())){
            recordFilterVo.setAlertTypeCode(recordFilterVo.getTreeValue());
        }
        Page<Map<String, Object>> mapPage = alertStatisticsMapper.alertRecordForPage(new Page<>(recordFilterVo.getCurrent(), recordFilterVo.getSize()),recordFilterVo,orgCode);
        return ResponseHelper.buildResponse(mapPage);
    }

    public ResponseModel<JSONObject> alertUnitBarChartForDP(DPFilterParamForDetailDto detailDto){
        JSONObject res = new JSONObject();
        JSONArray legendData = new JSONArray();
        legendData.add(new JSONObject()
                .fluentPut("dataKey", "alertUnitTotal")
                .fluentPut("value", "故障高发企业总数")
                .fluentPut("chartType", "bar"));

        List<RegionModel> regionList = stCommonService.setRegionIfRootParentAndNoAccessIf3Level(ValidationUtil.isEmpty(detailDto.getCityCode()) ? "610000" : detailDto.getCityCode());
        List<String> xData = regionList.stream()
                .map(RegionModel::getRegionName)
                .filter(regionName -> !"西咸新区".equals(regionName))
                .collect(Collectors.toList());
        List<? extends Number> alertUnitTotal = regionList.stream()
                .map(region -> {
                    String orgCode = stCommonService.getAndSetOrgCode(String.valueOf(region.getRegionCode()));
                    if (ValidationUtil.isEmpty(orgCode)) {
                        return 0L;
                    }
                    return alertUseUnitStatisticsMapper.selectCount(new QueryWrapper<AlertUseUnitStatistics>().lambda()
                            .likeRight(AlertUseUnitStatistics::getSupervisoryUnitOrgCode, orgCode)
                            .isNotNull(AlertUseUnitStatistics::getUseUnitCode));
                }).collect(Collectors.toList());
        res.put("legendData", legendData);
        res.put("xdata", xData);
        res.put("alertUnitTotal", alertUnitTotal);
        return ResponseHelper.buildResponse(res);
    }

    public ResponseModel<IPage<AlertUseUnitStatistics>> alertUseUnitTableForDP(DPFilterParamForDetailDto detailDto){
        Page<AlertUseUnitStatistics> page = new Page<>();
        page.setCurrent(detailDto.getCurrent());
        page.setSize(detailDto.getSize());

        String orgCode = stCommonService.getAndSetOrgCode(ValidationUtil.isEmpty(detailDto.getCityCode()) ? "610000" : detailDto.getCityCode());
        if (orgCode == null) {
            return ResponseHelper.buildResponse(page);
        }

        LambdaQueryWrapper<AlertUseUnitStatistics> lambda = new QueryWrapper<AlertUseUnitStatistics>().lambda();

        lambda.isNotNull(AlertUseUnitStatistics::getUseUnitCode);
        // 地市搜索
        if (!ValidationUtil.isEmpty(detailDto.getRegionName())) {
            List<RegionModel> regionList = stCommonService.setRegionIfRootParentAndNoAccessIf3Level(
                    ValidationUtil.isEmpty(detailDto.getCityCode()) ? "610000" : detailDto.getCityCode()
            );
            RegionModel matchedRegion = regionList.stream()
                    .filter(region -> detailDto.getRegionName().equals(region.getRegionName()))
                    .findFirst()
                    .orElseThrow(() -> new IllegalArgumentException("Region not found"));
            String cityOrgCode = stCommonService.getAndSetOrgCode(String.valueOf(matchedRegion.getRegionCode()));
            lambda.likeRight(AlertUseUnitStatistics::getSupervisoryUnitOrgCode, cityOrgCode);
        }else {
            lambda.likeRight(AlertUseUnitStatistics::getSupervisoryUnitOrgCode, orgCode);
        }

        // 使用单位
        if (!ValidationUtil.isEmpty(detailDto.getCompanyName())){
            lambda.like(AlertUseUnitStatistics::getUseUnit, detailDto.getCompanyName().trim());
        }
        // 维保单位
        if (!ValidationUtil.isEmpty(detailDto.getMaintenanceCompanyName())){
            lambda.like(AlertUseUnitStatistics::getMaintenanceUnit, detailDto.getMaintenanceCompanyName().trim());
        }
        IPage<AlertUseUnitStatistics> alertUseUnitStatistics = alertUseUnitStatisticsMapper.selectPage(page, lambda);
        return ResponseHelper.buildResponse(alertUseUnitStatistics);
    }

    public List<JSONObject> getKeyPositionMonitor(DPFilterParamForDetailDto filterParamDto) {
        String orgCode = stCommonService.getAndSetOrgCode(filterParamDto.getCityCode());
        return getKeyPositionMonitorByES(orgCode, filterParamDto);
    }

    private List<JSONObject> getKeyPositionMonitorByES(String orgCode, DPFilterParamForDetailDto filterParamDto) {
        SearchRequest request = new SearchRequest();
        request.indices("idx_biz_view_jg_all");
        BoolQueryBuilder boolMust = QueryBuilders.boolQuery();
        // 按照管辖机构区域信息模糊查询
        boolMust.must(QueryBuilders.wildcardQuery("ORG_BRANCH_CODE.keyword", QueryParser.escape(orgCode) + "*"));
        // 只统计已纳管设备
        boolMust.must(QueryBuilders.termQuery("IS_INTO_MANAGEMENT", Boolean.TRUE));
        // 根据设备种类查询重点监控单位
        boolMust.must(QueryBuilders.termQuery("EQU_LIST_CODE", filterParamDto.getEquListCode()));
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(boolMust);
        request.source(builder);
        List<JSONObject> list = null;
        Set<String> useUnitCreditCodeSet = Sets.newHashSet();
        try {
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            for (SearchHit hit : response.getHits().getHits()) {
                JSONObject jsonObject = (JSONObject) JSONObject.toJSON(hit);
                JSONObject source = jsonObject.getJSONObject("sourceAsMap");
                useUnitCreditCodeSet.add(source.getString("USE_UNIT_CREDIT_CODE"));
            }
            if (!ValidationUtil.isEmpty(useUnitCreditCodeSet)) {
                list = alertStatisticsMapper.getUseUnitByCreditCode(useUnitCreditCodeSet);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return list;
    }
}
