package org.springblade.third.iotdevice.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.AllArgsConstructor;

import org.springblade.common.beans.ApiResultBean;
import org.springblade.common.constant.CommonConstant;
import org.springblade.common.constant.OperationConstant;
import org.springblade.common.utils.JsonUtils;
import org.springblade.community.feign.IResidentialClient;
import org.springblade.device.entity.*;
import org.springblade.device.feign.*;
import org.springblade.device.vo.IotAlarmVO;
import org.springblade.device.vo.IotDeviceVO;
import org.springblade.sms.service.IPepNoticeService;
import org.springblade.system.expand.feign.IOrgPositionClient;
import org.springblade.system.user.feign.IUserClient;
import org.springblade.third.iotdevice.constant.PepComponentMetric;
import org.springblade.third.iotdevice.dto.AepSubscribeSettingDto;
import org.springblade.third.iotdevice.dto.PepAlarmNoticeDto;
import org.springblade.third.iotdevice.dto.PepHeartbeatNoticeDto;
import org.springblade.third.iotdevice.entity.IotSysConf;
import org.springblade.third.iotdevice.entity.SingleHeartBeat;
import org.springblade.third.iotdevice.service.*;
import org.springblade.third.iotdevice.util.PepComponentUtil;
import org.springblade.third.iotdevice.util.RedisUtil;
import org.springblade.third.iotdevice.util.SendMessageBuildUtil;
import org.springblade.third.iotdevice.vo.PepNoticeReturnVO;
import org.springblade.third.sms.dto.PepSmsSendDto;
import org.springblade.third.sms.dto.PepVoiceSendDto;
import org.springblade.workorder.deviceorder.entity.DeviceOrder;
import org.springblade.workorder.deviceorder.feign.IDeviceOrderClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;

import java.util.*;

/**
 * @author lidexi
 * @date 2021/5/21 9:48
 * 感知平台订阅接口实现
 */
@Service
@AllArgsConstructor
public class PerceptionSubscribeServiceImpl implements IPerceptionSubscribeService {

	private final IIotDeviceClient iotDeviceClient;
	private final IIotAlarmClient iotAlarmClient;
	private final IDeviceOrderClient deviceOrderClient;
	private final IPepNoticeService pepNoticeService;
	private final IResidentialClient residentialClient;
	private final IIotAlarmGroupClient iotAlarmGroupClient;
	private final IIotAlarmGroupUserClient iotAlarmGroupUserClient;
	private final OrderGenerateUtilService orderGenerateUtilService;
	private final IUserClient userClient;
	private final RedisTemplate<String,String> redisTemplate;
	private final IOrgPositionClient orgPositionClient;
	private final IIotDeviceHeartbeatClient iotDeviceHeartbeatClient;


	@Override
	public Object deviceStatusChange(Map<String,Object> pepDeviceStatusNoticeDto) {
		PepNoticeReturnVO returnVO = new PepNoticeReturnVO(0, "成功");

		String deviceId = pepDeviceStatusNoticeDto.get("device_id").toString();
		String status = pepDeviceStatusNoticeDto.get("device_status").toString();

		IotDevice searchEntity = new IotDevice();
		searchEntity.setDeviceId(deviceId);
		IotDeviceVO target = iotDeviceClient.detail(searchEntity);
		if(target == null){
			returnVO.setCode(-1);
			returnVO.setMsg("未找到设备记录");
			return returnVO;
		}else{
			target.setDeviceStatus(Integer.valueOf(status));
//			target.setLastUpdateTime(LocalDateTime.now());
			this.iotDeviceClient.update(target);
		}
		return returnVO;
	}

	@Override
	public PepNoticeReturnVO heartBeatReport(List<PepHeartbeatNoticeDto> pepHeartbeatNoticeDtos) {
		PepNoticeReturnVO returnVO = new PepNoticeReturnVO(0, "成功");

		PepHeartbeatNoticeDto heartbeatNoticeDto = pepHeartbeatNoticeDtos.get(0);
		String device_id = heartbeatNoticeDto.getDevice_id();
		IotDevice searchEntity = new IotDevice();
		searchEntity.setDeviceId(device_id);
		IotDeviceVO target = iotDeviceClient.detail(searchEntity);
		if(target == null){
			returnVO.setCode(-1);
			returnVO.setMsg("未找到设备记录");
			return returnVO;
		}else{
			Map<String,String> metricMap = PepComponentUtil.getPepMetricByDeviceType(target.getDeviceType());
			List<SingleHeartBeat> singleHeartBeats = new ArrayList<>();
			for(int i = 0; i < pepHeartbeatNoticeDtos.size(); i++){
				PepHeartbeatNoticeDto source = pepHeartbeatNoticeDtos.get(i);
				SingleHeartBeat singleHeartBeat = new SingleHeartBeat();
				singleHeartBeat.setName(source.getMetric());
				singleHeartBeat.setValue(source.getDevice_data());
				singleHeartBeat.setLabel(metricMap.get(source.getMetric()));
				singleHeartBeats.add(singleHeartBeat);
			}
			String specialData = JSONUtil.toJsonStr(singleHeartBeats);
			IotDeviceHeartbeat iotDeviceHeartbeat = new IotDeviceHeartbeat();
			iotDeviceHeartbeat.setDeviceId(target.getId());
			iotDeviceHeartbeat.setDeviceName(target.getDeviceName());
			iotDeviceHeartbeat.setData(specialData);
			iotDeviceHeartbeat.setPlatform("scepctwing");
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

			try {
				iotDeviceHeartbeat.setCreateTime(sdf.parse(heartbeatNoticeDto.getReceive_time()));
			} catch (ParseException e) {
				e.printStackTrace();
			}
			this.iotDeviceHeartbeatClient.save(iotDeviceHeartbeat);

//			target.setLastUpdateTime(LocalDateTime.now());
			this.iotDeviceClient.update(target);
		}

		return returnVO;
	}

	@Override
	public boolean setSubscribe(AepSubscribeSettingDto aepSubscribeSettingDto) {

//		List<IotSysConf> iotSysConfList = iotSysConfService.getBaseMapper().selectList(
//			new QueryWrapper<>(new IotSysConf()).lambda().eq(IotSysConf::getPaltform,CommonConstant.THIRDPLATFORM.PERCEPTION.getValue());
//		int flag = 0;
//		for(int i = 0; i < iotSysConfList.size(); i++){
//			IotSysConf iotSysConf = iotSysConfList.get(i);
//			IotHttpUtil httpUtil = new IotHttpUtil(iotSysConf);
//			String heartbeat_url = aepSubscribeSettingDto.getHeartbeat_url();
//			String alarm_url = aepSubscribeSettingDto.getAlarm_url();
//			String device_status_url = aepSubscribeSettingDto.getDevice_status_url();
//			Map<String, Object> bizParamsMap = new HashMap<>();
//			bizParamsMap.put("heartbeat_url", heartbeat_url);
//			bizParamsMap.put("alarm_url", alarm_url);
//			bizParamsMap.put("device_status_url", device_status_url);
//			String[] prefixList = iotSysConf.getPrefix().split(",");
//			String appId = iotSysConf.getAppId();
//			IotAuthentication iotAuthentication = this.iotAuthServiceInterface.findByAppId(appId);
//			for(int j = 0; j < prefixList.length; j++){
//				String prefix = prefixList[j];
//				ApiResultBean<Object> apiResultBean = httpUtil.subscribe(bizParamsMap, prefix, iotAuthentication.getAccessToken());
//				if(apiResultBean.getCode().equals(IotReturnCode.UNAUTHORIZED.getCode())){ //未认证，提示先去认证
//					return new ResultBean<>(ResultEnum.FAILURE, IotReturnCode.UNAUTHORIZED.toString());
//				}
//				String reqData = JsonUtils.objectToJson(bizParamsMap);
//				this.iotApiLogServiceInterface.recordIotApiLog("/setting/subscribe", prefix, appId, reqData, apiResultBean);
//				if(apiResultBean.getCode().equals(OperationConstant.ZERO)){
//					flag++;
//				}
//			}
//		}
//		if(flag == iotSysConfList.size()){
//			return new ResultBean<>(ResultEnum.SUCCESS, "订阅成功");
//		}else{
//			return new ResultBean<>(ResultEnum.SUCCESS, "部分订阅成功，请查看日志");
//		}
		return false;
	}

	/**
	 * 告警上报订阅接口
	 */
	@Override
	public PepNoticeReturnVO alarmReport(List<PepAlarmNoticeDto> alarmNoticeDtoList) {
		PepNoticeReturnVO returnVO = new PepNoticeReturnVO(0, "成功");

		int flag = 0;// 0-新增 1-更新

		for (int i = 0; i < alarmNoticeDtoList.size(); i++) {
			PepAlarmNoticeDto source = alarmNoticeDtoList.get(i);

			IotDevice searchDevice = new IotDevice();
			searchDevice.setDeviceId(source.getDevice_id());
			IotDevice smartDevice = iotDeviceClient.detail(searchDevice);
			if (smartDevice == null) {
				return returnVO;
			}

			IotAlarm target = null;
			/**
 				* 判断是否存在同种设设备同一告警
 				* 	  1 存在
 				*			更新该存在的告警的告警次数和最新告警时间并短信通知
 				* 	  2 不存在
 				* 	  		直接新增并自动生成工单和短信通知
 				*/
			if (source.getAlarm_id() != null) {
				IotAlarm searchIotAlarm = new IotAlarm();
				searchIotAlarm.setAlarmId(source.getAlarm_id());
				target = this.iotAlarmClient.detail(searchIotAlarm);
				if (target == null) {
					target = this.isExistSameAlarm(source);
				}

			} else {//没有alarmId  --  理论上不存在这种情况，感知平台alarmId必填
				target = this.isExistSameAlarm(source);
			}

			if(target == null){//不存在同种设备的同一警告，新增告警记录,并自动生成工单
				IotAlarm newObject = this.createNewIotAlarm(source,smartDevice);
				iotAlarmClient.save(newObject);
				//自动生成工单
				orderGenerateUtilService.deviceAlarmOrderGenerate(target,smartDevice);
//				//保存告警到redis
				try {
					RedisUtil.saveAlarmToRedis(target, target.getOrgPosition(), smartDevice.getTenantId(),userClient,redisTemplate
					,orgPositionClient);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}else{//存在同种设备的同一告警，更新告警次数和告警时间
				target.setLastNoticeDate(new Date());
				target.setAlarmTimes(target.getAlarmTimes() + 1);
				iotAlarmClient.update(target);
			}

			//异步短信通知

			//构建短信发送对象
			List<PepSmsSendDto> pepSmsSendDtos = SendMessageBuildUtil.buildIotSmsSendDto(target,iotDeviceClient
			,residentialClient,iotAlarmGroupClient,iotAlarmGroupUserClient);
			pepSmsSendDtos.stream().forEach(pepSmsSendDto -> this.pepNoticeService.sendSms(pepSmsSendDto));

			//构建语音发送对象
			List<PepVoiceSendDto> pepVoiceSendDtos = SendMessageBuildUtil.buildIotVoiceSendDto(target,iotDeviceClient
				,residentialClient,iotAlarmGroupClient,iotAlarmGroupUserClient);
			pepVoiceSendDtos.stream().forEach(pepVoiceSendDto -> this.pepNoticeService.sendVoice(pepVoiceSendDto));

		}

		return returnVO;
	}



	/**
	 * 判断是否存在同种设设备同一告警
	 *
	 *  (
	 * 		 视为同一个告警记录的条件（满足一个即可 ）：
	 * 		 1: AlarmId一样
	 * 		 2: 告警设备,告警描述一致，且未生成工单或已经生成工单但是工单的状态未完成
	 * 		 )
	 *
	 * @param pepAlarmNoticeDto
	 * @return
	 *  */

	private IotAlarm isExistSameAlarm(PepAlarmNoticeDto pepAlarmNoticeDto) {

		IotAlarm selectAlarm = new IotAlarm();
		selectAlarm.setAlarmDesc(pepAlarmNoticeDto.getAlarm_desc());
		selectAlarm.setDeviceId(pepAlarmNoticeDto.getDevice_id());
		//查询出与该告警记录一样的告警记录
		List<IotAlarmVO> alarms = iotAlarmClient.list(selectAlarm);
		System.out.println(alarms);
		if (alarms.size() > 0) {
			IotAlarm alarm1 = alarms.get(0);//只比较最新的一条告警记录
			if (alarm1.getOrderId() == null || alarm1.getOrderId().equals("")) {//未生成工单
				return alarm1;
			} else if (alarm1.getOrderId() != null) {//已生成工单
				DeviceOrder searchOrder = new DeviceOrder();
				searchOrder.setId(Long.valueOf(alarm1.getOrderId()));
				DeviceOrder deviceJob = deviceOrderClient.detail(searchOrder);
				 if (deviceJob != null && deviceJob.getJobStatus() == 1) {//未完成
					return alarm1;
				}
			}
		}
		return null;
	}

	/**
	 * 根据感知平台传递的告警记录生成本平台的告警记录
	 * @param source
	 * @return
	 */
	private IotAlarm createNewIotAlarm(PepAlarmNoticeDto source,IotDevice iotDevice) {
		IotAlarm iotAlarm = new IotAlarm();

		iotAlarm.setAlarmId(source.getAlarm_id());
		iotAlarm.setAlarmTimes(1);
		iotAlarm.setLevel(source.getLevel());
		iotAlarm.setName(source.getAlarm_desc());
		iotAlarm.setDeviceId(iotDevice.getDeviceId());
		iotAlarm.setDeviceName(iotDevice.getDeviceName());
		iotAlarm.setRecordTime(source.getReceive_time());
		iotAlarm.setDeviceType(iotDevice.getDeviceType());
		iotAlarm.setAlarmType(Integer.valueOf(source.getType()));
		iotAlarm.setMetric(source.getMetric());
		iotAlarm.setAlarmDesc(source.getAlarm_desc());
		iotAlarm.setIsAlarm(source.getIs_alarm());
		iotAlarm.setAlarmMetric(source.getAlarmMetric());
		iotAlarm.setAlarmValue(source.getAlarm_value());
		iotAlarm.setLastNoticeDate(new Date());
		iotAlarm.setLastSyncDate(LocalDateTime.now());
		iotAlarm.setMonitorValue(source.getAlarm_value());
		iotAlarm.setOrgPosition(iotDevice.getOrgPosition());
		iotAlarm.setTenantId(iotDevice.getTenantId());

		return iotAlarm;
	}






}
