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.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.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.utils.InfluxDButils;
import com.yeejoin.amos.component.influxdb.InfluxdbUtil;
import org.elasticsearch.index.query.BoolQueryBuilder;
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.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.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
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;

    /**
     * @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 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);
        if (mapList.size() < 1){
            return avageValue;
        }
        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("%.2f",totalvalue));
    }
    /**
     * @deprecated  获取指标值平均值
     * @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 {
                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"));
                stationBasicList.forEach(stationBasic -> {
                    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.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.setInstalledCapacity(String.format("%.2f",sjglZsjZsbtzMapper.getStationCapactityByStationWerks(stationBasic.getStationNumber())));
                    List<QueryDto> queryDtoList = new ArrayList<>();
                    queryDtoList.add(new QueryDto("gatewayId",stationBasic.getFanGatewayId()));
                    queryDtoList.add(new QueryDto("equipmentIndexName.keyword","有功功率"));
                    if(!stationBasic.getStationType().equals("FDZ")){
                        queryDtoList.add(new QueryDto("frontModule","逆变器"));
                    }
                    stationCacheInfoDto.setEquipmentNumbers(this.getCount(queryDtoList,"equipmentNumber.Keyword", ESEquipments.class).toString());
                    stationCacheInfoDto.setFanGatewayId(stationBasic.getFanGatewayId());
                    stationCacheInfoDto.setBoosterGatewayId(stationBasic.getBoosterGatewayId());
                    stationCacheInfoDtos.add(stationCacheInfoDto);
                });
                redisTemplate.opsForList().leftPushAll("station_info_cache",stationCacheInfoDtos);
                return  stationCacheInfoDtos;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return stationCacheInfoDtoList;
    }


    /*

     *分组求和
     **/
    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 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);
        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)).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;
    }



}
