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

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.annotation.PostConstruct;

import com.alibaba.fastjson.JSON;
import com.yeejoin.amos.boot.module.jcs.api.entity.AlertFormValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.DependsOn;
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.stereotype.Service;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;

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.jcs.api.dto.ESAlertCalledDto;
import com.yeejoin.amos.boot.module.jcs.api.dto.ESAlertCalledRequestDto;
import com.yeejoin.amos.boot.module.jcs.api.entity.AlertCalled;
import com.yeejoin.amos.boot.module.jcs.api.entity.ESAlertCalled;
import com.yeejoin.amos.boot.module.jcs.api.enums.AlertStatusEnum;
import com.yeejoin.amos.boot.module.jcs.biz.dao.ESAlertCalledRepository;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

/**
 *
 * <pre>
 * 警情信息ES检索服务
 * </pre>
 *
 * @author gwb
 * @version $Id: ESAlertCalledService.java, v 0.1 2021年6月19日 下午5:12:01 gwb Exp $
 */
@Service
public class ESAlertCalledService {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;

    @Autowired
    private ESAlertCalledRepository esAlertCalledRepository;

	@Autowired
	private AlertCalledServiceImpl alertCalledService;

    @Value("${alertcall.es.synchrony.time}")
	private Long time;

    private  static  final String CALLTIMELONG="callTimeLong";
    
	@PostConstruct
	public void init() throws Exception
	{
		//初始化ES，重建索引
		initEs();
	}

    /**
     * 重建索引
     */
    public Boolean initEs()  {
        esAlertCalledRepository.deleteAll();
        /**
         * 同步历史48小时以内的警情处置记录
         */
        QueryWrapper<AlertCalled> wrapper = new QueryWrapper<>();

        long currentTime = System.currentTimeMillis() ;
        if (ValidationUtil.isEmpty(time)) //默认为同步48小时
		{
        	currentTime = currentTime - 48*60*60*1000;
		}else
		{
			currentTime = currentTime - time*60*60*1000;
		}
        Date date=new Date(currentTime);

        wrapper.ge("call_time", date);
        wrapper.isNull("father_alert");

        List<AlertCalled> alertCalleds = alertCalledService.list(wrapper);
        if (!ValidationUtil.isEmpty(alertCalleds))
		{


			saveAlertCalledToES(alertCalleds);
		}

        return true;
    }

    /**
     *
     * <pre>
     * 批量保存
     * </pre>
     *
     * @param
     */
    public void saveAll(List<AlertCalled> alertCalleds) {

    	if (!ValidationUtil.isEmpty(alertCalleds))
		{
			for (AlertCalled alertCalled : alertCalleds)
			{
				this.saveAlertCalledToES(alertCalled);
			}
		}
    }

    /**
     *
     * <pre>
     * 根据警情记录批量保存
     * </pre>
     *
     * @param
     */
    public ESAlertCalled saveAlertCalledToES(AlertCalled alertCalled)
    {
    	ESAlertCalled esAlertCalled = new ESAlertCalled();
    	esAlertCalled.setSequenceNbr(alertCalled.getSequenceNbr());
    	esAlertCalled.setAlertType(alertCalled.getAlertType());
    	esAlertCalled.setAlertTypeCode(alertCalled.getAlertTypeCode());
    	esAlertCalled.setCallTime(alertCalled.getCallTime());
    	esAlertCalled.setCallTimeLong(alertCalled.getCallTime()!=null?alertCalled.getCallTime().getTime():null);
    	esAlertCalled.setContactUser(alertCalled.getContactUser());
    	esAlertCalled.setContactPhone(alertCalled.getContactPhone());
    	esAlertCalled.setAddress(alertCalled.getAddress());
    	esAlertCalled.setAlertStage(alertCalled.getAlertStage());
    	esAlertCalled.setAlertStatus(alertCalled.getAlertStatus());
		esAlertCalled.setForcedLandingTrack(alertCalled.getForcedLandingTrack());
		esAlertCalled.setFlightNumber(alertCalled.getFlightNumber());
		if(alertCalled.getLandingTime() != null ){
			Date date = new Date();
			try {
				date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(alertCalled.getLandingTime());
			} catch (ParseException e) {
				throw new BadRequest("系统异常");
			}
			esAlertCalled.setLandingTime(date.getTime());
		}
    	if (alertCalled.getAlertStatus())
    	{
    		esAlertCalled.setAlertStatusStr(AlertStatusEnum.CLOSED.getCode());
    	}else
    	{
    		esAlertCalled.setAlertStatusStr(AlertStatusEnum.UNCLOSED.getCode());
    	}
    	esAlertCalled.setResponseLevelCode(alertCalled.getResponseLevelCode());
    	esAlertCalled.setUnitInvolved(alertCalled.getUnitInvolved());
    	esAlertCalled.setCoordinateX(alertCalled.getCoordinateX());
    	esAlertCalled.setCoordinateY(alertCalled.getCoordinateY());

    	esAlertCalledRepository.save(esAlertCalled);

    	return esAlertCalled;
    }


	public List<ESAlertCalled> saveAlertCalledToES(List<AlertCalled> alertCalleds)
	{
		List<ESAlertCalled> list1=new ArrayList<>();
		for (AlertCalled alertCalled : alertCalleds)
		{
			ESAlertCalled esAlertCalled = new ESAlertCalled();
			esAlertCalled.setSequenceNbr(alertCalled.getSequenceNbr());
			esAlertCalled.setAlertType(alertCalled.getAlertType());
			esAlertCalled.setAlertTypeCode(alertCalled.getAlertTypeCode());
			esAlertCalled.setCallTime(alertCalled.getCallTime());
			esAlertCalled.setCallTimeLong(alertCalled.getCallTime()!=null?alertCalled.getCallTime().getTime():null);
			esAlertCalled.setContactUser(alertCalled.getContactUser());
			esAlertCalled.setContactPhone(alertCalled.getContactPhone());
			esAlertCalled.setAddress(alertCalled.getAddress());
			esAlertCalled.setAlertStage(alertCalled.getAlertStage());
			esAlertCalled.setAlertStatus(alertCalled.getAlertStatus());
			if (alertCalled.getAlertStatus())
			{
				esAlertCalled.setAlertStatusStr(AlertStatusEnum.CLOSED.getCode());
			}else
			{
				esAlertCalled.setAlertStatusStr(AlertStatusEnum.UNCLOSED.getCode());
			}
			esAlertCalled.setResponseLevelCode(alertCalled.getResponseLevelCode());
			esAlertCalled.setUnitInvolved(alertCalled.getUnitInvolved());
			esAlertCalled.setCoordinateX(alertCalled.getCoordinateX());
			esAlertCalled.setCoordinateY(alertCalled.getCoordinateY());
			list1.add(esAlertCalled);
		}

		esAlertCalledRepository.saveAll(list1);
		return list1;
	}




    /**
     *
     * <pre>
     *  从ES库批量删除
     * </pre>
     *
     * @param ids
     * @return
     * @throws Exception
     */
    public Boolean deleteById(List<Long> ids){
        if (!ValidationUtil.isEmpty(ids)) {
        	for (Long sequenceNbr : ids) {
        		if (esAlertCalledRepository.existsById(sequenceNbr)) {
        			esAlertCalledRepository.deleteById(sequenceNbr);
        		}
        	}
        }

        return true;
    }

    /**
     * 根据id查询ES存储对象
     *
     * @param sequenceNbr id
     * @return ES实例
     */
    public ESAlertCalled queryById(Long sequenceNbr) {
        return esAlertCalledRepository.findById(sequenceNbr).orElse(null);
    }

    /**
     * 根据关键字查询文档，关键字不为空时按相关性从大到小排序
     *
     * @param
     * @param current  当前页码
     * @param size     页面大小
     * @return
     */
    @SuppressWarnings({ "rawtypes" })
	public Page<ESAlertCalledDto> queryByKeys(ESAlertCalledRequestDto alertCalledVo, int current, int size)
    {
    	Page<ESAlertCalledDto> result = new Page<ESAlertCalledDto>(current, size);

    	String[] alertStatus = alertCalledVo.getAlertStatus();
    	if (ValidationUtil.isEmpty(alertStatus))
		{
    		return result;
		}

    	AlertCalled alertCalled = alertCalledVo.getAlertCalled();
    	if (ValidationUtil.isEmpty(alertCalled))
		{
			return result;
		}
        /**
         * 通用匹配规则，条件构建
         */
    	BoolQueryBuilder boolMustAll = QueryBuilders.boolQuery();
    	//警情状态
    	BoolQueryBuilder qb0 = QueryBuilders.boolQuery();
    	for (String status : alertStatus)
		{
    		AlertStatusEnum alertStatusEnum = AlertStatusEnum.getEnum(status);
    		if (!ValidationUtil.isEmpty(alertStatusEnum))
			{
    			qb0.should(QueryBuilders.termQuery("alertStatusStr.keyword", alertStatusEnum.getCode()));
			}
		}
    	boolMustAll.must(qb0);
    	
    	BoolQueryBuilder boolMust = QueryBuilders.boolQuery();
        //接警时间，距离当前时间不超过半小时的
        long currentTime = System.currentTimeMillis() ;
        currentTime = currentTime - 30*60*1000;
        BoolQueryBuilder qb1 = QueryBuilders.boolQuery()
        		.must(QueryBuilders.rangeQuery(CALLTIMELONG).gte(currentTime));
        boolMust.should(qb1);
        //报警人及报警电话一致
        if (!ValidationUtil.isEmpty(alertCalled.getContactUser()) && !ValidationUtil.isEmpty(alertCalled.getContactPhone()))
		{
        	BoolQueryBuilder qb2 = QueryBuilders.boolQuery()
        			.must(QueryBuilders.termQuery("contactUser.keyword", alertCalled.getContactUser()))
        			.must(QueryBuilders.termQuery("contactPhone.keyword", alertCalled.getContactPhone()));
        	boolMust.should(qb2);
		}
        //事发地点一致，或相距不超过200米的
        if (!ValidationUtil.isEmpty(alertCalled.getAddress()))
		{
        	BoolQueryBuilder qb3 = QueryBuilders.boolQuery()
        			.should(QueryBuilders.matchQuery("address", alertCalled.getAddress()));
        	boolMust.should(qb3);
		}
        //警情类型一致
        BoolQueryBuilder qb4 = QueryBuilders.boolQuery()
        		.must(QueryBuilders.termQuery("alertTypeCode.keyword", alertCalled.getAlertTypeCode()));
        boolMust.should(qb4);
        //事发单位名称一致
        if (!ValidationUtil.isEmpty(alertCalled.getUnitInvolved()))
		{
        	BoolQueryBuilder qb5 = QueryBuilders.boolQuery()
        			.must(QueryBuilders.matchQuery("unitInvolved", alertCalled.getUnitInvolved()));
        	boolMust.should(qb5);
		}
		//过滤120警情
		BoolQueryBuilder qb6 = QueryBuilders.boolQuery()
				.mustNot(QueryBuilders.termQuery("alertTypeCode", "1214"));

		if (!ValidationUtil.isEmpty(alertCalledVo.getAlertFormValue())){
			List<AlertFormValue> alertFormValue = alertCalledVo.getAlertFormValue();
			for (AlertFormValue formValue : alertFormValue) {
				if (formValue.getFieldCode().equals("forcedLandingTrack")&& formValue.getFieldValue() != null){
					BoolQueryBuilder qb7 = QueryBuilders.boolQuery()
							.must(QueryBuilders.termQuery("forcedLandingTrack.keyword", formValue.getFieldValue()));
					boolMust.must(qb7);
				}
				if (formValue.getFieldCode().equals("flightNumber") && formValue.getFieldValue() != null){
					BoolQueryBuilder qb8 = QueryBuilders.boolQuery()
							.must(QueryBuilders.termQuery("flightNumber.keyword", formValue.getFieldValue()));
					boolMust.must(qb8);
				}

				if (formValue.getFieldCode().equals("landingTime")&& formValue.getFieldValue() != null){
					BoolQueryBuilder qb9 = QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery("landingTime").gte(currentTime));
					boolMust.must(qb9);
				}
			}


		}


		/**
         * 一般火灾，条件构造
         */


        boolMust.minimumShouldMatch(1);//至少满足一个
        boolMustAll.must(boolMust);
        boolMustAll.must(qb6);




		// 创建查询构造器
		NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder()
				//过滤条件
				.withQuery(boolMustAll)
				// 排序
				.withSort(SortBuilders.fieldSort(CALLTIMELONG).order(SortOrder.DESC))
				// 分页
				.withPageable(PageRequest.of(current, size))
				;

        List<ESAlertCalledDto> list = new LinkedList<>();
        long totle = 0;
		try
		{
			SearchHits<ESAlertCalled> searchHits =elasticsearchTemplate.search(queryBuilder.build(), ESAlertCalled.class);
			
			for (SearchHit searchHit : searchHits.getSearchHits())
			{
				JSONObject jsonObject = (JSONObject) JSON.toJSON(searchHit.getContent());
				ESAlertCalledDto eSAlertCalled = JSON.toJavaObject(jsonObject, ESAlertCalledDto.class);
				list.add(eSAlertCalled);
			}
			totle =searchHits.getTotalHits();
		}
		catch (Exception e)
		{
			// TODO: handle exception
		}
        result.setRecords(list);
        result.setTotal(totle);

        return result;
    }
	@SuppressWarnings({ "rawtypes" })
	public Page<ESAlertCalledDto> queryByKeys(ESAlertCalledRequestDto alertCalledVo, int current, int size,String type)
	{
		Page<ESAlertCalledDto> result = new Page<ESAlertCalledDto>(current, size);

		String[] alertStatus = alertCalledVo.getAlertStatus();
		if (ValidationUtil.isEmpty(alertStatus))
		{
			return result;
		}

		AlertCalled alertCalled = alertCalledVo.getAlertCalled();
		if (ValidationUtil.isEmpty(alertCalled))
		{
			return result;
		}
		/**
		 * 通用匹配规则，条件构建
		 */
		BoolQueryBuilder boolMustAll = QueryBuilders.boolQuery();
		//警情状态
		BoolQueryBuilder qb0 = QueryBuilders.boolQuery();
		for (String status : alertStatus)
		{
			AlertStatusEnum alertStatusEnum = AlertStatusEnum.getEnum(status);
			if (!ValidationUtil.isEmpty(alertStatusEnum))
			{
				qb0.should(QueryBuilders.termQuery("alertStatusStr.keyword", alertStatusEnum.getCode()));
			}
		}
		boolMustAll.must(qb0);

		BoolQueryBuilder boolMust = QueryBuilders.boolQuery();
		//接警时间，距离当前时间不超过半小时的
		long currentTime = System.currentTimeMillis() ;
		currentTime = currentTime - 30*60*1000;
		BoolQueryBuilder qb1 = QueryBuilders.boolQuery()
				.must(QueryBuilders.rangeQuery(CALLTIMELONG).gte(currentTime));
		boolMust.should(qb1);
		//报警人及报警电话一致
		if (!ValidationUtil.isEmpty(alertCalled.getContactUser()) && !ValidationUtil.isEmpty(alertCalled.getContactPhone()))
		{
			BoolQueryBuilder qb2 = QueryBuilders.boolQuery()
					.must(QueryBuilders.termQuery("contactUser.keyword", alertCalled.getContactUser()))
					.must(QueryBuilders.termQuery("contactPhone.keyword", alertCalled.getContactPhone()));
			boolMust.should(qb2);
		}
		//事发地点一致，或相距不超过200米的
		if (!ValidationUtil.isEmpty(alertCalled.getAddress()))
		{
			BoolQueryBuilder qb3 = QueryBuilders.boolQuery()
					.should(QueryBuilders.matchQuery("address", alertCalled.getAddress()));
			boolMust.should(qb3);
		}
		//警情类型一致
		BoolQueryBuilder qb4 = QueryBuilders.boolQuery()
				.must(QueryBuilders.termQuery("alertTypeCode.keyword", alertCalled.getAlertTypeCode()));
		//事发单位名称一致
		if (!ValidationUtil.isEmpty(alertCalled.getUnitInvolved()))
		{
			BoolQueryBuilder qb5 = QueryBuilders.boolQuery()
					.must(QueryBuilders.matchQuery("unitInvolved", alertCalled.getUnitInvolved()));
			boolMust.should(qb5);
		}

		/**
		 * 一般火灾，条件构造
		 */


		boolMust.minimumShouldMatch(1);//至少满足一个

		boolMustAll.must(boolMust);
		boolMustAll.must(qb4);



		// 创建查询构造器
		NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder()
				// 分页
				.withPageable(PageRequest.of(current, size))
				// 排序
                .withSort(SortBuilders.fieldSort(CALLTIMELONG).order(SortOrder.DESC))
				//过滤条件
				.withQuery(boolMustAll)
				;


		List<ESAlertCalledDto> list = new LinkedList<>();
		long totle = 0;
		try
		{
			SearchHits<ESAlertCalled> searchHits =elasticsearchTemplate.search(queryBuilder.build(), ESAlertCalled.class);

			for (SearchHit searchHit : searchHits.getSearchHits())
			{
				JSONObject jsonObject = (JSONObject) JSON.toJSON(searchHit.getContent());
				ESAlertCalledDto eSAlertCalled =JSON.toJavaObject(jsonObject, ESAlertCalledDto.class);
				list.add(eSAlertCalled);
			}
			totle =searchHits.getTotalHits();
		}
		catch (Exception e)
		{
			// TODO: handle exception
		}
		result.setRecords(list);
		result.setTotal(totle);

		return result;
	}

}
