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

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.tuoheng.admin.constant.SystemConstant;
import com.tuoheng.admin.entity.domain.Inspection;
import com.tuoheng.admin.entity.domain.Tenant;
import com.tuoheng.admin.entity.vo.airport.AirPortCreateTaskVo;
import com.tuoheng.admin.enums.InspectionStatusEnum;
import com.tuoheng.admin.enums.code.inspection.ExecuteInspectionCodeEnum;
import com.tuoheng.admin.mapper.InspectionMapper;
import com.tuoheng.admin.mapper.TenantMapper;
import com.tuoheng.common.core.config.common.CommonConfig;
import com.tuoheng.common.core.exception.ServiceException;
import com.tuoheng.common.core.utils.DateUtils;
import com.tuoheng.common.core.utils.HttpUtils;
import com.tuoheng.common.core.utils.JsonResult;
import com.tuoheng.common.core.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Slf4j
@Service
public class ExecuteTaskService {

    @Autowired
    private TenantMapper tenantMapper;

    @Autowired
    private InspectionMapper inspectionMapper;

    @Autowired
    @Qualifier("restTemplate")
    private RestTemplate restTemplate;

    public JsonResult executeTask(String userId, Inspection inspection) {
        log.info("进入调用机场平台方法，执行任务");
        // 读取不同租户的机场平台url
        Tenant tenant = tenantMapper.selectById(inspection.getTenantId());
        if (ObjectUtil.isEmpty(tenant)) {
            log.info("进入调用机场平台方法: 租户不存在");
            return JsonResult.error(ExecuteInspectionCodeEnum.TENANT_IS_NOT_EXIST.getCode(), ExecuteInspectionCodeEnum.TENANT_IS_NOT_EXIST.getMsg());
        }
        AirPortCreateTaskVo airPortCreateTaskVo = this.createAirportTask(tenant, inspection);
        if (ObjectUtil.isEmpty(airPortCreateTaskVo)) {
            log.info("进入调用机场平台方法: 获取机场平台taskId失败");
            return JsonResult.error(ExecuteInspectionCodeEnum.AIRPORT_RETURN_TASK_ID_IS_NULL.getCode(), ExecuteInspectionCodeEnum.AIRPORT_RETURN_TASK_ID_IS_NULL.getMsg());
        }

        Integer airportTaskId = airPortCreateTaskVo.getId();
        Integer airlineFileId = airPortCreateTaskVo.getAirlineFileId();

        String url = CommonConfig.airportURL + SystemConstant.API_AIRPORT_EXECUTE_TASK;
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("taskId", airportTaskId);
        jsonObject.put("requestId", inspection.getId());
        jsonObject.put("requestName", inspection.getName());
        jsonObject.put("code", SystemConstant.PLATFORM_CODE); // 与机场平台约定好的
        jsonObject.put("tenantCode", tenant.getCode());

        log.info("执行任务, 调用机场平台: url:{}", url);
        log.info("执行任务, 调用机场平台: jsonObject:{}", jsonObject);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity httpEntity = new HttpEntity(jsonObject, headers);
        try {
            restTemplate.exchange(url, HttpMethod.POST, httpEntity, JsonResult.class);
        } catch (Exception e) {
            log.info("执行任务, 调用机场平台：机场接口异常, url:{}", url);
            log.info("执行任务, 调用机场平台：机场接口异常, httpEntity:{}", httpEntity);
            return JsonResult.error(ExecuteInspectionCodeEnum.AIRPORT_RETURN_DATA_IS_NULL.getCode(), ExecuteInspectionCodeEnum.AIRPORT_RETURN_DATA_IS_NULL.getMsg());
        }

        // 修改任务执行状态，防止手动执行和定时重复
        inspection.setAirportTaskId(airportTaskId);
        inspection.setInspectionLine(airlineFileId);
        this.updateInspectionExecutionStatus(userId, inspection);

        log.info("执行任务, 调用机场平台: 等待机场平台回调，修改执行任务状态");
        return JsonResult.success();
    }

    /**
     * 机场平台：周期性任务创建/修改
     *
     * @return
     */
    private AirPortCreateTaskVo createAirportTask(Tenant tenant, Inspection inspection) {
        String url = CommonConfig.airportURL + SystemConstant.API_AIRPORT_INSPECTION;
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("tenantCode", tenant.getCode());
        jsonObject.put("bnCode", SystemConstant.PLATFORM_CODE);
        jsonObject.put("name", inspection.getName());
        jsonObject.put("aid", inspection.getAirportId());
        jsonObject.put("airlineFileId", inspection.getInspectionLine());
        jsonObject.put("type", 1);  // 执行类型：1,单次;2,每天;3,指点;4,直面；5,每周;6,每月
        jsonObject.put("singleTime", inspection.getInspectionTime()); // 单次执行时间，如：2021-10-15 12:12:12

        log.info("调用机场平台，周期性任务创建，url:{}", url);
        log.info("调用机场平台，周期性任务创建，jsonObject:{}", jsonObject);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity httpEntity = new HttpEntity(jsonObject, headers);
        ResponseEntity<JsonResult> response;
        try {
            response = restTemplate.exchange(url, HttpMethod.POST, httpEntity, JsonResult.class);
        } catch (Exception e) {
            log.error("调用机场平台，周期性任务创建接口异常, url:{}", url);
            log.error("调用机场平台，周期性任务创建接口异常, httpEntity:{}", httpEntity);
            throw new ServiceException("调用机场平台，周期性任务创建接口异常");
        }
        JsonResult jsonResult = response.getBody();
        if (0 != jsonResult.getCode()) {
            log.info("调用机场平台，周期性任务创建，机场返回失败，jsonResult：{}", jsonResult.getMsg());
            throw new ServiceException("调用机场平台，周期性任务创建，机场返回失败");
        }

        AirPortCreateTaskVo airPortCreateTaskVo = JSONObject.parseObject(JSONObject.toJSONString(jsonResult.getData()), AirPortCreateTaskVo.class);

        log.info("调用机场平台，自主规划航线，airPortCreateTaskVo:{}", airPortCreateTaskVo);

        return airPortCreateTaskVo;
    }

    /**
     * 修改任务执行状态
     *
     * @param userId
     * @param inspection
     */
    private void updateInspectionExecutionStatus(String userId, Inspection inspection) {
        Inspection inspectionTmp = inspectionMapper.selectById(inspection.getId());
        if (InspectionStatusEnum.WAIT_FLIGHT.getCode() == inspectionTmp.getStatus()) {
            inspection.setStatus(InspectionStatusEnum.PREPARING.getCode());
        } else {
            // 此处是为解决将任务状态改为准备中之前，机场平台已经推送失败信息过来
            log.info("该任务状态不是待飞行，不需要修改为准备中，使用最新的状态，inspectionId={}, status={}，", inspectionTmp.getId(), inspectionTmp.getStatus());
            inspection.setStatus(inspectionTmp.getStatus());
        }
        inspection.setExecutionStatus(2);
        inspection.setExecutionStartTime(DateUtils.now());
        inspection.setUpdateUser(userId);
        inspection.setUpdateTime(DateUtils.now());
        Integer count = inspectionMapper.update(inspection);
        if (count <= 0) {
            log.info("执行任务，修改任务状态失败，inspectionId={}, status={}", inspection.getId(), inspection.getStatus());
        }
        log.info("执行任务，修改任务状态成功，inspectionId={}, status={}", inspection.getId(), inspection.getStatus());
    }
}