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

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tuoheng.admin.common.ServiceExceptionEnum;
import com.tuoheng.admin.entity.domain.ThMission;
import com.tuoheng.admin.entity.request.MissionStatusRequest;
import com.tuoheng.admin.entity.vo.AirWeatherVO;
import com.tuoheng.admin.enums.*;
import com.tuoheng.admin.mapper.ThMissionMapper;
import com.tuoheng.admin.service.IDspService;
import com.tuoheng.admin.service.IThInspectionService;
import com.tuoheng.admin.service.third.UpdateEmergencyMissionStatusService;
import com.tuoheng.admin.utils.WeatherUtil;
import com.tuoheng.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class AirportCallBackUpdateStatusService {

    @Autowired
    private ThMissionMapper thMissionMapper;

    @Resource
    @Lazy
    private IThInspectionService inspectionService;

    @Autowired
    private IDspService dspService;

    @Value("${tuoheng.dsp-callback-url:}")
    private String dspCallbackUrl;

    @Autowired
    private UpdateEmergencyMissionStatusService updateEmergencyMissionStatusService;

    /**
     * 机场平台回调，修改任务状态
     *
     * @param missionStatusRequest
     * @return
     * @throws ServiceException
     */
    public boolean updateStatus(MissionStatusRequest missionStatusRequest) throws ServiceException {
        //如果发送过来的状态是执行中，那么就说明之前是待执行，查询等待执行的数据，开始飞行
        ThMission thMission = thMissionMapper.selectOne(new LambdaQueryWrapper<ThMission>()
                .eq(ThMission::getId, missionStatusRequest.getRequestId())
                .eq(ThMission::getMark, MarkEnum.VALID.getCode()));

        Integer status = null;
        if (AirPortTaskStatusEnum.FLIGHT.getCode() == missionStatusRequest.getStatus()) {
            log.info("被硬件调用，存任务状态：执行中");
//            ThMission thMission = getRecentlyRecord(missionStatusRequest,TaskStatusEnum.WAIT.getCode());
            Assert.notNull(thMission, "飞行任务不能为空！");
            ThMission thMissionUpdate = setStatus(missionStatusRequest, thMission, AirPortTaskStatusEnum.FLIGHT);
            try {
                //开始分析
                log.info("被硬件调用，存任务状态：开始分析");
                JSONObject jsonObject = this.startAI(missionStatusRequest);
                thMissionUpdate.setRequestId(jsonObject.getJSONObject("data").getString("requestId"));
                thMissionUpdate.setAipullUrl(jsonObject.getJSONObject("data").getString("aipullUrl"));
                thMissionUpdate.setAipushUrl(jsonObject.getJSONObject("data").getString("aipushUrl"));
                thMissionUpdate.setPlayUrl(missionStatusRequest.getPlayUrl());
                thMissionUpdate.setAiplayUrl(jsonObject.getJSONObject("data").getString("aiplayUrl"));
                thMissionUpdate.setAnalyseStatus(AiAnalyseStatusEnum.WAITING.getCode());

                log.info("被硬件调用，原任务状态：status：{}", thMission.getStatus());
                thMissionMapper.updateById(thMissionUpdate);

                status = TaskStatusEnum.FLIGHT.getCode();
            } catch (ServiceException e) {
                //如果调用DSP失败就直接失败！
                log.error("调用DSP数据失败：{}", e.getMessage());
                thMissionUpdate.setStatus(TaskStatusEnum.FAIL.getCode());
                thMissionMapper.updateById(thMissionUpdate);

                status = TaskStatusEnum.FAIL.getCode();
//                throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "任务分析失败！");
            }

            updateEmergencyMissionStatusService.updateStatus(thMission, status);
        } else if (AirPortTaskStatusEnum.WAIT.getCode() == missionStatusRequest.getStatus()) {
            log.info("被硬件调用，存任务状态：已完成");
            // 机场飞行完成，立即修改任务状态为已完成
            ThMission thMissionUpdate = new ThMission(UpdateOrCreateEnum.UPDATE.getCode());
            thMissionUpdate.setId(Integer.parseInt(missionStatusRequest.getRequestId()));
            thMissionUpdate.setStatus(TaskStatusEnum.COMPLETE.getCode());
            thMissionUpdate.setExecutionEndTime(new Date());
            try {
                AirWeatherVO weather = inspectionService.getWeather(thMission.getAirportId());
                String weatherStr = WeatherUtil.getWeather(weather);
                thMissionUpdate.setWeather(weatherStr);
            } catch (Exception e) {
                thMissionUpdate.setWeather("");
                log.info("获取天气信息失败，请重试");
            }

            log.info("被硬件调用，任务状态：status：{}", thMissionUpdate.getStatus());
            thMissionMapper.updateById(thMissionUpdate);

            status = TaskStatusEnum.COMPLETE.getCode();

            updateEmergencyMissionStatusService.updateStatus(thMission, status);

            //硬件停止后，停止AI分析
            this.stopAI(missionStatusRequest, thMission);
        } else {
            log.info("机场平台回调，修改任务状态，不存在的任务状态");
            throw new ServiceException(ServiceExceptionEnum.TASK_NOT_STATUS);
        }
        log.info("机场平台回调，修改任务状态结束");
        return true;
    }

    private JSONObject startAI(MissionStatusRequest missionStatusRequest) throws ServiceException {
        log.info("开始AI分析");
        //任务调用完成之后，调用发送通道，请求DSP需要分析
        //调用DSP接口
        JSONObject request = new JSONObject();
        JSONArray configList = new JSONArray();
        JSONObject instConfigMode = new JSONObject();
        instConfigMode.put("ename", "service_mode");
        instConfigMode.put("evalue", "1");
        configList.add(instConfigMode);
        JSONObject instConfigUrl = new JSONObject();
        instConfigUrl.put("ename", "callback_url");
        instConfigUrl.put("evalue", dspCallbackUrl);
        configList.add(instConfigUrl);
        request.put("serviceInstConfigList", configList);

        JSONArray reqList = new JSONArray();

        JSONObject instReqUrlPush = new JSONObject();
        instReqUrlPush.put("ename", "push_url");
        instReqUrlPush.put("evalue", missionStatusRequest.getPushUrl());
        reqList.add(instReqUrlPush);

        JSONObject instReqUrlPull = new JSONObject();
        instReqUrlPull.put("ename", "pull_url");
        instReqUrlPull.put("evalue", missionStatusRequest.getPullUrl());
        reqList.add(instReqUrlPull);

        request.put("serviceInstReqList", reqList);
        JSONObject responseJson = dspService.serviceInstApplication(request);
        if (responseJson.getIntValue("code") == 0) {
            String requestId = responseJson.getJSONObject("data").getString("requestId");
            log.info("dsp实时调用响应requestId：{}", requestId);

        } else {
            log.error("dsp实时调用失败：{}", responseJson);
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "任务失败！");
        }
        return responseJson;
    }

    private Boolean stopAI(MissionStatusRequest missionStatusRequest, ThMission thMission) {
        log.info("停止AI分析");
        Assert.notNull(thMission, "飞行任务不能为空！");
        ThMission thMissionUpdate = new ThMission(UpdateOrCreateEnum.UPDATE.getCode());
        thMissionUpdate.setId(thMission.getId());
        thMissionUpdate.setMileage(missionStatusRequest.getMileage());
        boolean result = false;
        // 任务调用完成之后，调用发送通道，请求DSP关闭请求
        // 调用DSP接口
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("requestId", thMission.getRequestId());
        JSONObject responseJson = new JSONObject();
        try {
            responseJson = dspService.serviceStopApplication(jsonObject);
            if (responseJson.getIntValue("code") == 0) {
                if (responseJson.containsKey("data") && ObjectUtil.isNotEmpty(responseJson.get("data"))) {
                    String requestId = responseJson.getJSONObject("data").getString("requestId");
                    log.info("dsp实时调用响应requestId：{}", requestId);
                } else {
                    log.info("dsp实时调用响应:{}", responseJson);
                }
                result = true;
            } else {
                log.error("dsp实时调用失败：{}", responseJson);
                thMissionUpdate.setAnalyseStatus(AiAnalyseStatusEnum.FAILED.getCode());
            }
            thMissionMapper.updateById(thMissionUpdate);
        } catch (Exception e) {
            log.error("dsp实时调用失败：{}", responseJson);
            thMissionUpdate.setAnalyseStatus(AiAnalyseStatusEnum.FAILED.getCode());
            thMissionMapper.updateById(thMissionUpdate);
        }

        return result;
    }

    private ThMission setStatus(MissionStatusRequest missionStatusRequest, ThMission thMission, AirPortTaskStatusEnum airPortTaskStatusEnum) {
        ThMission thMissionUpdate = new ThMission(UpdateOrCreateEnum.UPDATE.getCode());
        thMissionUpdate.setId(thMission.getId());
        if (missionStatusRequest.getStatus() == AirPortTaskStatusEnum.FLIGHT.getCode() && airPortTaskStatusEnum.getCode() == AirPortTaskStatusEnum.FLIGHT.getCode()) {
            thMissionUpdate.setPushUrl(missionStatusRequest.getPushUrl());
            thMissionUpdate.setPullUrl(missionStatusRequest.getPullUrl());
            thMissionUpdate.setStatus(TaskStatusEnum.FLIGHT.getCode());
        }
        return thMissionUpdate;
    }

    private ThMission getRecentlyRecord(MissionStatusRequest missionStatusRequest, Integer status) {
        //获取当前任务里面这个巡检的最近的那一条,修改对应的任务的状态
        LambdaQueryWrapper<ThMission> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.orderByAsc(ThMission::getExecutionStartTime);
        lambdaQueryWrapper.eq(ThMission::getInspectionLine, missionStatusRequest.getId());
        lambdaQueryWrapper.eq(ThMission::getId, missionStatusRequest.getRequestId());
        lambdaQueryWrapper.eq(ThMission::getStatus, status);
        //lambdaQueryWrapper.eq(ThMission::getTenantId,ShiroUtils.getTenantId());
        List<ThMission> thMissions = thMissionMapper.selectList(lambdaQueryWrapper);
        return thMissions.size() > 0 ? thMissions.get(0) : null;
    }


}
