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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yeejoin.amos.boot.biz.common.utils.DateUtils;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.module.common.api.dto.FormValue;
import com.yeejoin.amos.boot.module.common.api.dto.RequestData;
import com.yeejoin.amos.boot.module.jcs.api.dto.*;
import com.yeejoin.amos.boot.module.jcs.api.entity.AlertCalled;
import com.yeejoin.amos.boot.module.jcs.api.entity.AlertFormValue;
import com.yeejoin.amos.boot.module.jcs.api.entity.Template;
import com.yeejoin.amos.boot.module.jcs.api.enums.AlertStageEnums;
import com.yeejoin.amos.boot.module.jcs.api.enums.DutyInfoEnum;
import com.yeejoin.amos.boot.module.jcs.api.mapper.AlertCalledMapper;
import com.yeejoin.amos.boot.module.jcs.api.mapper.AlertSubmittedMapper;
import com.yeejoin.amos.boot.module.jcs.api.mapper.PowerTransferMapper;
import com.yeejoin.amos.boot.module.jcs.api.mapper.TemplateMapper;
import com.yeejoin.amos.boot.module.jcs.api.service.IAlertCalledService;
import com.yeejoin.amos.component.rule.config.RuleConfig;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.typroject.tyboot.component.emq.EmqKeeper;
import org.typroject.tyboot.core.foundation.utils.Bean;
import org.typroject.tyboot.core.foundation.utils.StringUtil;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.utils.ResponseHelper;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* 警情接警记录 服务实现类
*
* @author tb
* @date 2021-06-17
*/
@Service
public class AlertCalledServiceImpl extends BaseService<AlertCalledDto,AlertCalled,AlertCalledMapper> implements IAlertCalledService {

	 @Autowired
	 RedisUtils redisUtils;
	@Autowired
	 AlertCalledMapper alertCalledMapper;
	 
	@Autowired
	private AlertFormValueServiceImpl iAlertFormValueService;
	    
    @Autowired
    private ESAlertCalledService eSAlertCalledService;
	    
    @Autowired
    RuleAlertCalledService ruleAlertCalledService;

	@Autowired
	private EmqKeeper emqKeeper;

	@Value("${mqtt.topic.command.alert.notice}")
	private String topic;

	@Value("${redis.cache.failure.time}")
	private long time;

	@Autowired
	TemplateMapper templateMapper;
	@Autowired
	PowerTransferMapper powerTransferMapper;
	@Autowired
	AlertSubmittedMapper alertSubmittedMapper;
	/**
	 *
	 * 指挥系统 未结束的警情列表
	 *
	 * **/
	@Override
	public List<AlertCalledZhDto> alertCalledListByAlertStatus( RequestData par) {

		List<AlertCalledZhDto> list = alertCalledMapper.alertCalledListByAlertStatus(par);
		return list;

	}
	/**
	 *
	 * 根据灾情id 查询灾情详情
	 *
	 * **/
	@Override
	public Object selectAlertCalledById(Long id) {
		if(redisUtils.hasKey(RedisKey.ALERTCALLED_ID+id)){
			Object obj= redisUtils.get(RedisKey.ALERTCALLED_ID+id);
			return obj;
		}else{
			// 警情基本信息
			AlertCalled alertCalled = this.getById(id);
			QueryWrapper<AlertFormValue> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq("alert_called_id", id);
			// 警情动态表单数据
			List<AlertFormValue> list = iAlertFormValueService.list(queryWrapper);
			List<FormValue> formValue = new ArrayList<FormValue>();
			if(list!=null&&list.size()>0) {
				for (AlertFormValue alertFormValue : list) {
					FormValue value = new FormValue(alertFormValue.getFieldCode(), alertFormValue.getFieldName(), "text", alertFormValue.getFieldValue(),alertFormValue.getBlock());
					formValue.add(value);
				}
			}
			AlertCalledFormDto alertCalledFormVo = new AlertCalledFormDto(alertCalled, formValue);

			redisUtils.set(RedisKey.ALERTCALLED_ID+id, JSON.toJSON(alertCalledFormVo),time);
			return alertCalledFormVo;
		}
	}

	/**
	 * 
	 * <pre>
	 * 保存警情信息
	 * </pre>
	 *
	 * @param alertCalledObjsDto
	 * @return
	 */
	@Transactional(rollbackFor = RuntimeException.class)
	public AlertCalledObjsDto createAlertCalled(AlertCalledObjsDto alertCalledObjsDto) {
		try {
   	    // 警情基本信息
         AlertCalled alertCalled = alertCalledObjsDto.getAlertCalled();
         alertCalled.setCallTime(new Date());  
 		   if(AlertStageEnums.RG.getValue().equals(alertCalled.getAlertSourceCode())||
			AlertStageEnums.RG.getValue().equals(alertCalled.getAlertSourceCode())){
			   alertCalled.setType("0");
		   }else {
			   alertCalled.setType("1");
		   }
         
         // 判断是否归并警情
         if (alertCalled.getFatherAlert() != null) {
             // 警情归并，设置当前警情状态为结束。
             alertCalled.setAlertStatus(true);
             alertCalled.setAlertStage(AlertStageEnums.JQJB.getValue());
             alertCalled.setAlarmType(AlertStageEnums.JQGB.getValue());
             alertCalled.setAlarmTypeCode(AlertStageEnums.JQGB.getCode());
             this.save(alertCalled);
             // 动态表单
             List<AlertFormValue> alertFormValuelist = alertCalledObjsDto.getAlertFormValue();
             // 填充警情主键
                 alertFormValuelist.stream().forEach(alertFormValue -> {
                 alertFormValue.setAlertCalledId(alertCalled.getSequenceNbr());
                 alertFormValue.setAlertTypeCode(alertCalled.getAlertTypeCode());
             });
             // 保存动态表单数据
             iAlertFormValueService.saveBatch(alertFormValuelist);
         } else {
             // 警情报送
             // ****************************************************待确认开发
        	  alertCalled.setAlertStatus(false);
        	  alertCalled.setIsDelete(false);
        	  alertCalled.setAlertStage(AlertStageEnums.LLDP.getValue());
        	  alertCalled.setAlarmType(AlertStageEnums.JQCB.getValue());
              alertCalled.setAlarmTypeCode(AlertStageEnums.JQCB.getCode());
              this.save(alertCalled);

              // 动态表单
              List<AlertFormValue> alertFormValuelist = alertCalledObjsDto.getAlertFormValue();
              // 填充警情主键
                  alertFormValuelist.stream().forEach(alertFormValue -> {
                  alertFormValue.setAlertCalledId(alertCalled.getSequenceNbr());
                  alertFormValue.setAlertTypeCode(alertCalled.getAlertTypeCode());
              });
              // 保存动态表单数据
              iAlertFormValueService.saveBatch(alertFormValuelist);
              alertCalledObjsDto.setAlertCalled(alertCalled);
              alertCalledObjsDto.setAlertFormValue(alertFormValuelist);
              //调用规则          
              ruleAlertCalledService.fireAlertCalledRule(alertCalledObjsDto);
              //通知实战指挥页面发送mqtt 默认发送 String 类型 0, 新警情 1 警情状态变化
			 emqKeeper.getMqttClient().publish(topic, "0".getBytes(), RuleConfig.DEFAULT_QOS, true);

		 }
        
         
         /**
          * 同步保存ES
          */
         eSAlertCalledService.saveAlertCalledToES(alertCalled);
         
		 return alertCalledObjsDto;
		} catch (Exception e) {
			throw new RuntimeException("报送失败，系统异常!");
		}
	 }


	/**
	 * 根据id 修改警情
	 * type：警情相关 操作类型  0警情续报   1非警情确认   2 警情结案
	 *
	 */
	@Override
	@Transactional(rollbackFor = RuntimeException.class)
	public boolean updateAlertCalled(Long id, String code) {
		// TODO Auto-generated method stub
		try {
			switch (code) {
				case "314":
					alertCalledMapper.update(null, new UpdateWrapper<AlertCalled>().eq("sequence_nbr", id)
							.set("alert_status", 1).set("alert_stage", AlertStageEnums.ZBQJ.getValue()).set("alarm_type", AlertStageEnums.FJQ.getValue()).set("alarm_type_code", AlertStageEnums.FJQ.getCode()));
					break;
				case "315":
					alertCalledMapper.update(null, new UpdateWrapper<AlertCalled>().eq("sequence_nbr", id)
							.set("alert_status", 1).set("alert_stage", AlertStageEnums.CZJS.getValue()));
					break;
				default:
					alertCalledMapper.update(null, new UpdateWrapper<AlertCalled>().eq("sequence_nbr", id)
							.set("alert_stage", AlertStageEnums.CZGZ.getValue()));

					break;
			}

			AlertCalled alertCalled = this.getById(id);
			//删除缓存
			redisUtils.del(RedisKey.ALERTCALLED_ID + id);
			/**
			 * 同步更新存ES
			 */
			eSAlertCalledService.saveAlertCalledToES(alertCalled);

			//通知实战指挥页面发送mqtt 默认发送 String 类型 0新警情， 1警情状态变化
			emqKeeper.getMqttClient().publish(topic, "1".getBytes(), RuleConfig.DEFAULT_QOS, true);

			return true;
		} catch (Exception e) {
			throw new RuntimeException("系统异常!");
		}
	}

	private static int comparingByGroupVal(Map<String, Object> map, Map<String, Object> map2, String key) {
		int result = 0;
		if (map.get(key) instanceof Date) {
			long r1 = ((Date) map.get(key)).getTime();
			long r2 = ((Date) map2.get(key)).getTime();
			result = Long.compare(r1, r2);
		}
		return result;
	}

	/**
	 * 根据时间区间查询警情列表信息
	 *
	 * @param beginDate 开始时间
	 * @param endDate 结束时间
	 */
	public List<Map<String, Object>> listByDateRange(String beginDate, String endDate) {
		// 查询指定日期内的警情列表

		List<AlertCalled> alertCalledList =
                this.list(new LambdaQueryWrapper<AlertCalled>().apply(!ValidationUtil.isEmpty(beginDate),
						"call_time >= '" + beginDate + "'").le(true, AlertCalled::getCallTime, endDate));
		Map<String, String> queryParams = Maps.newHashMap();
		queryParams.put("beginDate", beginDate);
		queryParams.put("endDate", endDate);
		List<Map<String, Object>> allList = Lists.newArrayList();
		if (!ValidationUtil.isEmpty(alertCalledList)) {
			Map<String, List<AlertCalled>> alertCalledMap =
					alertCalledList.stream().collect(Collectors.groupingBy(AlertCalled::getAlertTypeCode));
			Map<Long, AlertCalled> calledMap =
					alertCalledList.stream().collect(Collectors.toMap(AlertCalled::getSequenceNbr, Function.identity()));
			alertCalledMap.forEach((alertTypeCode, list) -> {
				allList.addAll(iAlertFormValueService.listAll(alertTypeCode, queryParams));
			});

			allList.forEach(i -> {
				AlertCalled alertCalled = calledMap.get(Long.parseLong(i.get("instanceId").toString()));
				i.putAll(Bean.BeantoMap(alertCalled));
			});
		}
		// 按接警时间正序排序
		allList.sort((e, o) -> comparingByGroupVal(e, o, "callTime"));
		return allList;
	}

	public Map<String, Object> getAlertInfoList(String beginDate, String endDate) {
		Map<String, Object> result = Maps.newHashMap();
		List<Map<String, Object>> list = listByDateRange(beginDate, endDate);
		// 获取接警情况模板
		List<Template> templateList =
				templateMapper.selectList(new LambdaQueryWrapper<Template>().eq(Template::getFormat, false).like(Template::getTypeCode,
						DutyInfoEnum.接警情况.getKey() + "-"));
		Map<String, Template> templateMap = templateList.stream().collect(Collectors.toMap(Template::getTypeCode,
				Function.identity()));
		List<String> contentList = Lists.newArrayList();
		list.forEach(i -> {
			String tempContent =
					templateMap.get(DutyInfoEnum.接警情况.getKey() + "-" + i.get("alertTypeCode")).getContent();
			contentList.add(replaceTemplate(tempContent, i));
		});
		Map<String, Integer> statusCountMap = alertCalledMapper.queryAlertStatusCount(beginDate, endDate);
		Integer unFinishedCount =
				this.count(new LambdaQueryWrapper<AlertCalled>().eq(AlertCalled::getAlertStatus, "0"));

		result.put("alertInfoList", contentList);
		result.putAll(statusCountMap);
		result.put("unFinishedCount", unFinishedCount);
		return result;
	}

	/**
	 * 替换模板
	 *
	 * @param tempContent 模板
	 * @param objMap      对象map
	 * @return
	 */
	private String replaceTemplate(String tempContent, Map<String, Object> objMap) {
		int size = objMap.size();
		String[] keys = objMap.keySet().toArray(new String[size]);
		Object[] values = objMap.values().toArray(new Object[size]);
		List<String> strList = Lists.newArrayList();
		for (Object obj : values) {
			if (!ValidationUtil.isEmpty(obj)) {
				if (obj instanceof Date) {
					obj = DateUtils.date2LongStr((Date) obj);
				}
				strList.add(obj.toString());
			} else {
				strList.add("");
			}
		}
		return StringUtils.replaceEach(tempContent, keys, strList.toArray(new String[strList.size()]));
	}
	@Override
	public    Map<String,Object>   selectAlertCalledKeyValueLabelById(Long id) {
		
			// 警情基本信息
			AlertCalled alertCalled = this.getById(id);			
			QueryWrapper<AlertFormValue> queryWrapper = new QueryWrapper<>();
			Map<String,Object> map=new HashMap();
		    map.put("title","【"+alertCalled.getAlertType()+"】"+alertCalled.getAddress());
			queryWrapper.eq("alert_called_id", id);
			// 警情动态表单数据
		    List<KeyValueLabel> listdate =new ArrayList<>();
			List<AlertFormValue> list = iAlertFormValueService.list(queryWrapper);			
			listdate.add(new KeyValueLabel("接警时间","callTime",alertCalled.getCallTime()));
			listdate.add(new KeyValueLabel("警情地点","address",alertCalled.getAddress()));
			listdate.add(new KeyValueLabel("警情类型","alertType",alertCalled.getAlertType()));
			listdate.add(new KeyValueLabel("警情阶段","alertStage",alertCalled.getAlertStage()));
			listdate.add(new KeyValueLabel("警情等级","responseLevel","无"));
			listdate.add(new KeyValueLabel("被困人数","trappedNum",alertCalled.getTrappedNum()));
			listdate.add(new KeyValueLabel("伤亡人数","casualtiesNum",alertCalled.getCasualtiesNum()));
			listdate.add(new KeyValueLabel("联系人","contactUser",alertCalled.getContactUser()));
			listdate.add(new KeyValueLabel("联系电话","contactPhone",alertCalled.getContactPhone()));
			listdate.add(new KeyValueLabel("联系人电话","contactPhone",alertCalled.getContactPhone()));
		     list.stream().forEach(AlertFormValue->{
              listdate.add(new KeyValueLabel(AlertFormValue.getFieldName(),AlertFormValue.getFieldCode(), AlertFormValue.getFieldValue()));
			 });
		    map.put("data",listdate);
			return map;
		
	}
	@Override
	public List<KeyValueLabel> selectAlertCalledcount(Long id) {
		// 警情基本信息
		AlertCalled alertCalled = this.getById(id);		
		
		List<KeyValueLabel> listdate =new ArrayList<>();
		listdate.add(new KeyValueLabel("被困人数","trappedNum",alertCalled.getTrappedNum()));
		listdate.add(new KeyValueLabel("伤亡人数","casualtiesNum",alertCalled.getCasualtiesNum()));
		return listdate;
	}

	@Override
	public List<KeyValueLabel> powercount(Long id) {
		Map<String,Integer>  map=powerTransferMapper.getCarNum(id);
//		Map<String,Integer>  mapc=powerTransferMapper.getCompanyNum(id);
//		Map<String,Integer>  mapu= alertSubmittedMapper.getUseNum(id);
		//统计参与人员
		List<KeyValueLabel> listdate =new ArrayList<>();
		listdate.add(new KeyValueLabel("调动人力","useNum","0","人"));
		//统计参与车辆
		listdate.add(new KeyValueLabel("调动人力","carNum",map.get("carNum"),"辆"));
		//统计参与队伍
		listdate.add(new KeyValueLabel("调动单位","companyNum",map.get("companyNum"),"个"));
        return listdate;

	}

	@Override
	public List<PowerData> getPowerDataList(Long id) {
		List<PowerData> list=powerTransferMapper.getPowerDataList(id);
		return list;
	}

	@Override
	public AlertCalled getAlertCalledById(Long id) {
		return this.getById(id);
	}
}
