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

import com.yeejoin.amos.boot.module.common.api.constant.TZSCommonConstant;
import com.yeejoin.amos.boot.module.common.api.dto.CylinderFillingRecordStatisticsDto;
import com.yeejoin.amos.boot.module.common.api.enums.ReginStepEnum;
import com.yeejoin.amos.boot.module.ymt.api.dto.TzBaseEnterpriseInfoDto;
import com.yeejoin.amos.boot.module.ymt.api.mapper.TzBaseEnterpriseInfoMapper;
import com.yeejoin.amos.boot.module.ymt.flc.api.mapper.CylinderAreaDataMapper;
import com.yeejoin.amos.boot.module.ymt.flc.api.mapper.CylinderInfoMapper;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.RegionModel;
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.index.query.QueryBuilders;
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.springframework.util.ObjectUtils;

import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

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


    private RestHighLevelClient restHighLevelClient;


    private TzBaseEnterpriseInfoMapper baseEnterpriseInfoMapper;

    private CylinderAreaDataMapper cylinderAreaDataMapper;

    private CylinderInfoMapper cylinderInfoMapper;

    public CylinderDPStatisticsServiceImpl(RestHighLevelClient restHighLevelClient, TzBaseEnterpriseInfoMapper baseEnterpriseInfoMapper, CylinderAreaDataMapper cylinderAreaDataMapper, CylinderInfoMapper cylinderInfoMapper) {
        this.restHighLevelClient = restHighLevelClient;
        this.baseEnterpriseInfoMapper = baseEnterpriseInfoMapper;
        this.cylinderAreaDataMapper = cylinderAreaDataMapper;
        this.cylinderInfoMapper = cylinderInfoMapper;
    }


    public List<Map<String, Object>> getCylinderStatisticsData(String regionCode) throws IOException {
        // 构建搜索请求
        CompanyModel result = Privilege.companyClient.queryByCompanyCode(regionCode).getResult();
        String orgCode = result.getOrgCode();
        SearchRequest searchRequest = new SearchRequest("idx_biz_view_jg_all");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        // 构建查询条件
        searchSourceBuilder.query(
                QueryBuilders.boolQuery()
                        .must(QueryBuilders.termQuery("EQU_CATEGORY_CODE", "2300"))
                        .must(QueryBuilders.matchPhraseQuery("ORG_BRANCH_CODE", orgCode))
        );

        TermsAggregationBuilder aggregation = AggregationBuilders.terms("USE_UNIT_CREDIT_CODE").field("USE_UNIT_CREDIT_CODE.keyword").size(10);

        searchSourceBuilder.aggregation(aggregation);
        searchRequest.source(searchSourceBuilder);

        // 执行搜索并获取响应
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        // 处理聚合结果
        // 这里只是打印出聚合的名称和桶的数量，你需要根据自己的需求来处理这些数据
        Terms terms = searchResponse.getAggregations().get("USE_UNIT_CREDIT_CODE");
        List<Map<String, Object>> dataList = new ArrayList<>();
        List<String> keys = new ArrayList<>();
        for (Terms.Bucket bucket : terms.getBuckets()) {
            Map<String, Object> item = new HashMap<>();
            item.put("count", bucket.getDocCount());
            item.put("key", bucket.getKeyAsString());
            dataList.add(item);
            keys.add(bucket.getKeyAsString());
        }

        List<TzBaseEnterpriseInfoDto> tzBaseEnterpriseInfoDtos = baseEnterpriseInfoMapper.queryByUseCode(keys);
        Map<String, TzBaseEnterpriseInfoDto> collect = tzBaseEnterpriseInfoDtos.stream().collect(Collectors.toMap(TzBaseEnterpriseInfoDto::getUseCode, f -> f));
        for (Map<String, Object> item : dataList) {
            Object key = item.get("key");
            if (collect.containsKey(key)) {
                item.put("name", collect.get(key).getUseUnit());
                item.put("city", collect.get(key).getCity());
                item.put("province", collect.get(key).getProvince());
                item.put("district", collect.get(key).getDistrict());
            }
        }
        return dataList;
    }


    public Map<String, Object> getCylinderStatisticsDataByCity(String regionCode) throws Exception {
        // 构建搜索请求
        List<RegionModel> regionList = this.setRegionIfRootParent(regionCode);
        List<String> companyCode = regionList.stream().map(r -> r.getRegionCode().toString()).collect(Collectors.toList());
        List<CompanyModel> companyList = Privilege.companyClient.queryListByCompanyCode(String.join(",", companyCode)).getResult();
        Map<String, RegionModel> regionMap = regionList.stream().collect(Collectors.toMap(r -> r.getRegionCode().toString(), r -> r));
        List<Map<String, Object>> legendData = new ArrayList<>();
        List<String> xdata = new ArrayList<>();
        List<String> qiping = new ArrayList<>();
        List<String> qizhan = new ArrayList<>();

        long maxValue = 0;

        for (CompanyModel comapany : companyList) {
            String orgCode = comapany.getOrgCode();
            xdata.add(regionMap.get(comapany.getCompanyCode()).getRegionName());
            SearchRequest searchRequest = new SearchRequest("idx_biz_view_jg_all");
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

            // 构建查询条件
            searchSourceBuilder.query(
                    QueryBuilders.boolQuery()
                            .must(QueryBuilders.termQuery("EQU_CATEGORY_CODE", "2300"))
                            .must(QueryBuilders.matchPhraseQuery("ORG_BRANCH_CODE", orgCode))
            );

            TermsAggregationBuilder aggregation = AggregationBuilders.terms("ORG_BRANCH_CODE").field("ORG_BRANCH_CODE.keyword").size(10);

            searchSourceBuilder.aggregation(aggregation);
            searchRequest.source(searchSourceBuilder);

            // 执行搜索并获取响应
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            // 处理聚合结果
            // 这里只是打印出聚合的名称和桶的数量，你需要根据自己的需求来处理这些数据
            Terms terms = searchResponse.getAggregations().get("ORG_BRANCH_CODE");
            if (!ObjectUtils.isEmpty(terms.getBuckets())) {
                if (terms.getBuckets().get(0).getDocCount() > maxValue) {
                    maxValue = terms.getBuckets().get(0).getDocCount();
                }
                qiping.add(terms.getBuckets().get(0).getDocCount() + "");
            } else {
                qiping.add("0");
            }
        }

        if (maxValue > 100000) {
            for (int i = 0; i < qiping.size(); i++) {
                qiping.set(i, String.format("%.4f", Long.parseLong(qiping.get(i)) / 10000.0000) + "");
            }
        }

        List<String> orgCodes = companyList.stream().map(c -> c.getOrgCode()).collect(Collectors.toList());
        List<Map<String, Object>> qizhanMap = cylinderAreaDataMapper.getQiZhanStatisticsDataByCity(orgCodes);
        Map<Object, Object> collect = qizhanMap.stream().collect(Collectors.toMap(m -> ((Map) m).get("orgCode"), m -> ((Map) m).get("unitCount")));
        for (CompanyModel comapany : companyList) {
            String orgCode = comapany.getOrgCode();
            if (collect.containsKey(orgCode)) {
                qizhan.add(collect.get(orgCode).toString());
            } else {
                qizhan.add("0");
            }
        }

        Map<String, Object> qiLegend = new HashMap<>();
        if (maxValue > 100000) {
            qiLegend.put("value", "气瓶数量(万)");
            qiLegend.put("dataKey", "qiping");
        } else {
            qiLegend.put("value", "气瓶数量");
            qiLegend.put("dataKey", "qiping");
        }

        Map<String, Object> zhanLegend = new HashMap<>();
        zhanLegend.put("value", "气站数量");
        zhanLegend.put("dataKey", "qizhan");

        legendData.add(qiLegend);
        legendData.add(zhanLegend);

        Map<String, Object> result = new HashMap<>();
        result.put("qizhan", qizhan);
        result.put("qiping", qiping);
        result.put("xdata", xdata);
        result.put("legendData", legendData);
        return result;
    }

    private List<RegionModel> setRegionIfRootParent(String regionCode) throws Exception {
        List<RegionModel> regionList = Systemctl.regionClient.queryByParentRegionCode(Integer.parseInt(regionCode)).getResult();
        // 陕西省时需要在地图返回独立的地级市:韩城、杨凌、西咸
        if (regionCode.equals(TZSCommonConstant.SHAN_XI_REGION_CODE)) {
            List<RegionModel> independentRegions = ReginStepEnum.enum2RegionList("map");
            regionList.addAll(independentRegions);
        }
        return regionList;
    }

    public Map<String, Object> getCylinderStatisticsDataByCityForTotal(String regionCode) throws IOException {
        // 构建搜索请求
        CompanyModel comapany = Privilege.companyClient.queryByCompanyCode(regionCode).getResult();
        String orgCode = comapany.getOrgCode();
        SearchRequest searchRequest = new SearchRequest("idx_biz_view_jg_all");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        long qiping = 0;
        // 构建查询条件
        searchSourceBuilder.query(
                QueryBuilders.boolQuery()
                        .must(QueryBuilders.termQuery("EQU_CATEGORY_CODE", "2300"))
                        .must(QueryBuilders.matchPhraseQuery("ORG_BRANCH_CODE", orgCode))
        );

        TermsAggregationBuilder aggregation = AggregationBuilders.terms("ORG_BRANCH_CODE").field("ORG_BRANCH_CODE.keyword").size(10); // 注意：.keyword后缀可能根据你的字段映射而有所不同

        searchSourceBuilder.aggregation(aggregation);
        searchRequest.source(searchSourceBuilder);

        // 执行搜索并获取响应
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        // 处理聚合结果
        // 这里只是打印出聚合的名称和桶的数量，你需要根据自己的需求来处理这些数据
        Terms terms = searchResponse.getAggregations().get("ORG_BRANCH_CODE");
        if (!ObjectUtils.isEmpty(terms.getBuckets())) {
            qiping = terms.getBuckets().get(0).getDocCount();
        } else {
            qiping = 0;
        }

        List<String> orgCodes = new ArrayList<>();
        orgCodes.add(orgCode);
        List<Map<String, Object>> qizhanMap = cylinderAreaDataMapper.getQiZhanStatisticsDataByCity(orgCodes);
        String unitNumber = "0";
        if (!ObjectUtils.isEmpty(qizhanMap)) {
            unitNumber = qizhanMap.get(0).get("unitCount").toString();
        }

        Map<String, Object> result = new HashMap<>();
        result.put("cylindersCount", qiping);
        result.put("stationCount", unitNumber);
        result.put("operatorCount", cylinderAreaDataMapper.getOpertorStatisticsDataByCity(orgCodes));
        return result;
    }

    public List<Map<String, Object>> getCylinderStatisticsDataByCityForMap(String regionCode) throws Exception {
        // 构建搜索请求
        List<RegionModel> regionList = this.setRegionIfRootParent(regionCode);
        List<String> companyCode = regionList.stream().map(r -> r.getRegionCode().toString()).collect(Collectors.toList());
        List<CompanyModel> companyList = Privilege.companyClient.queryListByCompanyCode(String.join(",", companyCode)).getResult();
        Map<String, RegionModel> regionMap = regionList.stream().collect(Collectors.toMap(r -> r.getRegionCode().toString(), r -> r));
        List<Map<String, Object>> list = new ArrayList<>();
        if (ObjectUtils.isEmpty(companyList)) {
            return new ArrayList<>();
        }
        List<String> orgCodes = companyList.stream().map(CompanyModel::getOrgCode).collect(Collectors.toList());
        List<Map<String, Object>> qizhanMap = cylinderAreaDataMapper.getQiZhanStatisticsDataByCity(orgCodes);
        Map<Object, Object> collect = qizhanMap.stream().collect(Collectors.toMap(m -> ((Map) m).get("orgCode"), m -> ((Map) m).get("unitCount")));

        for (CompanyModel company : companyList) {
            String orgCode = company.getOrgCode();
            SearchRequest searchRequest = new SearchRequest("idx_biz_view_jg_all");
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            long qiping = 0;
            // 构建查询条件
            searchSourceBuilder.query(
                    QueryBuilders.boolQuery()
                            .must(QueryBuilders.termQuery("EQU_CATEGORY_CODE", "2300"))
                            .must(QueryBuilders.matchPhraseQuery("ORG_BRANCH_CODE", orgCode))
            );

            TermsAggregationBuilder aggregation = AggregationBuilders.terms("ORG_BRANCH_CODE").field("ORG_BRANCH_CODE.keyword").size(10);

            searchSourceBuilder.aggregation(aggregation);
            searchRequest.source(searchSourceBuilder);

            // 执行搜索并获取响应
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            // 处理聚合结果
            // 这里只是打印出聚合的名称和桶的数量，你需要根据自己的需求来处理这些数据
            Terms terms = searchResponse.getAggregations().get("ORG_BRANCH_CODE");
            if (!ObjectUtils.isEmpty(terms.getBuckets())) {
                qiping = terms.getBuckets().get(0).getDocCount();
            } else {
                qiping = 0;
            }

            String unitNumber = "0";
            if (!ObjectUtils.isEmpty(collect) && collect.containsKey("orgCode")) {
                unitNumber = collect.get("orgCode").toString();
            }

            Map<String, Object> result = new HashMap<>();

            RegionModel region = regionMap.get(company.getCompanyCode());
            result.put("regionAddress", company.getAddress());
            result.put("regionCode", company.getCompanyCode());
            result.put("regionName", region.getRegionName());
            result.put("longitude", company.getLongitude());
            result.put("latitude", company.getLatitude());
            result.put("stationCount", unitNumber);
            result.put("cylindersCount", qiping);
            result.put("operatorCount", 0);

            list.add(result);
        }
        return list;
    }

    public List<CylinderFillingRecordStatisticsDto> fillingTimesAndQuantity(String reginCode) {
        String orgCode = null;
        CompanyModel result = Privilege.companyClient.queryByCompanyCode(reginCode).getResult();
        orgCode = result.getOrgCode();

        List<String> times = new ArrayList<>();
        for (int i = 0; i < 30; i++) {
            times.add(LocalDate.now().minusDays(i).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        }
        List<CylinderFillingRecordStatisticsDto> fillingRecord = cylinderInfoMapper.queryFillingRecordByOrgCode(orgCode, LocalDate.now().minusDays(29).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        List<CylinderFillingRecordStatisticsDto> offloading = cylinderInfoMapper.queryoffloadingByOrgCode(orgCode, LocalDate.now().minusDays(29).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        if (fillingRecord == null) {
            fillingRecord = new ArrayList<>(0);
        }
        if (offloading == null) {
            offloading = new ArrayList<>(0);
        }
        Map<String, String> fillingRecordMap = fillingRecord.stream().collect(Collectors.toMap(CylinderFillingRecordStatisticsDto::getTime, f -> f.getFillingQuantity()));
        Map<String, String> offloadingMap = offloading.stream().collect(Collectors.toMap(CylinderFillingRecordStatisticsDto::getTime, f -> f.getOffloadingVolume()));
        List<CylinderFillingRecordStatisticsDto> data = new ArrayList<>();
        for (String key : times) {
            CylinderFillingRecordStatisticsDto dayData = new CylinderFillingRecordStatisticsDto();
            dayData.setTime(key);
            dayData.setFillingQuantity(fillingRecordMap.getOrDefault(key, "0"));
            dayData.setOffloadingVolume(offloadingMap.getOrDefault(key, "0"));
            data.add(dayData);
        }
        return data;
    }


}