package com.yeejoin.amos.boot.module.tzs.flc.biz.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.module.tzs.api.entity.ESCylinderFillingRecordDto;
import com.yeejoin.amos.boot.module.tzs.biz.dao.ESCylinderFillingRecordRepository;
import com.yeejoin.amos.boot.module.tzs.flc.api.dto.CylinderFillingRecordDto;
import com.yeejoin.amos.boot.module.tzs.flc.api.entity.CylinderFillingRecord;
import com.yeejoin.amos.boot.module.tzs.flc.api.mapper.CylinderFillingRecordMapper;
import com.yeejoin.amos.boot.module.tzs.flc.api.service.ICylinderFillingRecordService;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.rdbms.service.BaseService;

import java.io.IOException;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 液化气体气瓶充装信息-充装记录服务实现类
 *
 * @author system_generator
 * @date 2022-03-04
 */
@Service
public class CylinderFillingRecordServiceImpl extends BaseService<CylinderFillingRecordDto, CylinderFillingRecord, CylinderFillingRecordMapper> implements ICylinderFillingRecordService {

    @Autowired
    ESCylinderFillingRecordRepository esCylinderFillingRecordRepository;

    @Autowired
    CylinderFillingRecordMapper cylinderFillingRecordMapper;

    @Value("${biz.elasticsearch.address}")
    private String esAddress;

    @Value("${biz.elasticsearch.port}")
    private Integer esPort;

    @Value("${elasticsearch.username}")
    private String esUserName;

    @Value("${elasticsearch.password}")
    private String esPwd;

    /**
     * 分页查询
     */
    public Page<CylinderFillingRecordDto> queryForCylinderFillingRecordPage(Page<CylinderFillingRecordDto> page) {
        return this.queryForPage(page, null, false);
    }

    /**
     * 列表查询 示例
     */
    public List<CylinderFillingRecordDto> queryForCylinderFillingRecordList() {
        return this.queryForList("", false);
    }

    public Double queryIntegirtyByAppId(String appId) {
        return this.baseMapper.queryIntegirtyByAppId(appId);
    }

    public Double getFillingSum(String r, Date time) {
        return this.baseMapper.getFillingSum(r, time);
    }

    public Page<CylinderFillingRecordDto> queryListByQueryDto(Page<CylinderFillingRecordDto> page, CylinderFillingRecordDto cylinderFillingRecordDto, String sortParam, String sortRule) {
        Page<List<CylinderFillingRecordDto>> list = this.baseMapper.queryListByQueryDto(
                page,
//                cylinderFillingRecordDto.getFillingUnitName(),
//                cylinderFillingRecordDto.getPropertyUnit(),
//                cylinderFillingRecordDto.getFactoryNum(),
//                cylinderFillingRecordDto.getCylinderVariety(),
//                cylinderFillingRecordDto.getQrCode(),
//                cylinderFillingRecordDto.getElectronicLabelCode(),
//                cylinderFillingRecordDto.getSequenceCode(),
//                cylinderFillingRecordDto.getUnitInnerCode(),
                cylinderFillingRecordDto.getFillingStarttime(),
                cylinderFillingRecordDto.getFillingEndtime(),
                sortParam, sortRule, cylinderFillingRecordDto.getAppId()
        );
        Page<CylinderFillingRecordDto> page1 = new Page<>();
        List<CylinderFillingRecordDto> resultDtoList = JSONArray.parseArray(JSONArray.toJSONString(list.getRecords()), CylinderFillingRecordDto.class);
        page1.setCurrent(page.getCurrent());
        page1.setSize(page.getSize());
        page1.setTotal(list.getTotal());
        page1.setRecords(resultDtoList);
        return page1;
    }

    public Double getFillingSumByMonth(String appId, Date time) {
        return baseMapper.getFillingSumByMonth(appId, time);
    }

    public Integer getFillingCountByMonth(String appId, Date time) {
        return baseMapper.getFillingCountByMonth(appId, time);
    }

    public Double getFillingSumByDate(String appId, Date time) {
        return baseMapper.getFillingSumByDate(appId, time);
    }


    @Scheduled(cron = "${tzs.cylinder.fill.cron}")
    public void setTimeSaveCylinderInfoToES(){
        Page<ESCylinderFillingRecordDto> cylinderFillingRecordPage = new Page<>();
        Page<ESCylinderFillingRecordDto> cyinderInfoList = cylinderFillingRecordMapper.getCyinderFillingRecord(cylinderFillingRecordPage);
        Long count = cyinderInfoList.getCurrent();
        Long times = 0L;
        if (count != 0) {
            times = count / 1000;
            Long last = count % 1000;
            if (last > 0) {
                times++;
            }
        }
        for (int i = 0; i <= times; i++) {
            cylinderFillingRecordPage.setCurrent(i);
            cylinderFillingRecordPage.setSize(1000);
            cylinderFillingRecordPage = cylinderFillingRecordMapper.getCyinderFillingRecord(cylinderFillingRecordPage);
            if(!ObjectUtils.isEmpty(cylinderFillingRecordPage)){
                cylinderFillingRecordPage.getRecords().stream().map(item->{
                    if(!ObjectUtils.isEmpty(item.getSequenceCode())){
                        ESCylinderFillingRecordDto cyinderFillingRecordInfo = cylinderFillingRecordMapper.getCyinderFillingRecordInfo(item.getAppId(),item.getSequenceCode());
                        item.setUnitName(cyinderFillingRecordInfo.getUnitName());
                        item.setFactoryNum(cyinderFillingRecordInfo.getFactoryNum());
                        item.setCylinderVariety(cyinderFillingRecordInfo.getCylinderVariety());
                        item.setCylinderVarietyName(cyinderFillingRecordInfo.getCylinderVarietyName());
                        item.setUnitInnerCode(cyinderFillingRecordInfo.getUnitInnerCode());
                        item.setSequenceCode(cyinderFillingRecordInfo.getSequenceCode());
                        item.setQrCode(cyinderFillingRecordInfo.getQrCode());
                        item.setElectronicLabelCode(cyinderFillingRecordInfo.getElectronicLabelCode());
                        item.setAppId(cyinderFillingRecordInfo.getAppId());
                        item.setCreditCode(cyinderFillingRecordInfo.getCreditCode());
                    }
                    return item;
                }).collect(Collectors.toList());
            }
            for (ESCylinderFillingRecordDto ci : cylinderFillingRecordPage.getRecords()) {
                saveCylinderFillingRecordToES(ci);
            }
        }
    }


    @Override
    public Page<ESCylinderFillingRecordDto> getCyinderFillingRecord(Page<ESCylinderFillingRecordDto> cylinderFillingRecordDto) {
        Page<ESCylinderFillingRecordDto> cyinderFillingRecord = cylinderFillingRecordMapper.getCyinderFillingRecord(cylinderFillingRecordDto);
        if(!ObjectUtils.isEmpty(cyinderFillingRecord)){
            cyinderFillingRecord.getRecords().stream().map(item -> {
                if (!ObjectUtils.isEmpty(item.getSequenceCode())) {
                    ESCylinderFillingRecordDto cyinderFillingRecordInfo = cylinderFillingRecordMapper.getCyinderFillingRecordInfo(item.getAppId(), item.getSequenceCode());
                    if (!ObjectUtils.isEmpty(cyinderFillingRecordInfo)) {
                        item.setUnitName(cyinderFillingRecordInfo.getUnitName());
                        item.setFactoryNum(cyinderFillingRecordInfo.getFactoryNum());
                        item.setCylinderVariety(cyinderFillingRecordInfo.getCylinderVariety());
                        item.setCylinderVarietyName(cyinderFillingRecordInfo.getCylinderVarietyName());
                        item.setUnitInnerCode(cyinderFillingRecordInfo.getUnitInnerCode());
                        item.setSequenceCode(cyinderFillingRecordInfo.getSequenceCode());
                        item.setQrCode(cyinderFillingRecordInfo.getQrCode());
                        item.setElectronicLabelCode(cyinderFillingRecordInfo.getElectronicLabelCode());
                        item.setAppId(cyinderFillingRecordInfo.getAppId());
                        item.setCreditCode(cyinderFillingRecordInfo.getCreditCode());
                        item.setRegionCode(cyinderFillingRecordInfo.getRegionCode());
                    }
                }
                return item;
            }).collect(Collectors.toList());
        }
        return cyinderFillingRecord;
    }

    @Override
    public Page<ESCylinderFillingRecordDto> queryByKeys(ESCylinderFillingRecordDto esCylinderFillingRecordDto, int pageNum, int pageSize) {

        Page<ESCylinderFillingRecordDto> result = new Page<ESCylinderFillingRecordDto>(pageNum, pageSize);

        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY,
                new UsernamePasswordCredentials(esUserName, esPwd));  //es账号密码
        RestHighLevelClient esClient =new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost(esAddress,esPort)
                ).setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                        httpClientBuilder.disableAuthCaching();
                        return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                    }
                })
        );


//        RestHighLevelClient esClient = new RestHighLevelClient(
//                RestClient.builder(new HttpHost(esAddress, esPort, "http"))
//        );

        SearchRequest request = new SearchRequest();
        request.indices("cylinder_filling");

        //通用匹配规则，条件构建
        boolean flag = true;

        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder boolMust = QueryBuilders.boolQuery();

        //匹配统一信用代码
        if (!ObjectUtils.isEmpty(esCylinderFillingRecordDto.getCreditCode())) {
            flag = false;
            BoolQueryBuilder meBuilder = QueryBuilders.boolQuery();
            meBuilder.must(QueryBuilders.matchQuery("creditCode", esCylinderFillingRecordDto.getCreditCode()));
            boolMust.must(meBuilder);
        }

        //匹配行政区划
        if (!ObjectUtils.isEmpty(esCylinderFillingRecordDto.getRegionCode())) {
            flag = false;
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.matchQuery("regionCode", "*" + esCylinderFillingRecordDto.getRegionCode() + "*"));
            boolMust.must(query);
        }

        //匹配充装单位
        if (!ObjectUtils.isEmpty(esCylinderFillingRecordDto.getFillingUnitName())) {
            flag = false;
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.matchQuery("fillingUnitName", "*" + esCylinderFillingRecordDto.getFillingUnitName() + "*"));
            boolMust.must(query);
        }

        //匹配产权单位
        if (!ObjectUtils.isEmpty(esCylinderFillingRecordDto.getUnitName())) {
            flag = false;
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.matchQuery("unitName", "*" + esCylinderFillingRecordDto.getUnitName() + "*"));
            boolMust.must(query);
        }

        //匹配出厂编号
        if (!ObjectUtils.isEmpty(esCylinderFillingRecordDto.getFactoryNum())) {
            flag = false;
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.matchQuery("factoryNum", "*" + esCylinderFillingRecordDto.getFactoryNum() + "*"));
            boolMust.must(query);
        }

        //匹配气瓶品种
        if (!ObjectUtils.isEmpty(esCylinderFillingRecordDto.getCylinderVariety())) {
            flag = false;
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.matchQuery("cylinderVariety", esCylinderFillingRecordDto.getCylinderVariety()));
            boolMust.must(query);
        }

        //匹配二维码编码
        if (!ObjectUtils.isEmpty(esCylinderFillingRecordDto.getQrCode())) {
            flag = false;
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.matchQuery("qrCode", "*" + esCylinderFillingRecordDto.getQrCode() + "*"));
            boolMust.must(query);
        }

        //匹配电子标签
        if (!ObjectUtils.isEmpty(esCylinderFillingRecordDto.getElectronicLabelCode())) {
            flag = false;
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.matchQuery("electronicLabelCode", "*" + esCylinderFillingRecordDto.getElectronicLabelCode() + "*"));
            boolMust.must(query);
        }

        //匹配气瓶唯一标识
        if (!ObjectUtils.isEmpty(esCylinderFillingRecordDto.getSequenceCode())) {
            flag = false;
            BoolQueryBuilder sequenceCodeBuilder = QueryBuilders.boolQuery();
            sequenceCodeBuilder.must(QueryBuilders.matchQuery("sequenceCode", esCylinderFillingRecordDto.getSequenceCode()));
            boolMust.must(sequenceCodeBuilder);
        }

        //匹配单位内部编号
        if (!ObjectUtils.isEmpty(esCylinderFillingRecordDto.getUnitInnerCode())) {
            flag = false;
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.matchQuery("unitInnerCode", "*" + esCylinderFillingRecordDto.getUnitInnerCode() + "*"));
            boolMust.must(query);
        }


        //充装开始时间
        if (!ObjectUtils.isEmpty(esCylinderFillingRecordDto.getFillingStartTime())) {
            flag = false;
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.matchQuery("fillingStartTime", esCylinderFillingRecordDto.getFillingStartTime()));
            boolMust.must(query);
        }

        //充装结束时间
        if (!ObjectUtils.isEmpty(esCylinderFillingRecordDto.getFillingEndTime())) {
            flag = false;
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.matchQuery("fillingEndTime", esCylinderFillingRecordDto.getFillingEndTime()));
            boolMust.must(query);
        }

        if(flag) { // 搜索全部
            boolMust.must(QueryBuilders.matchAllQuery());
        }

        builder.query(boolMust);
        builder.from((pageNum - 1) * pageSize);
        builder.size(pageSize);
        builder.trackTotalHits(true);
        request.source(builder);
        List<ESCylinderFillingRecordDto> list = new LinkedList<>();
        long totle = 0;
        try {
            SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
            for (org.elasticsearch.search.SearchHit hit : response.getHits()) {
                System.out.println(hit);
                JSONObject jsonObject = (JSONObject) JSONObject.toJSON(hit);
                ESCylinderFillingRecordDto esCylinderFillingRecordDto1 = JSONObject.toJavaObject(jsonObject.getJSONObject("sourceAsMap"), ESCylinderFillingRecordDto.class);
                list.add(esCylinderFillingRecordDto1);
            }
            totle = response.getInternalResponse().hits().getTotalHits().value;
            result.setRecords(list);
            result.setTotal(totle);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return result;
    }

    @Override
    public ESCylinderFillingRecordDto saveCylinderFillingRecordToES(ESCylinderFillingRecordDto ci) {

        ESCylinderFillingRecordDto recordDto = esCylinderFillingRecordRepository.save(ci);
        if (!ObjectUtils.isEmpty(recordDto)) {
            //同步到es后修改
            CylinderFillingRecord cylinderFillingRecord = new CylinderFillingRecord();
            cylinderFillingRecord.setIsNotEs("1");
            baseMapper.update(cylinderFillingRecord, new QueryWrapper<CylinderFillingRecord>().eq("sequence_nbr", ci.getSequenceNbr()));
        }

        return recordDto;
    }
}