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

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.StationBasic;
import com.yeejoin.amos.boot.module.jxiop.biz.ESDto.ESEquipments;
import com.yeejoin.amos.boot.module.jxiop.biz.dto.IndicatorsDto;
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 com.yeejoin.amos.boot.module.jxiop.biz.repository.ESEquipmentsRepository;
import com.yeejoin.amos.boot.module.jxiop.biz.utils.InfluxDButils;
import com.yeejoin.amos.component.influxdb.InfluxdbUtil;
import net.bytebuddy.asm.Advice;
import org.apache.poi.ss.formula.functions.Count;
import org.apache.poi.ss.formula.functions.T;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
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.ParsedTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.*;
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.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 java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Service
public class CommonServiceImpl {
    @Autowired
    InfluxDButils influxDButils;

    @Autowired
    InfluxdbUtil influxdbUtil;
    @Autowired
    SjglZsjZsbtzMapper sjglZsjZsbtzMapper;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;
    @Autowired
    ESEquipmentsRepository equipmentsRepository;
    @Autowired
    private StationCacheDataInit stationCacheDataInit;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     *   带参数 求平均值
     *
     * */
    public Double getavg(List<QueryDto> queryDto,String keyavg,Class clas){
        Double value=null;
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        for (QueryDto dto : queryDto) {
            queryBuilder.must( QueryBuilders.termQuery(dto.getKey(), dto.getValue()));
        }
        AvgAggregationBuilder buyCountAvg = AggregationBuilders.avg("buyCountAvg").field(keyavg);
        Query query = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .addAggregation(buyCountAvg)
                .withPageable(PageRequest.of(0, 1))
                .build();
        query.setTrackTotalHits(true);
        SearchHits search = elasticsearchTemplate.search(query,clas);
        if (search.hasAggregations()) {
            Aggregations aggregations = search.getAggregations();
            if (Objects.nonNull(aggregations)) {
                Avg avg = aggregations.get("buyCountAvg");
                value= avg.getValue();
            }
        }
          return value;
    }


    /*

    *分组平均值
    **/
    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);
        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  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);
        SumAggregationBuilder buyCountSum = AggregationBuilders.sum("buyCountSum").field(keyavg);
        tb1.subAggregation(buyCountSum);	// 通过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 getsum(List<QueryDto> queryDto,String keysum,Class clas){
        Double value=null;
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        for (QueryDto dto : queryDto) {
            queryBuilder.must( QueryBuilders.termQuery(dto.getKey(), dto.getValue()));
        }
        SumAggregationBuilder buyCountSum = AggregationBuilders.sum("buyCountSum").field(keysum);
        Query query = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .addAggregation(buyCountSum)
                .withPageable(PageRequest.of(0, 1))
                .build();
        query.setTrackTotalHits(true);
        SearchHits search = elasticsearchTemplate.search(query,clas);

        if (search.hasAggregations()) {
            Aggregations aggregations = search.getAggregations();
            if (Objects.nonNull(aggregations)) {
                Sum sum = aggregations.get("buyCountSum");
                value=  sum.getValue();
            }
        }
        return value;
    }

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















    /**
     * @deprecated  获取指标值总和
     * @param gatewayId 网关id 用于拼接sql语句
     * @param indicator 指标名称  查询条件-根据指标名称获取风速
     * @return 指标值总和
     */
    public Double getTotalByIndicatior(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));
    }

    public Double getTotalByIndicatiorAndParams(String gatewayId,String indicator,String querySql){
        String sql = "SELECT * FROM indicators_"+gatewayId+" where equipmentIndexName='"+indicator+"'";
        Double totalvalue =  0.0;
        if (null != querySql){
            sql = sql + " "+  querySql;
        }
        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));
    }


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

    /**
     * @deprecated  获取指标值平均值
     * @param gatewayId 网关id 用于拼接sql语句
     * @param indicator 指标名称  查询条件-根据指标名称获取风速
     * @return 指标值总和
     */
    public Double getAvgvalueByIndicatior(String gatewayId,String indicator){
        String sql = "SELECT * FROM indicators_"+gatewayId+" where equipmentIndexName='"+indicator+"'";
        Double avageValue =  0.0;
        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();
        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("%.4f",totalvalue));
    }
    /**
     * @deprecated  获取指标值平均值
     * @param gatewayId 网关id 用于拼接sql语句
     * @param indicator 指标名称  查询条件-根据指标名称获取风速
     * @return 指标值总和
     */
    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  List<StationCacheInfoDto> getListStationCacheInfoDto(){
        List<StationCacheInfoDto> stationCacheInfoDtoList =redisTemplate.opsForList().range("station_info_cache",0,-1);
       if(ObjectUtils.isEmpty(stationCacheInfoDtoList)){
           try {
               stationCacheDataInit.run();
               stationCacheInfoDtoList =redisTemplate.opsForList().range("station_info_cache",0,-1);
           } catch (Exception e) {
               throw new RuntimeException(e);
           }
       }

        return stationCacheInfoDtoList;
    }
}
