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

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.dto.AlertCalledDto;
import com.yeejoin.amos.boot.module.tzs.api.dto.ESAlertCalledDto;
import com.yeejoin.amos.boot.module.tzs.api.dto.ESAlertCalledRequestDto;
import com.yeejoin.amos.boot.module.tzs.api.entity.AlertCalled;
import com.yeejoin.amos.boot.module.tzs.api.entity.ESAlertCalled;
import com.yeejoin.amos.boot.module.tzs.api.enums.AlertStatusEnum;
import com.yeejoin.amos.boot.module.tzs.biz.dao.ESAlertCalledRepository;
import com.yeejoin.amos.boot.module.tzs.biz.utils.BeanDtoVoUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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 javax.annotation.PostConstruct;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 *
 * <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;
    
    
	@PostConstruct
	public void init() throws Exception
	{
		//初始化ES，重建索引
		initEs();
	}

    /**
     * 重建索引
     */
    public Boolean initEs() throws Exception {
        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);

        List<AlertCalled> alertCalleds = alertCalledService.list(wrapper);
        if (!ValidationUtil.isEmpty(alertCalleds))
		{
    		for (AlertCalled alertCalled : alertCalleds)
    		{
    			saveAlertCalledToES(alertCalled);
    		}
		}
        return true;
    }


    /**
     *
     * <pre>
     * 根据警情记录批量保存
     * </pre>
     *
     * @param alertCalled 警情信息列表
     */
    public ESAlertCalled saveAlertCalledToES(AlertCalled alertCalled) throws Exception
    {
    	ESAlertCalled esAlertCalled = new ESAlertCalled();
    	esAlertCalled.setSequenceNbr(alertCalled.getSequenceNbr());
    	esAlertCalled.setAlarmType(alertCalled.getAlarmType());
    	esAlertCalled.setAlarmTypeCode(alertCalled.getAlarmTypeCode());
    	esAlertCalled.setCallTime(alertCalled.getCallTime());
    	esAlertCalled.setCallTimeLong(alertCalled.getCallTime()!=null?alertCalled.getCallTime().getTime():null);
    	esAlertCalled.setContactPhone(alertCalled.getContactPhone());
    	esAlertCalled.setAddress(alertCalled.getAddress());
    	esAlertCalled.setAlertStage(alertCalled.getAlertStage());
    	esAlertCalled.setAlertStatus(alertCalled.getAlertStatus());
		esAlertCalled.setEmergencyCall(alertCalled.getEmergencyCall());
		esAlertCalled.setDeviceId(alertCalled.getDeviceId());
    	if (alertCalled.getAlertStatus())
    	{
    		esAlertCalled.setAlertStatusStr(AlertStatusEnum.CLOSED.getCode());
    	}else
    	{
    		esAlertCalled.setAlertStatusStr(AlertStatusEnum.UNCLOSED.getCode());
    	}

    	esAlertCalledRepository.save(esAlertCalled);

    	return esAlertCalled;
    }

    /**
     * 根据关键字查询文档，关键字不为空时按相关性从大到小排序
     *
     * @param alertCalledVo 关键字
     * @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 = BeanDtoVoUtils.convert(alertCalledVo.getAlertCalledDto(),AlertCalled.class);
    	if (ValidationUtil.isEmpty(alertCalled))
		{
			return result;
		}
        /**
         * 通用匹配规则，条件构建
         */
    	BoolQueryBuilder boolMust = 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()));
			}
		}
    	boolMust.must(qb0);
        //接警时间，距离当前时间不超过两个小时的
        long currentTime = System.currentTimeMillis() ;
        currentTime = currentTime - 120*60*1000;
        BoolQueryBuilder qb1 = QueryBuilders.boolQuery()
        		.filter(QueryBuilders.rangeQuery("callTimeLong").gte(currentTime));
        boolMust.must(qb1);
        //报警电话一致
        if (!ValidationUtil.isEmpty(alertCalled.getEmergencyCall()) && !ValidationUtil.isEmpty(alertCalled.getContactPhone()))
		{
        	BoolQueryBuilder qb2 = QueryBuilders.boolQuery()
        			.should(QueryBuilders.termQuery("emergencyCall.keyword", alertCalled.getEmergencyCall()))
        			.should(QueryBuilders.termQuery("contactPhone.keyword", alertCalled.getContactPhone()));
        	boolMust.must(qb2);
		}
        //事发地点一致，或相距不超过200米的
        if (!ValidationUtil.isEmpty(alertCalled.getAddress()))
		{
        	BoolQueryBuilder qb3 = QueryBuilders.boolQuery()
        			.filter(QueryBuilders.matchQuery("address", alertCalled.getAddress()));
        	boolMust.should(qb3);
		}
        //警情类型一致
        BoolQueryBuilder qb4 = QueryBuilders.boolQuery()
        		.filter(QueryBuilders.termQuery("alarmTypeCode", alertCalled.getAlarmTypeCode()));
        boolMust.must(qb4);
        //使用单位名称一致
        if (!ValidationUtil.isEmpty(alertCalled.getUseUnit()))
		{
        	BoolQueryBuilder qb5 = QueryBuilders.boolQuery()
        			.filter(QueryBuilders.termQuery("useUnit.keyword", alertCalled.getUseUnit()));
        	boolMust.must(qb5);
		}
        //电梯识别码一致
        if(!ValidationUtil.isEmpty(alertCalled.getDeviceId())) {
			BoolQueryBuilder qb6 = QueryBuilders.boolQuery()
					.filter(QueryBuilders.termQuery("deviceId.keyword", alertCalled.getDeviceId()));
			boolMust.must(qb6);
		}

        /**
         * 困人救援,故障报修,投诉咨询 条件构造
         */

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

        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) JSONObject.toJSON(searchHit.getContent());
				ESAlertCalledDto eSAlertCalled =JSONObject.toJavaObject(jsonObject, ESAlertCalledDto.class);
				list.add(eSAlertCalled);
			}
			totle =searchHits.getTotalHits();
		}
		catch (Exception e)
		{
			// TODO: handle exception
		}
        result.setRecords(list);
        result.setTotal(totle);

        return result;
    }

	/**
	 * 更新索引
	 */
	public ESAlertCalled updateEsAlertCalled(AlertCalledDto alertCalled) throws Exception {
		esAlertCalledRepository.deleteById(alertCalled.getSequenceNbr());
		ESAlertCalled esAlertCalled = new ESAlertCalled();
		esAlertCalled.setSequenceNbr(alertCalled.getSequenceNbr());
		esAlertCalled.setAlarmType(alertCalled.getAlarmType());
		esAlertCalled.setAlarmTypeCode(alertCalled.getAlarmTypeCode());
		esAlertCalled.setCallTime(alertCalled.getCallTime());
		esAlertCalled.setCallTimeLong(alertCalled.getCallTime()!=null?alertCalled.getCallTime().getTime():null);
		esAlertCalled.setContactPhone(alertCalled.getContactPhone());
		esAlertCalled.setAddress(alertCalled.getAddress());
		esAlertCalled.setAlertStage(alertCalled.getAlertStage());
		esAlertCalled.setAlertStatus(alertCalled.getAlertStatus());
		esAlertCalled.setEmergencyCall(alertCalled.getEmergencyCall());
		esAlertCalled.setDeviceId(alertCalled.getDeviceId());
		if (alertCalled.getAlertStatus())
		{
			esAlertCalled.setAlertStatusStr(AlertStatusEnum.CLOSED.getCode());
		}else
		{
			esAlertCalled.setAlertStatusStr(AlertStatusEnum.UNCLOSED.getCode());
		}
		esAlertCalledRepository.save(esAlertCalled);
		return esAlertCalled;
	}

}
