package com.zzsn.modules.kgj.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zzsn.modules.kgj.entity.*;
import com.zzsn.modules.kgj.mapper.BaseDataMapper;
import com.zzsn.modules.kgj.mapper.BaseDataTypeMapper;
import com.zzsn.modules.kgj.mapper.CisAnsBasedataMapper;
import com.zzsn.modules.kgj.service.ICisAnsBasedataService;
import com.zzsn.modules.kgj.utils.DateUtil;
import com.zzsn.modules.kgj.utils.EsDateUtil;
import com.zzsn.modules.kgj.utils.EsOpUtil;
import org.apache.commons.lang.StringUtils;
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.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.jsoup.Jsoup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;



/**
 * @Description: CIS_ANS_BASEDATA
 * @Author: zzsn-boot
 * @Date:   2020-08-26
 * @Version: V1.0
 */
@Service
@DS("master")
public class CisAnsBasedataServiceImpl extends ServiceImpl<CisAnsBasedataMapper, CisAnsBasedata> implements ICisAnsBasedataService {
    private Logger logger = LoggerFactory.getLogger(CisAnsBasedataServiceImpl.class);
    @Autowired
    private CisAnsBasedataMapper cisAnsBasedataMapper;

//    @Resource(name = "restHighLevelClient")
    @Autowired
    private RestHighLevelClient client;

    @Autowired
    private BaseDataMapper baseDataMapper;

    @Autowired
    private BaseDataTypeMapper baseDataTypeMapper;

    @Autowired
    private EsOpUtil esOpUtil;

    /**
     * 同步素材库数据到ES
     */
    @Override
    public void run(){}

    /**
     * 从es库中查询数据
     * @param baseDataDto
     * @return
     */
    @Override
    public Page<CisAnsBasedata> findEsByKey(BaseDataDto baseDataDto) {
        long l = System.currentTimeMillis();
        System.out.println("调用es:"+l);
        SearchRequest searchRequest = new SearchRequest("kgj");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        int fromPage = (baseDataDto.getPageNum()-1) * baseDataDto.getPageSize();
        //设置分页参数
        //共返回几条数据
        searchSourceBuilder.size(baseDataDto.getPageSize());
        //from标识从第几条开始
        searchSourceBuilder.from(fromPage);
        //设置排序字段
        searchSourceBuilder.sort("publishDate", SortOrder.DESC);
        //默认最大数量是10000，设置为true后，显示准确数量
        searchSourceBuilder.trackTotalHits(true);
        //创建查询对象
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if(baseDataDto.getDelflag()!=null && !(baseDataDto.getDelflag().equals(0L))){
            boolQuery.filter(QueryBuilders.termQuery("delflag",baseDataDto.getDelflag()));
        }
        if (!StringUtils.isBlank(baseDataDto.getSearchKey())) {
//            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//            boolQueryBuilder.should(QueryBuilders.wildcardQuery("title.keyword", "*" + baseDataDto.getSearchKey() + "*"));
//            boolQueryBuilder.should(QueryBuilders.wildcardQuery("contentNoTag.keyword", "*" + baseDataDto.getSearchKey() + "*"));
//            boolQueryBuilder.should(QueryBuilders.matchPhraseQuery("title", baseDataDto.getSearchKey()));
            MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("title", baseDataDto.getSearchKey());
            MatchPhraseQueryBuilder matchPhraseQueryBuilder1 = QueryBuilders.matchPhraseQuery("contentNoTag", baseDataDto.getSearchKey());
            BoolQueryBuilder childBoolQueryBuilder = new BoolQueryBuilder().should(matchPhraseQueryBuilder).should(matchPhraseQueryBuilder1);
            boolQuery.filter(childBoolQueryBuilder);
//            QueryBuilders.fuzzyQuery("title")
//            boolQuery.filter(boolQueryBuilder);
        }
        if(!StringUtils.isBlank(baseDataDto.getPublishStartTime()) || !StringUtils.isBlank(baseDataDto.getPublishEndTime())) {
            String startTime = baseDataDto.getPublishStartTime();
            String endTime = baseDataDto.getPublishEndTime();
            RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("publishDate");
            //有闭合时间区间速度会比较快
            if (StringUtils.isBlank(baseDataDto.getPublishStartTime())) {
                //开始时间为空，默认为：
                startTime = "2015-01-01 00:00:00";
            }
            if (StringUtils.isBlank(baseDataDto.getPublishEndTime())) {
                //结束时间为空，默认为：当前时间
                endTime = DateUtil.formatDateTime(new Date());

            }
            rangeQuery.gt(EsDateUtil.esFieldDateFormat(startTime));
            rangeQuery.lt(EsDateUtil.esFieldDateFormat(endTime));
            boolQuery.filter(rangeQuery);
        }
        //打印e查询语句
        System.out.println(boolQuery.toString());
        searchSourceBuilder.query(boolQuery);
        System.out.println(searchSourceBuilder.toString());
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = null;
        try{
            searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        }catch (Exception e){
            logger.info("查询es库失败");
            e.printStackTrace();
            throw new RuntimeException("查询es库列表失败");
        }
        SearchHits searchHits = searchResponse.getHits();
        long es = System.currentTimeMillis();
        System.out.println("调用es结束:"+l);
        System.out.println("调用es时间:"+(es-l));
//        List<CisAnsBasedata> list = new ArrayList<>();
        List<Long> list = new ArrayList<>();
        SearchHit[] hits = searchHits.getHits();
        long data = System.currentTimeMillis();
        System.out.println("调用数据库:"+data);
        for (SearchHit hit :hits) {
            String baseDataString = hit.getSourceAsString();
            Basedata baseData = JSON.parseObject(baseDataString, Basedata.class);
//            baseData.setPublishDate(EsDateUtil.esFieldDateMapping(baseData.getPublishDate()));
//            baseData.setCreateDate(EsDateUtil.esFieldDateMapping(baseData.getPublishDate()));
//            long datastart = System.currentTimeMillis();
//            System.out.println("实际调用数据库:"+datastart);
//            CisAnsBasedata cisAnsBasedata = cisAnsBasedataMapper.queryById(new Long(baseData.getId()));
//            long end = System.currentTimeMillis();
//            System.out.println("实际调用数据库:"+end);
//            System.out.println("实际调用数据库时间:"+(end-datastart));
//            list.add(cisAnsBasedata);
            list.add(new Long(baseData.getId()));
        }
        long datastart = System.currentTimeMillis();
        System.out.println("实际调用数据库:"+datastart);
        List<CisAnsBasedata> basedataList =new ArrayList<>();
        if(list!=null && list.size()>0){
            //basedataList = cisAnsBasedataMapper.selectBatchIds(list);
            basedataList = cisAnsBasedataMapper.selectByIdsOld(list);
        }
        long dataend = System.currentTimeMillis();
        System.out.println("调用数据库:"+dataend);
        System.out.println("调用数据库时间:"+(dataend-data));
        Map<String,Object> result = new HashMap<>();
//        result.put("total",searchHits.getTotalHits().value);
//        result.put("list",list);
//        result.put("pageNum",baseDataDto.getPageNum());
//        result.put("pageSize",baseDataDto.getPageSize());
        Page<CisAnsBasedata> page = new Page<CisAnsBasedata>(baseDataDto.getPageNum(), baseDataDto.getPageSize());
        page.setTotal(searchHits.getTotalHits().value);
        page.setRecords(basedataList);
        //result.put("records",basedataList);
        //result.put("total",searchHits.getTotalHits().value);
        //result.put("size",baseDataDto.getPageSize());
        //result.put("current",baseDataDto.getPageNum());
        //result.put("pages",searchHits.getTotalHits().value/ baseDataDto.getPageSize()+1);
        return page;
    }
    /**
     * 从es库中查询数据
     * @param baseDataDto
     * @return
     */
    @Override
    public Page<CisAnsBasedata> findEsByKey(BaseDataDto baseDataDto,List<Long> webTypeList) {
        long l = System.currentTimeMillis();
        System.out.println("调用es:"+l);
        SearchRequest searchRequest = new SearchRequest("kgj");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        int fromPage = (baseDataDto.getPageNum()-1) * baseDataDto.getPageSize();
        //设置分页参数
        //共返回几条数据
        searchSourceBuilder.size(baseDataDto.getPageSize());
        //from标识从第几条开始
        searchSourceBuilder.from(fromPage);
        //设置排序字段
        searchSourceBuilder.sort("publishDate", SortOrder.DESC);
        //默认最大数量是10000，设置为true后，显示准确数量
        searchSourceBuilder.trackTotalHits(true);
        //创建查询对象
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        if(baseDataDto.getDelflag()!=null && !(baseDataDto.getDelflag().equals(0L))){
            boolQuery.filter(QueryBuilders.termQuery("delflag",baseDataDto.getDelflag()));
        }
        if (!StringUtils.isBlank(baseDataDto.getSearchKey())) {
            String[] sArray = baseDataDto.getSearchKey().split(" ");
            for (String s : sArray) {
                MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("title", s);
                MatchPhraseQueryBuilder matchPhraseQueryBuilder1 = QueryBuilders.matchPhraseQuery("contentNoTag", s);
                BoolQueryBuilder childBoolQueryBuilder = new BoolQueryBuilder().should(matchPhraseQueryBuilder).should(matchPhraseQueryBuilder1);
                boolQuery.filter(childBoolQueryBuilder);
            }
        }
        if(!StringUtils.isBlank(baseDataDto.getPublishStartTime()) || !StringUtils.isBlank(baseDataDto.getPublishEndTime())) {
            String startTime = baseDataDto.getPublishStartTime();
            String endTime = baseDataDto.getPublishEndTime();
            RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("publishDate");
            //有闭合时间区间速度会比较快
            if (StringUtils.isBlank(baseDataDto.getPublishStartTime())) {
                //开始时间为空，默认为：
                startTime = "2015-01-01 00:00:00";
            }
            if (StringUtils.isBlank(baseDataDto.getPublishEndTime())) {
                //结束时间为空，默认为：当前时间
                endTime = DateUtil.formatDateTime(new Date());

            }
            rangeQuery.gt(EsDateUtil.esFieldDateFormat(startTime));
            rangeQuery.lt(EsDateUtil.esFieldDateFormat(endTime));
            boolQuery.filter(rangeQuery);
        }
        //add lihuawei 增加分数条件
        if(baseDataDto.getMax()>0||baseDataDto.getMin()>0){

            RangeQueryBuilder scoreQuery = QueryBuilders.rangeQuery("publishDate");
            scoreQuery.gt(baseDataDto.getMin());
            if(baseDataDto.getMax()>0){

                scoreQuery.lt(baseDataDto.getMax());
            }
            boolQuery.filter(scoreQuery);
        }


        //打印e查询语句
        System.out.println(boolQuery.toString());
        searchSourceBuilder.query(boolQuery);
        System.out.println(searchSourceBuilder.toString());
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = null;
        try{
            searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        }catch (Exception e){
            logger.info("查询es库失败");
            e.printStackTrace();
            throw new RuntimeException("查询es库列表失败");
        }
        SearchHits searchHits = searchResponse.getHits();
        long es = System.currentTimeMillis();
        System.out.println("调用es结束:"+l);
        System.out.println("调用es时间:"+(es-l));
//        List<CisAnsBasedata> list = new ArrayList<>();
        List<Long> list = new ArrayList<>();
        SearchHit[] hits = searchHits.getHits();
        long data = System.currentTimeMillis();
        System.out.println("调用数据库:"+data);
        for (SearchHit hit :hits) {
            String baseDataString = hit.getSourceAsString();
            Basedata baseData = JSON.parseObject(baseDataString, Basedata.class);
            list.add(new Long(baseData.getId()));
        }
        long datastart = System.currentTimeMillis();
        System.out.println("实际调用数据库:"+datastart);
        List<CisAnsBasedata> basedataList =new ArrayList<>();
        if(list.size() > 0){
            basedataList = cisAnsBasedataMapper.selectByOlnyIds(list,webTypeList,baseDataDto.getSiteId());
        }
        long dataend = System.currentTimeMillis();
        System.out.println("调用数据库:"+dataend);
        System.out.println("调用数据库时间:"+(dataend-data));
        Page<CisAnsBasedata> page = new Page<>(baseDataDto.getPageNum(), baseDataDto.getPageSize());
//        page.setTotal(searchHits.getTotalHits().value);
        page.setTotal(basedataList.size());
        page.setRecords(basedataList);
        return page;
    }

    /**
     * 涉密信息确认保存
     * @param cisAnsBasedata
     */
    @Override
    @Transactional
    public void edit(CisAnsBasedata cisAnsBasedata,Long delflag) {
//        String locale = cisAnsBasedataMapper.queryLocaleById(cisAnsBasedata.getId());
//        if(StringUtils.isNotBlank(locale) ){
//            int i = Integer.parseInt(locale);
//            String locale1 = cisAnsBasedata.getLocale();
//            if(StringUtils.isNotBlank(locale1)){
//                int i1 = Integer.parseInt(locale1);
//                if(i>=i1){
//                    //如果数据库中的审核状态比传过来的状态大，比如：数据库中是4，传过来是3，那么还是以数据库4为准，'审核状态：1：未查看，2：已查看，3：已修改，4：已确认'
//                    cisAnsBasedata.setLocale(locale);
//                }
//            }else{
//                //审核状态为空，不做处理，直接返回
//                return;
//            }
//        }

        //1.先更新baseData表中的内容

        //把内容中的src=“http://192.168.1.134:8001 替换成src="
        //如果是base64方式，要通过base64的值找到数据库中MD5的值，替换掉，然后把src="data:image/png;base64,替换为src="
//		cisAnsBasedata.setContent(cisAnsBasedata.getContentStringTwo().getBytes());
        String text = Jsoup.parse(cisAnsBasedata.getContentStringTwo()).text();
        cisAnsBasedata.setContentNoTagString(text);
        int i = cisAnsBasedataMapper.updateById(cisAnsBasedata);
        if(i!=1){
            logger.info("审核信息保存到basedata表中失败！");
            throw new RuntimeException("审核信息保存失败！");
        }
        if(delflag!=null){
            //2.同时更新base_data_type表中delflag的字段为
            List<BasedataType> typeList = baseDataTypeMapper.selectByBid(cisAnsBasedata.getId());
            if(CollectionUtils.isNotEmpty(typeList)){
                BasedataType basedataType = new BasedataType();
                basedataType.setId(typeList.get(0).getId());
                basedataType.setDelflag(delflag);
                int i1 = baseDataTypeMapper.updateById(basedataType);
                if(i1 !=1){
                    logger.info("审核信息保存到basedataType表中失败！");
                    throw new RuntimeException("审核信息保存失败！");
                }
            }
        }
        //3.保存的时候同步信息到es库
        Basedata basedata = baseDataMapper.queryById(cisAnsBasedata.getId());
        basedata.setContent(null);
        basedata.setFeaturewords(null);
        basedata.setContentNoTag(text);
        basedata.setPublishDate(EsDateUtil.esFieldDateFormat(basedata.getPublishDate()));
        basedata.setCreateDate(EsDateUtil.esFieldDateFormat(basedata.getCreateDate()));
        if(delflag!=null){
        basedata.setDelflag(delflag);
        }
        if(StringUtils.isNotBlank(cisAnsBasedata.getLocale())){
            basedata.setLocale(cisAnsBasedata.getLocale());
        }
        String s = JSON.toJSONString(basedata);
        boolean kgj = esOpUtil.docUpdateById("kgj", String.valueOf(cisAnsBasedata.getId()), s);
        if(!kgj){
            logger.info("审核信息更新es库失败！");
            throw new RuntimeException("审核信息确认保存失败");
        }
    }

    /**
     * 点击审核
     * @param cisAnsBasedata
     */
    @Override
    @Transactional
    public void clickCheck(CisAnsBasedata cisAnsBasedata) {
        String locale = cisAnsBasedataMapper.queryLocaleById(cisAnsBasedata.getId());
        if(StringUtils.isNotBlank(locale) ){
            int i = Integer.parseInt(locale);
            String locale1 = cisAnsBasedata.getLocale();
            if(StringUtils.isNotBlank(locale1)){
                int i1 = Integer.parseInt(locale1);
                if(i>=i1){
                    //如果数据库中的审核状态比传过来的状态大，比如：数据库中是4，传过来是3，那么还是以数据库4为准，'审核状态：1：未查看，2：已查看，3：已修改，4：已确认'
                    return;
                }
            }else{
                //审核状态为空，不做处理，直接返回
                return;
            }
        }
//        String locale = cisAnsBasedataMapper.queryLocaleById(cisAnsBasedata.getId());
//        if(StringUtils.isNotBlank(locale)){
//            //审核状态不为空，不做处理，直接返回
//            return;
//        }
        CisAnsBasedata basedata = new CisAnsBasedata();
        basedata.setId(cisAnsBasedata.getId());
        //已经查看
        //		'审核状态：null或者1：未查看，2：已查看，3：已修改，4：已确认'

        basedata.setLocale("2");
        int i = cisAnsBasedataMapper.updateById(basedata);
        if(i!=1){
            logger.info("审核信息保存到basedata表中失败！");
            throw new RuntimeException("审核信息保存失败！");
        }
        //更新到es库
        Basedata basedata1 = baseDataMapper.queryById(cisAnsBasedata.getId());
        basedata1.setContent(null);
        basedata1.setFeaturewords(null);
        basedata1.setPublishDate(EsDateUtil.esFieldDateFormat(basedata.getPublishDate()));
        basedata1.setCreateDate(EsDateUtil.esFieldDateFormat(basedata.getCreateDate()));
        basedata1.setLocale("2");
        String s = JSON.toJSONString(basedata1);
        boolean kgj = esOpUtil.docUpdateById("kgj", String.valueOf(cisAnsBasedata.getId()), s);
        if(!kgj){
            logger.info("审核信息更新es库失败！");
            throw new RuntimeException("审核信息失败");
        }
    }
}
