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

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.module.jxiop.api.entity.MapRegion;
import com.yeejoin.amos.boot.module.jxiop.api.entity.Region;
import com.yeejoin.amos.boot.module.jxiop.api.entity.StationBasic;
import com.yeejoin.amos.boot.module.jxiop.api.mapper.MapRegionMapper;
import com.yeejoin.amos.boot.module.jxiop.api.mapper.RegionMapper;
import com.yeejoin.amos.boot.module.jxiop.api.mapper.StationBasicMapper;
import com.yeejoin.amos.boot.module.jxiop.biz.ESDto.ESEquipments;
import com.yeejoin.amos.boot.module.jxiop.biz.constants.CommonConstans;
import com.yeejoin.amos.boot.module.jxiop.biz.dto.QueryDto;
import com.yeejoin.amos.boot.module.jxiop.biz.dto.SocialContributionDto;
import com.yeejoin.amos.boot.module.jxiop.biz.dto.StationCacheInfoDto;
import com.yeejoin.amos.boot.module.jxiop.biz.initdata.StationCacheDataInit;
import com.yeejoin.amos.boot.module.jxiop.biz.mapper2.SjglZsjZsbtzMapper;

import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.AvgAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.SumAggregationBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CommonServiceImpl {
//    @Autowired
//    InfluxDButils influxDButils;

    //    @Autowired
//    InfluxdbUtil influxdbUtil;
    @Autowired
    SjglZsjZsbtzMapper sjglZsjZsbtzMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StationCacheDataInit stationCacheDataInit;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;
    @Resource
    private StationBasicMapper stationBasicMapper;
    @Resource
    private RegionMapper regionMapper;
    @Resource
    private MapRegionMapper mapRegionMapper;

    /**
     * @param gatewayId 网关id 用于拼接sql语句
     * @param indicator 指标名称  查询条件-根据指标名称获取风速
     * @return 指标值总和
     * @deprecated 获取指标值总和
     */
    public Double getTotalByIndicatior(String gatewayId, String indicator) {

        //用于组装-es查询条件
        Map<String, List<String>> queryCondtion = new HashMap<>();
        queryCondtion.put(CommonConstans.QueryStringEquipmentIndexName, Arrays.asList(indicator));
        queryCondtion.put(CommonConstans.QueryStringGateWayId, Arrays.asList(gatewayId));
        List<ESEquipments> result = getListDataByCondtions(queryCondtion, null, ESEquipments.class);
        Double totalvalue = 0.00;
        try {
            totalvalue = result.stream().filter(stringObjectMap -> !ObjectUtils.isEmpty(stringObjectMap.getValueF())).mapToDouble(l -> Double.parseDouble(l.getValueF().toString())).sum();
        } catch (Exception e) {
            return totalvalue;
        }
        return Double.valueOf(String.format("%.2f", totalvalue));
    }

    public Double getAvagerByEquipmentIndxName(List<ESEquipments> equipments, String indexName) {
        Double result = 0.00;
        result = equipments.stream().filter(esEquipments -> esEquipments.getEquipmentIndexName().equals(indexName)).filter(esEquipments -> esEquipments.getValueF() != null).mapToDouble(ESEquipments::getValueF).average().getAsDouble();
        return result;
    }

//    public Double getNumByIndicatior(String gatewayId,String indicator){
//        String sql = "SELECT * FROM indicators_"+gatewayId+" where equipmentIndexName=~/"+indicator+"$/";
//        Double totalvalue =  0.0;
//        List<Map<String,Object>> mapList = influxdbUtil.query(sql);
//        totalvalue =mapList.stream().filter(stringObjectMap -> !ObjectUtils.isEmpty(stringObjectMap.get("value"))).mapToDouble(l->Double.parseDouble((String) l.get("value"))).sum();
//        return Double.valueOf(String.format("%.2f",totalvalue));
//    }

    /**
     * @param gatewayId 网关id 用于拼接sql语句
     * @param indicator 指标名称  查询条件-根据指标名称获取风速
     * @return 指标值总和
     * @deprecated 获取指标值平均值
     */
//    public Double getAvgvalueByIndicatior(String gatewayId,String indicator){
//        String sql = "SELECT * FROM indicators_" + gatewayId + " where equipmentIndexName='" + indicator + "'";
//        Double avageValue = 0.00;
//        try {
//            List<Map<String, Object>> mapList = influxdbUtil.query(sql);
//            avageValue = mapList.stream().filter(stringObjectMap -> !ObjectUtils.isEmpty(stringObjectMap.get("value"))).mapToDouble(l -> Double.parseDouble((String) l.get("value"))).average().getAsDouble();
//        } catch (Exception e) {
//            return avageValue;
//        }
//        return Double.valueOf(String.format("%.2f", avageValue));
//    }
    public Double getTotalByIndicatior(List<Map<String, Object>> mapList, String indicator) {
        Double totalvalue = 0.0;
        totalvalue = mapList.stream().filter(stringObjectMap -> stringObjectMap.get("equipmentIndexName").toString().contains(indicator) && !ObjectUtils.isEmpty(stringObjectMap.get("value"))).mapToDouble(l -> Double.parseDouble((String) l.get("value"))).sum();
        return Double.valueOf(String.format("%.2f", totalvalue));
    }

    /**
     * @param indicator 指标名称  查询条件-根据指标名称获取风速
     * @return 指标值总和
     * @deprecated 获取指标值平均值
     */
    public Double getAvgvalueByIndicatior(List<Map<String, Object>> mapList, String indicator) {
        Double avageValue = 0.0;
        avageValue = mapList.stream().filter(stringObjectMap -> stringObjectMap.get("equipmentIndexName").toString().contains(indicator) && !ObjectUtils.isEmpty(stringObjectMap.get("value"))).mapToDouble(l -> Double.parseDouble((String) l.get("value"))).sum();
        return Double.valueOf(String.format("%.2f", avageValue));
    }


    public Double getStationCapactityByStationWerks(String WERKS) {
        return sjglZsjZsbtzMapper.getStationCapactityByStationWerks(WERKS);
    }

    public Page<SocialContributionDto> getSocialContributionDtoList(Double totalSocialContribution) {
        Page<SocialContributionDto> socialContributionDtoPage = new Page<SocialContributionDto>();
        List<SocialContributionDto> socialContributionDtoList = new ArrayList<>();

        //获取所有网关id不为空的数据

        //二氧化碳贡献数
        SocialContributionDto co2 = new SocialContributionDto();
        //标准煤贡献度
        SocialContributionDto coal = new SocialContributionDto();
        //碳粉尘计算公式
        SocialContributionDto toner = new SocialContributionDto();
        //二氧化硫贡献度
        SocialContributionDto so2 = new SocialContributionDto();
        /** 社会贡献原始计算公式，后边的数据已经经过处理
         //二氧化碳计算公式  *10000*832/10000/1000/1000
         //标准煤计算公式  *10000*304.9/10000/1000/1000
         //碳粉尘计算公式 *10000*0.032/1000/1000
         //二氧化硫计算公式  =A2*10000*0.16/1000/1000
         */
        co2.setUnit("二氧化碳减排量（万t）");
        co2.setTitle(String.format("%.2f", totalSocialContribution * 0.000832));
        socialContributionDtoList.add(co2);
        coal.setUnit("节约标准煤（万t）");
        coal.setTitle(String.format("%.2f", totalSocialContribution * 0.0003049));
        socialContributionDtoList.add(coal);
        toner.setUnit("碳粉尘减排量（万t）");
        toner.setTitle(String.format("%.2f", totalSocialContribution * 0.00032));
        socialContributionDtoList.add(toner);
        so2.setUnit("二氧化硫减排量（万t）");
        so2.setTitle(String.format("%.2f", totalSocialContribution * 0.0016));
        socialContributionDtoList.add(so2);
        socialContributionDtoPage.setRecords(socialContributionDtoList);
        socialContributionDtoPage.setTotal(100);
        socialContributionDtoPage.setCurrent(1);
        return socialContributionDtoPage;
    }

    public <T> List<T> getListDataByCondtion(Map<String, List<String>> mustQuerCondtion, Map<String, String> shouldQuerCondtion, Class<T> tClass, Map<String, String> likeQuerCondtion) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if (!ObjectUtils.isEmpty(mustQuerCondtion)) {
            for (String key : mustQuerCondtion.keySet()) {
                List<String> va = mustQuerCondtion.get(key);
                queryBuilder.must(QueryBuilders.termsQuery(key, va));
            }
        }
        if (!ObjectUtils.isEmpty(shouldQuerCondtion)) {
            for (String key : shouldQuerCondtion.keySet()) {
                queryBuilder.should(QueryBuilders.wildcardQuery(key, shouldQuerCondtion.get(key)));
            }
        }

        if (!ObjectUtils.isEmpty(likeQuerCondtion)) {
            for (String key : likeQuerCondtion.keySet()) {
                queryBuilder.must(QueryBuilders.wildcardQuery(key, "*" + likeQuerCondtion.get(key) + "*"));
            }
        }
        Query query = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .build();
        query.setTrackTotalHits(true);
        SearchHits search = elasticsearchTemplate.search(query, tClass);
        if (search.hasSearchHits()) {
            List<SearchHit<T>> searchHitList = search.getSearchHits();
            List<T> list = searchHitList.stream().map(hit -> hit.getContent()).collect(Collectors.toList());
            return list;
        }
        return null;
    }


    public List<StationCacheInfoDto> getListStationCacheInfoDto() {
        List<StationCacheInfoDto> stationCacheInfoDtos = new ArrayList<>();
        List<Region> regionList = regionMapper.selectList(new QueryWrapper<Region>().eq("LEVEL", 1));
        List<MapRegion> mapRegionList = mapRegionMapper.selectList(new QueryWrapper<MapRegion>().isNotNull("name"));
        List<StationBasic> stationBasicList = stationBasicMapper.selectList(new QueryWrapper<StationBasic>().isNotNull("belong_area").isNotNull("fan_gateway_id"));
        for (int i = 0; i < stationBasicList.size(); i++) {
            StationBasic stationBasic = stationBasicList.get(i);
            StationCacheInfoDto stationCacheInfoDto = new StationCacheInfoDto();
            stationCacheInfoDto.setStationId(stationBasic.getSequenceNbr().toString());
            stationCacheInfoDto.setStationName(stationBasic.getStationName());
            stationCacheInfoDto.setStationType(stationBasic.getStationType());
            stationCacheInfoDto.setBelongProvince(regionList.stream().filter(region -> region.getRegionCode().toString().equals(stationBasic.getBelongArea().replace("[", "").split(",")[0])).map(region -> region.getRegionName()).collect(Collectors.toList()).get(0));
            stationCacheInfoDto.setBelongArea(mapRegionList.stream().filter(mapRegion -> mapRegion.getProvince().contains(stationCacheInfoDto.getBelongProvince().substring(0, 2)) || mapRegion.getProvince().contains(stationCacheInfoDto.getBelongProvince().substring(0, 3))).map(mapRegion -> mapRegion.getName()).collect(Collectors.toList()).get(0));
            stationCacheInfoDto.setInstalledCapacity(String.format("%.2f", sjglZsjZsbtzMapper.getStationCapactityByStationWerks(stationBasic.getStationNumber())));
            stationCacheInfoDto.setFanGatewayId(stationBasic.getFanGatewayId());
            stationCacheInfoDto.setAreaCode(mapRegionList.stream().filter(mapRegion -> mapRegion.getProvince().contains(stationCacheInfoDto.getBelongProvince().substring(0, 2)) || mapRegion.getProvince().contains(stationCacheInfoDto.getBelongProvince().substring(0, 3))).map(mapRegion -> mapRegion.getAreaCode()).collect(Collectors.toList()).get(0));
            stationCacheInfoDto.setBoosterGatewayId(stationBasic.getBoosterGatewayId());
            stationCacheInfoDtos.add(stationCacheInfoDto);
        }

        return stationCacheInfoDtos;
    }

    /**
     * 根据查询条件获取列表信息
     *
     * @param mustQuerCondtion
     * @param shouldQuerCondtion
     * @param tClass
     * @param <T>
     * @param likeMap            模糊字段查询 key：不能带.keyWords
     * @return
     */
    public <T> List<T> getListDataByCondtionsAndLike(Map<String, List<String>> mustQuerCondtion, Map<String, String> shouldQuerCondtion, Class<T> tClass, Map<String, String> likeMap) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if (!ObjectUtils.isEmpty(mustQuerCondtion)) {
            for (String key : mustQuerCondtion.keySet()) {
                List<String> va = mustQuerCondtion.get(key);
                queryBuilder.must(QueryBuilders.termsQuery(key, va));
            }
        }
        if (!ObjectUtils.isEmpty(shouldQuerCondtion)) {
            for (String key : shouldQuerCondtion.keySet()) {
                queryBuilder.should(QueryBuilders.wildcardQuery(key, shouldQuerCondtion.get(key)));
            }
        }
        if (!ObjectUtils.isEmpty(likeMap)) {
            for (String key : likeMap.keySet()) {
                MatchPhraseQueryBuilder queryBuilder1 = QueryBuilders.matchPhraseQuery(key, "*" + likeMap.get(key) + "*");
                queryBuilder.must(queryBuilder1);
            }
        }

        Query query = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .build();
        query.setTrackTotalHits(true);
        SearchHits search = elasticsearchTemplate.search(query, tClass);
        if (search.hasSearchHits()) {
            List<SearchHit<T>> searchHitList = search.getSearchHits();
            List<T> list = searchHitList.stream().map(hit -> hit.getContent()).collect(Collectors.toList());
            return list;
        }
        return new ArrayList<>();
    }

    /*

     *分组求和
     **/
    public List<? extends Terms.Bucket> getgroupsum(Map<String, List<String>> value, String keyavg, String groupKey, Class clas) {
        List<? extends Terms.Bucket> listdata = null;
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        for (String key : value.keySet()) {
            List<String> va = value.get(key);
            queryBuilder.must(QueryBuilders.termsQuery(key, va));
        }

        TermsAggregationBuilder tb1 = AggregationBuilders.terms("groupKey").field(groupKey).size(1000);
        SumAggregationBuilder buyCountSum = AggregationBuilders.sum("buyCountSum").field(keyavg);
        tb1.subAggregation(buyCountSum);    // 通过typeId字段分组统计总数
        Query query = new NativeSearchQueryBuilder()
                .addAggregation(tb1)
                .withQuery(queryBuilder)

                .withPageable(PageRequest.of(0, 10000))
                .build();
        query.setTrackTotalHits(true);


        SearchHits search = elasticsearchTemplate.search(query, clas);
        if (search.hasAggregations()) {
            Aggregations aggregations = search.getAggregations();
            if (Objects.nonNull(aggregations)) {
                List<Aggregation> list = aggregations.asList();
                listdata = list != null && !list.isEmpty() ? ((ParsedStringTerms) list.get(0)).getBuckets() : null;

            }
        }
        return listdata;
    }

    public Integer getCount(List<QueryDto> queryDto, String keysum, Class clas) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        for (QueryDto dto : queryDto) {
            queryBuilder.must(QueryBuilders.matchPhraseQuery(dto.getKey(), dto.getValue()));
        }
        Query query = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withPageable(PageRequest.of(0, 10000))
                .build();
        query.setTrackTotalHits(true);
        SearchHits search = elasticsearchTemplate.search(query, clas);
        return search.getSearchHits().size();
    }

    /*

     *分组平均值
     **/
    public List<? extends Terms.Bucket> getgroupavg(Map<String, List<String>> value, String keyavg, String groupKey, Class clas) {
        List<? extends Terms.Bucket> listdata = null;
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        for (String key : value.keySet()) {
            List<String> va = value.get(key);
            queryBuilder.must(QueryBuilders.termsQuery(key, va));
        }

        TermsAggregationBuilder tb1 = AggregationBuilders.terms("groupKey").field(groupKey).size(1000);
        AvgAggregationBuilder buyCountAvg = AggregationBuilders.avg("buyCountAvg").field(keyavg);

        tb1.subAggregation(buyCountAvg);    // 通过typeId字段分组统计总数
        Query query = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .addAggregation(tb1)
                .withPageable(PageRequest.of(0, 1))
                .build();
        query.setTrackTotalHits(true);
        SearchHits search = elasticsearchTemplate.search(query, ESEquipments.class);
        if (search.hasAggregations()) {
            Aggregations aggregations = search.getAggregations();
            if (Objects.nonNull(aggregations)) {
                List<Aggregation> list = aggregations.asList();
                listdata = list != null && !list.isEmpty() ? ((ParsedStringTerms) list.get(0)).getBuckets() : null;

            }
        }
        return listdata;
    }

    public Double getSumByEquipmentIndxName(List<ESEquipments> equipments, String indexName) {
        Double result = 0.00;
        result = equipments.stream().filter(esEquipments -> esEquipments.getEquipmentIndexName().equals(indexName)).filter(esEquipments -> esEquipments.getValueF() != null).mapToDouble(ESEquipments::getValueF).sum();
        return result;
    }

    /**
     * 根据查询条件获取列表信息
     *
     * @param mustQuerCondtion
     * @param shouldQuerCondtion
     * @param tClass
     * @param <T>
     * @return
     */
    public <T> List<T> getListDataByCondtions(Map<String, List<String>> mustQuerCondtion, Map<String, String> shouldQuerCondtion, Class<T> tClass) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if (!ObjectUtils.isEmpty(mustQuerCondtion)) {
            for (String key : mustQuerCondtion.keySet()) {
                List<String> va = mustQuerCondtion.get(key);
                queryBuilder.must(QueryBuilders.termsQuery(key, va));
            }
        }
        if (!ObjectUtils.isEmpty(shouldQuerCondtion)) {
            for (String key : shouldQuerCondtion.keySet()) {
                queryBuilder.should(QueryBuilders.wildcardQuery(key, shouldQuerCondtion.get(key)));
            }
        }
        Query query = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .build();
        query.setTrackTotalHits(true);
        SearchHits search = elasticsearchTemplate.search(query, tClass);
        if (search.hasSearchHits()) {
            List<SearchHit<T>> searchHitList = search.getSearchHits();
            List<T> list = searchHitList.stream().map(hit -> hit.getContent()).collect(Collectors.toList());
            return list;
        }
        return null;
    }

    public <T> List<T> getListDataByCondtions(Map<String, List<String>> mustQuerCondtion, Map<String, String> shouldQuerCondtion, Class<T> tClass, Map<String, String> likeQuerCondtion) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if (!ObjectUtils.isEmpty(mustQuerCondtion)) {
            for (String key : mustQuerCondtion.keySet()) {
                List<String> va = mustQuerCondtion.get(key);
                queryBuilder.must(QueryBuilders.termsQuery(key, va));
            }
        }
        if (!ObjectUtils.isEmpty(shouldQuerCondtion)) {
            for (String key : shouldQuerCondtion.keySet()) {
                queryBuilder.should(QueryBuilders.wildcardQuery(key, shouldQuerCondtion.get(key)));
            }
        }

        if (!ObjectUtils.isEmpty(likeQuerCondtion)) {
            for (String key : likeQuerCondtion.keySet()) {
                queryBuilder.must(QueryBuilders.wildcardQuery(key, "*" + likeQuerCondtion.get(key) + "*"));
            }
        }
        Query query = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .build();
        query.setTrackTotalHits(true);
        SearchHits search = elasticsearchTemplate.search(query, tClass);
        if (search.hasSearchHits()) {
            List<SearchHit<T>> searchHitList = search.getSearchHits();
            List<T> list = searchHitList.stream().map(hit -> hit.getContent()).collect(Collectors.toList());
            return list;
        }
        return null;
    }


    public Double getTotalByIndicatiorByGF(String gatewayId, String indicator) {
        if (indicator.equals("日发电量")) {
            indicator = CommonConstans.taiHeGenIndicatorDay;
        }
        if (indicator.equals("月发电量")) {
            indicator = CommonConstans.taiHeGenIndicatorMonth;

        }
        if (indicator.equals("年发电量")) {
            indicator = CommonConstans.taiHeGenIndicatorYear;
        }
        //用于组装-es查询条件
        Map<String, List<String>> queryCondtion = new HashMap<>();
        queryCondtion.put(CommonConstans.QueryStringEquipmentIndexName, Arrays.asList(indicator));
        queryCondtion.put(CommonConstans.QueryStringGateWayId, Arrays.asList(gatewayId));
        List<ESEquipments> result = getListDataByCondtions(queryCondtion, null, ESEquipments.class);
        Double totalvalue = 0.00;
        try {
            totalvalue = result.stream().filter(stringObjectMap -> !ObjectUtils.isEmpty(stringObjectMap.getValueF())).mapToDouble(l -> Double.parseDouble(l.getValueF().toString())).sum();
        } catch (Exception e) {
            return totalvalue;
        }
        return Double.valueOf(String.format("%.4f", totalvalue));
    }

}
