package com.tuoheng.admin.service.inspection.update.status;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tuoheng.admin.constant.SystemConstant;
import com.tuoheng.admin.entity.*;
import com.tuoheng.admin.enums.MarkEnum;
import com.tuoheng.admin.enums.TaskStatusEnum;
import com.tuoheng.admin.enums.code.inspection.EditInspectionStatusCodeEnum;
import com.tuoheng.admin.mapper.*;
import com.tuoheng.admin.service.third.dsp.IDspService;
import com.tuoheng.admin.utils.AirWeatherUtil;
import com.tuoheng.admin.vo.AirWeatherVO;
import com.tuoheng.common.core.config.common.CommonConfig;
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.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class UpdateWaittStatusService {

    @Autowired
    private BusinessMapper businessMapper;

    @Autowired
    private TenantMapper tenantMapper;

    @Autowired
    private InspectionMapper inspectionMapper;

    @Autowired
    private FlightDataMapper flightDataMapper;

    @Autowired
    private ReportMapper reportMapper;

    @Autowired
    private IDspService dspService;

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

    public void updateWaittStatus(Inspection inspection) {
        Inspection inspectionUpdate = new Inspection();
        inspectionUpdate.setId(inspection.getId());
        inspectionUpdate.setStatus(TaskStatusEnum.COMPLETE.getCode());
        inspectionUpdate.setExecutionEndTime(DateUtils.now());

        List<Business> businessList = businessMapper.selectList(new LambdaQueryWrapper<Business>()
                                        .eq(Business::getTypeId, inspection.getId())
                                        .eq(Business::getMark, MarkEnum.VALID.getCode())
                                        .orderByDesc(Business::getCreateTime));

        if (CollectionUtil.isEmpty(businessList)) {
            // 硬件停止后，停止AI分析
            log.info("硬件停止后，停止AI分析, inspectionId:{}", inspection.getId());
            dspService.stopAI(businessList.get(0).getMsgId(), inspection.getId());
        } else {
            log.info("硬件停止后，停止AI分析, 业务数据为空, inspectionId:{}", inspection.getId());
        }

        //获取天气信息
        JsonResult result =  this.getWeather(CommonConfig.airportURL, inspection.getAirportId());
        if (0 != result.getCode()) {
            log.info("修改任务状态业务接口：获取天气信息失败：{}", result.getMsg());
            inspectionUpdate.setWeather("");
            inspectionMapper.updateById(inspectionUpdate);
            return;
        }
        AirWeatherVO weather = (AirWeatherVO) result.getData();
        String weatherStr = AirWeatherUtil.getWeather(weather);
        inspectionUpdate.setWeather(weatherStr);

        // 增加实时数据最后一次“飞行总里程”、“飞行总时长”
        FlightData flightData = this.getFlightData(inspection);
        if (ObjectUtil.isNotNull(flightData)) {
            inspectionUpdate.setFlyHeight(flightData.getUltrasonic());
            inspectionUpdate.setFlytime(flightData.getFlytime());
            inspectionUpdate.setMileage(flightData.getMileage());
        }

        inspectionMapper.updateById(inspectionUpdate);

        this.updateReport(inspection);
    }

    public JsonResult getWeather(String airportUrl, Integer airportId) {
        String url = UriComponentsBuilder.fromHttpUrl(CommonConfig.airportURL + SystemConstant.API_AIRPORT_GET_WEATHER)
                .queryParam("airportId", airportId)
                .toUriString();
        JsonResult jsonResult;
        try {
            jsonResult = restTemplate.getForObject(url, JsonResult.class);
        } catch (Exception e) {
            log.info("获机场列表接口异常, url:{}", url);
            throw new ServiceException("获机场列表接口异常");
        }
        try {
            if (ObjectUtil.isEmpty(jsonResult) || Objects.requireNonNull(jsonResult).getCode() != 0) {
                log.info("获取天气信息失败，url={}", url);
                log.info("获取天气信息失败，返回为空或code为0");
                return JsonResult.error(EditInspectionStatusCodeEnum.GET_WEATHER_FAILED.getCode(), EditInspectionStatusCodeEnum.GET_WEATHER_FAILED.getMsg());
            }
            if (ObjectUtil.isEmpty(jsonResult.getData())) {
                return JsonResult.success(new AirWeatherVO());
            }
            AirWeatherVO airWeatherVO = JSONObject.parseObject(JSONObject.toJSONString(jsonResult.getData()), AirWeatherVO.class);
            return JsonResult.success(airWeatherVO);
        } catch (Exception e) {
            log.error("获取天气信息失败，url={}", url);
            log.error("获取天气信息失败，异常!");
            return JsonResult.error(EditInspectionStatusCodeEnum.GET_WEATHER_FAILED.getCode(), EditInspectionStatusCodeEnum.GET_WEATHER_FAILED.getMsg());
        }
    }

    private FlightData getFlightData(Inspection inspection) {
        FlightData flightData = null;
        Integer flightDataCount = flightDataMapper.selectCount(new LambdaQueryWrapper<FlightData>()
                .eq(FlightData::getInspectionId, inspection.getId())
                .eq(FlightData::getTenantId, inspection.getTenantId())
                .eq(FlightData::getMark, MarkEnum.VALID.getCode()));
        log.info("坐标数据，flightDataCount:{}", flightDataCount);
        if (flightDataCount > 0) {
            int index = (int) Math.ceil((double) flightDataCount / 2);
            flightData = flightDataMapper.selectOne(new LambdaQueryWrapper<FlightData>()
                    .eq(FlightData::getInspectionId, inspection.getId())
                    .eq(FlightData::getTenantId, inspection.getTenantId())
                    .eq(FlightData::getMark, MarkEnum.VALID.getCode())
                    .orderByDesc(FlightData::getTimestamp)
                    .last("limit " + index + ",1"));

        }
        return flightData;
    }

    private void updateReport(Inspection inspection) {
        Report report = reportMapper.selectOne(Wrappers.<Report>lambdaQuery()
                .eq(Report::getInspectionId, inspection.getId())
                .eq(Report::getMark, MarkEnum.VALID.getCode()));
        if (ObjectUtil.isNull(report)) {
            log.info("该任务还没有生成报告，不需要修改报告的完成时间和状态");
            return;
        }
        report.setStatus(inspection.getStatus());
        report.setExecutionEndTime(inspection.getExecutionEndTime());
        reportMapper.updateById(report);
    }

}
