package com.tuoheng.admin.service.third.airport;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tuoheng.admin.constant.SystemConstant;
import com.tuoheng.admin.dto.ReversalFlightDto;
import com.tuoheng.admin.entity.Accident;
import com.tuoheng.admin.entity.AccidentInspection;
import com.tuoheng.admin.entity.Inspection;
import com.tuoheng.admin.entity.User;
import com.tuoheng.admin.enums.AccidentStatusEnum;
import com.tuoheng.admin.enums.EmergencyInspectionEnum;
import com.tuoheng.admin.enums.InspectionStatusEnum;
import com.tuoheng.admin.enums.MarkEnum;
import com.tuoheng.admin.mapper.AccidentInspectionMapper;
import com.tuoheng.admin.mapper.AccidentMapper;
import com.tuoheng.admin.mapper.InspectionMapper;
import com.tuoheng.admin.service.menu.AccidentEnum;
import com.tuoheng.admin.utils.CurrentUserUtil;
import com.tuoheng.admin.websocket.WebSocketService;
import com.tuoheng.common.core.config.common.CommonConfig;
import com.tuoheng.common.core.enums.ServiceExceptionEnum;
import com.tuoheng.common.core.exception.ServiceException;
import com.tuoheng.common.core.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @Author ChengWang
 * @Date 2023/3/14
 */
@Slf4j
@Service
public class ReversalFlightService {

    @Autowired
    private InspectionMapper inspectionMapper;

    @Autowired
    private AccidentMapper accidentMapper;

    @Autowired
    private AccidentInspectionMapper accidentInspectionMapper;

    @Autowired
    private WebSocketService webSocketService;

    /**
     * 无人机返仓
     * @param dto
     * @return
     */
    public JsonResult reversalFlight(ReversalFlightDto dto) {
        //获取当前登录用户
        User userInfo = CurrentUserUtil.getUserInfo();
        if(ObjectUtil.isEmpty(userInfo)){
            throw new ServiceException("登录用户为空");
        }
        dto.setZhilin("03");
        log.info("进入调用机场平台，执行巡检任务返航飞行,accidentId={}",dto.getAccidentId());
        log.info("进入调用机场平台，执行应急任务返航飞行,zhilin={}",dto.getZhilin());
        //校验传参
        if(StringUtils.isEmpty(dto.getAccidentId())){
            return JsonResult.error(AccidentEnum.ACCIDENT_ID_IS_NULL.getCode(),AccidentEnum.ACCIDENT_ID_IS_NULL.getMsg());
        }
        //巡检任务关联应急任务指点飞行返航
        Accident accident = accidentMapper.selectById(dto.getAccidentId());
        if(ObjectUtil.isNull(accident)){
            return JsonResult.error(AccidentEnum.DATA_IS_NULL.getCode(),AccidentEnum.DATA_IS_NULL.getMsg());
        }
        //此时判断任务id是否为空，若不为空这是dsp识别的应急事故，若为空则是手动创建的应急事故
        if(StringUtils.isNotEmpty(accident.getInspectionId())){
            //获取对应的任务
            Inspection inspection = inspectionMapper.selectOne(Wrappers.<Inspection>lambdaQuery()
                    .eq(Inspection::getId, accident.getInspectionId())
                    .eq(Inspection::getMark, MarkEnum.VALID.getCode()));
            //此时会手动创建一个应急任务与事故进行关联,判断应急任务是否关联巡检任务(目前是一对一)
            //校验
            Integer count = accidentInspectionMapper.selectCount(Wrappers.<AccidentInspection>lambdaQuery()
                    .eq(AccidentInspection::getAccidentId, dto.getAccidentId()));
            if(count >1){
                return JsonResult.error("当前事故关联的任务不唯一");
            }
            AccidentInspection accidentInspection = accidentInspectionMapper.selectOne(Wrappers.<AccidentInspection>lambdaQuery()
                    .eq(AccidentInspection::getAccidentId, dto.getAccidentId())
                    .eq(AccidentInspection::getMark, MarkEnum.VALID.getCode()));
            if(StringUtils.isEmpty(accidentInspection.getInspectionId())){
                throw new ServiceException(ServiceExceptionEnum.PARAMETER_IS_NULL.getCode(),ServiceExceptionEnum.PARAMETER_IS_NULL.getMsg());
            }
            Inspection emergencyInspection = inspectionMapper.selectOne(Wrappers.<Inspection>lambdaQuery()
                    .eq(Inspection::getId, accidentInspection.getInspectionId())
                    .eq(Inspection::getMark, MarkEnum.VALID.getCode()));
            if(ObjectUtil.isNull(emergencyInspection)){
                return JsonResult.error(AccidentEnum.EMERGENCY_INSPECTION_IS_NULL.getCode(),AccidentEnum.EMERGENCY_INSPECTION_IS_NULL.getMsg());
            }
            //根据关联id是否存在判断应急任务是否和巡检任务关联
            if(StringUtils.isNotEmpty(emergencyInspection.getEmergencyDataInspectionId())){
                //此时原巡检任务无人机返航即可
                log.info("执行原巡检任务无人机返航,inspection={}",inspection);
                JsonResult jsonResult = this.getRevFlight(inspection);
                if (0 != jsonResult.getCode()){
                    return JsonResult.error(jsonResult.getCode(),jsonResult.getMsg());
                }
            }else {
                //此时原巡检任务和应急任务的无人机返航
                //log.info("执行原巡检任务无人机返航,inspection={}",inspection);
                //JsonResult jsonResult = this.getRevFlight(inspection);
                log.info("执行新应急任务无人机返航,emergencyInspection={}",emergencyInspection);
                JsonResult jsonResult1 = this.getRevFlight(emergencyInspection);
                if(0 != jsonResult1.getCode()){
                    return JsonResult.error(jsonResult1.getCode(),jsonResult1.getMsg());
                }
            }
        }
        //手动添加的应急任务返航
        if(StringUtils.isEmpty(accident.getInspectionId())){
            Integer count = accidentInspectionMapper.selectCount(Wrappers.<AccidentInspection>lambdaQuery()
                    .eq(AccidentInspection::getAccidentId, dto.getAccidentId()));
            if(count >1){
                return JsonResult.error("当前事故关联的任务不唯一");
            }
            AccidentInspection accidentInspection = accidentInspectionMapper.selectOne(Wrappers.<AccidentInspection>lambdaQuery()
                    .eq(AccidentInspection::getAccidentId, accident.getId())
                    .eq(AccidentInspection::getMark, MarkEnum.VALID.getCode()));
            if(StringUtils.isEmpty(accidentInspection.getInspectionId())){
                throw new ServiceException(ServiceExceptionEnum.PARAMETER_IS_NULL);
            }
            Inspection emergencyInspection = inspectionMapper.selectOne(Wrappers.<Inspection>lambdaQuery()
                    .eq(Inspection::getId, accidentInspection.getInspectionId())
                    .eq(Inspection::getMark, MarkEnum.VALID.getCode()));
            if(ObjectUtil.isEmpty(emergencyInspection)){
                return JsonResult.error(EmergencyInspectionEnum.INSPECTION_IS_NULL.getCode(),EmergencyInspectionEnum.INSPECTION_IS_NULL.getDescription());
            }
            log.info("手动创建的应急任务无人机返航,emergencyInspection={}",emergencyInspection);
            JsonResult jsonResult = this.getRevFlight(emergencyInspection);
            if(0 != jsonResult.getCode()){
                return JsonResult.error(jsonResult.getCode(),jsonResult.getMsg());
            }
        }
        log.info("修改应急事故的状态,accident={}",accident);
        this.updateAccident(userInfo,accident);
        return JsonResult.success("无人机返航成功");
    }

    private JsonResult getRevFlight(Inspection inspection) {
        log.info("无人机回仓");
//        Inspection inspection = inspectionMapper.selectOne(Wrappers.<Inspection>lambdaQuery()
//                .eq(Inspection::getAirportId, airportId)
//                .eq(Inspection::getMark, MarkEnum.VALID.getCode())
//                .eq(Inspection::getStatus, InspectionStatusEnum.IN_FLIGHT.getCode())
//                .eq(Inspection::getType, 1));
        if(ObjectUtil.isNotNull(inspection)){
            //修改任务的状态为已完成
            inspection.setStatus(InspectionStatusEnum.FLIGHT_COMPLETED.getCode());
            inspection.setUpdateTime(DateUtils.now());
            inspection.setUpdateUser(CurrentUserUtil.getUserId());
            int count = inspectionMapper.updateById(inspection);
            if(count == 0){
                return JsonResult.error("修改任务状态失败");
            }
        }
        //设置返航状态码
        //调用机场平台无人机返航
        String url = CommonConfig.airportURL + SystemConstant.API_AIRPORT_DRONE_CONTROL;
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("airportId", inspection.getAirportId());
        jsonObject.put("taskId", inspection.getId());
        jsonObject.put("zhilin", "03");
        jsonObject.put("msg", "回仓");
        log.info("调用机场平台，无人机执行定点飞行返航：url:{}", url);
        log.info("调用机场平台，原无人机执行定点飞行返航，jsonObject:{}", jsonObject);

        String airPortStr = HttpUtils.doSend(url, jsonObject, null, "POST");
        log.info("调用无人机平台，操作无人机：airPortStr:{}", airPortStr);
        if (StringUtils.isEmpty(airPortStr)) {
            log.info("原无人机执行定点飞行返航：机场接口返回数据为空，返航失败，jsonObject：{}", jsonObject);
            throw new ServiceException("机场接口返回数据为空，返航失败");
        }
        JsonResult jsonResult = JacksonUtil.json2pojo(airPortStr, JsonResult.class);
        if(0 != jsonResult.getCode()){
            log.info("调用机场平台，无人机执行定点飞行：返航失败，jsonResult：{}", jsonResult.getMsg());
            return JsonResult.error(-1, "机场平台返回失败");
        }
        log.info("调用无人机平台返航结束");
        return JsonResult.success();
    }

    /**
     * 修改应急事故状态
     *
     * @param user
     * @param accident
     */
    private void updateAccident(User user,Accident accident) {
        accident.setStatus(AccidentStatusEnum.COMPLETED.getCode());
        accident.setUpdateUser(user.getId());
        accident.setUpdateTime(DateUtils.now());
        accident.setEndTime(DateUtils.now());
        int count = accidentMapper.updateById(accident);
        if (count <= 0) {
            log.info("应急事故处理完成修改状态失败, accidentId={}", accident.getId());
            throw new ServiceException("应急事故处理完成修改状态失败");
        }
        //事故状态发生变化推送通知
        log.info("执行消息推送方法");
        webSocketService.accidentNotice(accident.getTenantId());
        log.info("消息推送完成");
    }


}
