package com.yeejoin.equipmanage.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yeejoin.amos.boot.module.jcs.api.dto.IotSystemAlarmRo;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.systemctl.model.DictionarieValueModel;
import com.yeejoin.equipmanage.common.dto.UserDto;
import com.yeejoin.equipmanage.common.entity.EquipmentSpecific;
import com.yeejoin.equipmanage.common.entity.EquipmentSpecificAlarm;
import com.yeejoin.equipmanage.common.entity.EquipmentSpecificAlarmLog;
import com.yeejoin.equipmanage.common.entity.vo.AlamVideoVO;
import com.yeejoin.equipmanage.common.enums.AlarmCleanTypeEnum;
import com.yeejoin.equipmanage.common.enums.AlarmStatusEnum;
import com.yeejoin.equipmanage.common.enums.AlarmTypeEnum;
import com.yeejoin.equipmanage.common.enums.TopicEnum;
import com.yeejoin.equipmanage.common.utils.StringUtil;
import com.yeejoin.equipmanage.fegin.JcsFeign;
import com.yeejoin.equipmanage.mapper.ConfirmAlarmMapper;
import com.yeejoin.equipmanage.mapper.EquipmentSpecificAlarmMapper;
import com.yeejoin.equipmanage.mapper.EquipmentSpecificMapper;
import com.yeejoin.equipmanage.mapper.VideoMapper;
import com.yeejoin.equipmanage.remote.RemoteSecurityService;
import com.yeejoin.equipmanage.remote.WebMqttHandler;
import com.yeejoin.equipmanage.service.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ConfirmAlarmServiceImpl extends ServiceImpl<ConfirmAlarmMapper, EquipmentSpecificAlarm> implements IConfirmAlarmService {

    private final static String FIELD_NAME = "longitude,latitude";

    @Autowired
    private RemoteSecurityService remoteSecurityService;

    @Autowired
    ConfirmAlarmMapper confirmAlarmMapper;

    @Autowired
    private JcsFeign jcsFeign;

    @Autowired
    VideoMapper videoMapper;

    @Autowired
    IEquipmentSpecificIndexService equipmentSpecificIndexService;

    @Autowired
    private ISyncDataService syncDataService;

    @Autowired
    MqttSendGateway mqttSendGateway;

    @Autowired
    private WebMqttHandler webMqttHandler;

    @Autowired
    private IEquipmentSpecificAlarmLogService equipmentSpecificAlarmLogService;

    @Autowired
    private IEquipmentSpecificSerivce equipmentSpecificSerivce;

    @Autowired
    private IVideoService videoService;

    @Value("${systemctl.jcs.switch}")
    private Boolean jcsSwitch;

    @Value("${window.vedioFormat}")
    String vedioFormat;

    @Autowired
    private RuleConfirmAlarmService ruleConfirmAlamService;

    @Autowired
    private EquipmentSpecificMapper equipmentSpecificMapper;

    @Autowired
    private EquipmentSpecificAlarmMapper equipmentSpecificAlarmMapper;



    @Override
    public Map<String, Object> getDetailsById(Long alarmId, Long equipId, String type, String area) {
        final String videoType = "video";
        final String alarmType = "IOT_CORE_PARAM";
        Map<String, Object> res = new HashMap<>();
        if (videoType.equals(type)) {
            List<AlamVideoVO> video = videoMapper.getVideoBySpeId(equipId);
            video.forEach(action -> {
                action.setVedioFormat(vedioFormat);
                action.setUrl(videoService.getVideoUrl(action.getName(), action.getPresetPosition(), action.getUrl(), action.getCode()));
            });
            res.put("video", video);
            return res;
        }
        EquipmentSpecificAlarmLog specificAlarm = confirmAlarmMapper.getDetailsById(alarmId, equipId);
        List<AlamVideoVO> videoBySpeId;
        if (specificAlarm == null) {
            videoBySpeId = videoMapper.getVideoBySpeId(equipId);
        } else {
            videoBySpeId = videoMapper.getVideoBySpeId(specificAlarm.getEquipmentSpecificId());
            List<DictionarieValueModel> dict = remoteSecurityService.listDictionaryByDictCode(alarmType);
            Map<String, String> dictMap = dict.stream().collect(Collectors.toMap(DictionarieValueModel::getDictDataKey, DictionarieValueModel::getDictDataValue));
            //specificAlarm.getEquipmentSpecificIndexKey() 取值为告警类型type，兼容之前的页面取值
            specificAlarm.setEquipmentSpecificIndexName(dictMap.get(specificAlarm.getEquipmentSpecificIndexKey()));
        }

        videoBySpeId.forEach(action -> {
            action.setVedioFormat(vedioFormat);
            action.setUrl(videoService.getVideoUrl(action.getName(), action.getPresetPosition(), action.getUrl(), action.getCode()));
        });
        res.put("data", specificAlarm);
        res.put("video", videoBySpeId);
        return res;
    }

    @Override
    public void confirmAlam(EquipmentSpecificAlarmLog ent, String appKey, String product, String token, String userId) {
        try {
            AgencyUserModel userModel = remoteSecurityService.getAgencyUser();
            ent.setConfirmUser(userModel.getUserId());
            ent.setConfirmUserName(userModel.getRealName());
            EquipmentSpecificAlarmLog alarmLog = equipmentSpecificAlarmLogService.getById(ent.getId());
            List<EquipmentSpecificAlarmLog> list = null;
            int isBatch = 0;
            if (!ObjectUtils.isEmpty(alarmLog)) {
                Long equipmentSpecificAlarmId = alarmLog.getEquipmentSpecificAlarmId();
                ent.setEquipmentSpecificAlarmId(equipmentSpecificAlarmId);
                String cleanType = equipmentSpecificMapper.getEquipmentBySpecificId(alarmLog.getEquipmentSpecificId());
                if (StringUtil.isNotEmpty(cleanType) && AlarmCleanTypeEnum.QRXC.getCode().equals(cleanType)) {
                    EquipmentSpecificAlarm alarm = equipmentSpecificAlarmMapper.selectById(alarmLog.getEquipmentSpecificAlarmId());
                    alarm.setStatus(AlarmStatusEnum.HF.getCode());
                    equipmentSpecificAlarmMapper.updateById(alarm);
                    if (isBatch == 1) {
                        List<EquipmentSpecificAlarmLog> logs = equipmentSpecificAlarmLogService.getIsConfirmByAlarmId(equipmentSpecificAlarmId, "0");
                        logs = logs.stream().map(x -> {
                            BeanUtils.copyProperties(ent, x);
                            x.setCleanTime(new Date());
                            x.setStatus(AlarmStatusEnum.HF.getCode());
                            return x;
                        }).collect(Collectors.toList());
                        equipmentSpecificAlarmLogService.updateBatchById(logs);
                    } else {
                        ent.setCleanTime(new Date());
                        ent.setStatus(AlarmStatusEnum.HF.getCode());
                        equipmentSpecificAlarmLogService.updateById(ent);
                    }
                    return;
                }
                //  如果是批量确警，先查询，再确警，用于批量消息推送
                isBatch = ent.getIsBatch();
                if (isBatch == 1) {
                    list = equipmentSpecificAlarmLogService.getIsConfirmByAlarmId(equipmentSpecificAlarmId, "0");
                }
            }

            int i = confirmAlarmMapper.confirmAlam(ent);
            if (i > 0) {
                if (jcsSwitch && AlarmTypeEnum.HZGJ.getCode().equals(ent.getConfirmType())) {
                    // 确警消息发送
                    if (StringUtils.isNotBlank(userId)) {
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    sendIotSystemAlarm(ent, userId, appKey, product, token);
                                } catch (Exception e) {
                                    log.error("sendIotSystemAlarm消息发送失败！");
                                    e.printStackTrace();
                                }
                            }
                        }).start();
                    }
                }
                if (isBatch == 1 && CollectionUtils.isNotEmpty(list)) {
                    list.stream().forEach(x -> webMqttHandler.publish(TopicEnum.EQYQR.getTopic(), JSON.parseObject(JSON.toJSONString(x), HashMap.class)));
                } else {
//                    mqttSendGateway.sendToMqtt(TopicEnum.EQYQR.getTopic(), JSON.toJSONString(ent));
                    webMqttHandler.publish(TopicEnum.EQYQR.getTopic(), JSON.parseObject(JSON.toJSONString(ent), HashMap.class));
                }
//                syncDataService.syncCreatedSendAlarmReport(ent);
            }
            //数字换流站使用
            mqttSendGateway.sendToMqtt(TopicEnum.EQZXDT.getTopic(), "");
        } catch (Exception e) {
            e.printStackTrace();
            throw new BadRequest("确认失败");
        }
    }

    @Override
    public Integer getFireAlarm() {
        return confirmAlarmMapper.getFireAlarm();
    }

    @Override
    public Integer getFaultAlarm() {
        return confirmAlarmMapper.getFaultAlarm();
    }

//    public void sendIotSystemAlarm(EquipmentSpecificAlarmLog ent, String userId, String appKey, String product, String token){
////        Token serverToken = remoteSecurityService.getServerToken();
//        ResponseModel<List<UserDto>> responseModel = null;
//        try {
//            responseModel = jcsFeign.getUserInfo(appKey, product, token, userId);
//        } catch (Exception e) {
//            log.error("查询机场人员为空，检查机场人员是否绑定单位！");
//        }
//        List<UserDto> result = responseModel.getResult();
//        IotSystemAlarmRo confirmAlamVo = new IotSystemAlarmRo();
//        confirmAlamVo.setId(ent.getId());
//        if (CollectionUtils.isNotEmpty(result)) {
//            result.stream().forEach(x -> {
//                confirmAlamVo.setUnitInvolvedId(x.getCompanyId());
//                confirmAlamVo.setUnitInvolvedName(x.getCompanyName());
//                String bizOrgType = x.getBizOrgType();
//                String fieldCode = x.getFieldCode();
//                String fieldValue = x.getFieldValue();
//                String personName = x.getPersonName();
//                if ("PERSON".equalsIgnoreCase(bizOrgType)) {
//                    confirmAlamVo.setContactUser(personName);
//                    confirmAlamVo.setContactPhone(fieldValue);
//                } else if ("COMPANY".equalsIgnoreCase(bizOrgType)) {
//                    switch (fieldCode) {
//                        case "companyLocation":
//                            confirmAlamVo.setAddress(fieldValue);
//                            break;
//                        case "longitude":
//                            confirmAlamVo.setLongitude(getVal(fieldValue));
//                            break;
//                        case "latitude":
//                            confirmAlamVo.setLatitude(getVal(fieldValue));
//                            break;
//                        default:
//                    }
//                }
//                List<UserDto> infoList = equipmentSpecificSerivce.getEquipSpecificLocationInfo(ent.getEquipmentSpecificId(), FIELD_NAME.split(","));
//                if (CollectionUtils.isNotEmpty(infoList)) {
//                    infoList.stream().forEach(dto -> {
//                        String name = dto.getPersonName();
//                        String code = dto.getFieldCode();
//                        String value = dto.getFieldValue();
//                        confirmAlamVo.setFireLocation(name);
//                        switch (code) {
//                            case "longitude":
//                                confirmAlamVo.setFloorLongitude(getVal(value));
//                                break;
//                            case "latitude":
//                                confirmAlamVo.setFloorLatitude(getVal(value));
//                                break;
//                            default:
//                        }
//                    });
//                }
//            });
//        }
//        try {
//            ruleConfirmAlamService.confirmAlam(confirmAlamVo, appKey, product, token);
//        } catch (Exception e) {
//            log.error("发送接处警消息失败！");
//        }
//    }

    public void sendIotSystemAlarm(EquipmentSpecificAlarmLog ent, String userId, String appKey, String product, String token){
//        Token serverToken = remoteSecurityService.getServerToken();
        IotSystemAlarmRo confirmAlamVo = new IotSystemAlarmRo();
        confirmAlamVo.setId(ent.getId());
        ent = confirmAlarmMapper.getDetailsById(ent.getId(), null);
        EquipmentSpecific equipmentSpecific = equipmentSpecificSerivce.getById(ent.getEquipmentSpecificId());

        if (!ValidationUtil.isEmpty(equipmentSpecific.getAgencyId())){
            // 机场单位
            JSONObject unitMap = jcsFeign.getUnitById(appKey, product, token, equipmentSpecific.getAgencyId()).getResult();
            JSONObject jsonObject = unitMap.getJSONObject("map");
            confirmAlamVo.setUnitInvolvedId(equipmentSpecific.getAgencyId());
            confirmAlamVo.setUnitInvolvedName(unitMap.getString("bizOrgName"));
            confirmAlamVo.setAddress(jsonObject.getString("companyLocation"));
            confirmAlamVo.setLongitude(jsonObject.getDouble("longitude"));
            confirmAlamVo.setLatitude(jsonObject.getDouble("latitude"));
        }
        try {
            // 机场人员
            JSONObject personMap = jcsFeign.getPersonByUserId(appKey, product, token, userId).getResult();
            confirmAlamVo.setContactUser(personMap.getString("bizOrgName"));
            confirmAlamVo.setContactPhone(personMap.getJSONObject("map").getString("telephone"));
        } catch (Exception e) {
            log.error("查询机场人员为空，检查机场人员是否绑定单位！");
        }
        confirmAlamVo.setFireLocation(ent.getLocation());
        List<UserDto> infoList = equipmentSpecificSerivce.getEquipSpecificLocationInfo(ent.getEquipmentSpecificId(), FIELD_NAME.split(","));
        if (CollectionUtils.isNotEmpty(infoList)) {
            infoList.stream().forEach(dto -> {
//                String name = dto.getPersonName();
//                confirmAlamVo.setFireLocation(name);
                String code = dto.getFieldCode();
                String value = dto.getFieldValue();
                switch (code) {
                    case "longitude":
                        confirmAlamVo.setFloorLongitude(getVal(value));
                        break;
                    case "latitude":
                        confirmAlamVo.setFloorLatitude(getVal(value));
                        break;
                    default:
                }
            });
        }
        try {
            ruleConfirmAlamService.confirmAlam(confirmAlamVo, appKey, product, token);
        } catch (Exception e) {
            log.error("发送接处警消息失败！");
        }
    }

    private Double getVal(String value){
        return ValidationUtil.isEmpty(value) ? null : Double.parseDouble(value);
    }
}
