package com.tuoheng.admin.service.impl;

import cn.hutool.core.lang.Assert;
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.Tenant;
import com.tuoheng.admin.entity.domain.ThInspection;
import com.tuoheng.admin.entity.domain.ThMission;
import com.tuoheng.admin.entity.domain.WarningRecord;
import com.tuoheng.admin.entity.request.InspectionRequest;
import com.tuoheng.admin.entity.request.PushAndPullURLRequest;
import com.tuoheng.admin.entity.vo.AirLineVO;
import com.tuoheng.admin.entity.vo.AirPortVO;
import com.tuoheng.admin.entity.vo.AirWeatherVO;
import com.tuoheng.admin.entity.vo.InspectionVO;
import com.tuoheng.admin.enums.AirportFlyTypeEnum;
import com.tuoheng.admin.enums.MarkTypeEnum;
import com.tuoheng.admin.enums.TaskStatusEnum;
import com.tuoheng.admin.enums.UpdateOrCreateEnum;
import com.tuoheng.admin.mapper.TenantMapper;
import com.tuoheng.admin.mapper.ThInspectionMapper;
import com.tuoheng.admin.mapper.ThMissionMapper;
import com.tuoheng.admin.mapper.WarningRecordMapper;
import com.tuoheng.admin.service.IMissionService;
import com.tuoheng.admin.service.IThInspectionService;
import com.tuoheng.common.common.BaseServiceImpl;
import com.tuoheng.common.exception.ServiceException;
import com.tuoheng.common.utils.*;
import com.tuoheng.system.entity.User;
import com.tuoheng.system.mapper.UserMapper;
import com.tuoheng.system.utils.ShiroUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @User qiujinyang
 * @Description
 * @Date Created by 2022/7/28 9:39
 */
@Service
@Slf4j
public class ThInspectionServiceImpl extends BaseServiceImpl<ThInspectionMapper, ThInspection> implements IThInspectionService {


    @Autowired
    private ThInspectionMapper inspectionMapper;

    @Autowired
    private ThMissionMapper missionMapper;

    @Autowired
    private TenantMapper tenantMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private IMissionService missionService;

    @Autowired
    private WarningRecordMapper warningRecordMapper;

    @Override
    public List<InspectionVO> track(Integer id) {
        ThMission mission = missionMapper.selectOne(new LambdaQueryWrapper<ThMission>()
                .eq(ThMission::getId, id)
                .eq(ThMission::getMark, 1));

        if (AirportFlyTypeEnum.POINTING_FLIGHT.getCode() == mission.getAirportFlyType()) {
            // 定点飞行
            WarningRecord warningRecord = warningRecordMapper.selectOne(new LambdaQueryWrapper<WarningRecord>()
                    .eq(WarningRecord::getEmergencyMissionId, id)
                    .eq(WarningRecord::getMark, MarkTypeEnum.VALID.getCode()));
            if (ObjectUtil.isNull(warningRecord)) {
                throw new ServiceException("该应急任务没有对应的预警记录");
            }
            ThMission oldMission = missionMapper.selectOne(new LambdaQueryWrapper<ThMission>()
                    .eq(ThMission::getId, warningRecord.getMissionId())
                    .eq(ThMission::getMark, MarkTypeEnum.VALID.getCode()));
            if (ObjectUtil.isNull(oldMission)) {
                throw new ServiceException("该应急任务没有对应的巡检任务记录");
            }
            if (mission.getAirportId().equals(oldMission.getAirportId())) {
                // 原机场执行的应急任务，在查看应急任务轨迹时，查询的是原巡检任务的轨迹
                id = oldMission.getId();
                log.info("该任务是应急任务，执行的是原机场，id={}", id);
            } else {
                log.info("该任务是应急任务，执行的是新机场，id={}", id);
            }
        }

        LambdaQueryWrapper<ThInspection> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        lambdaQueryWrapper.eq(ThInspection::getMissionId, id)
                .orderByAsc(ThInspection::getCreateTime);
        List<InspectionVO> result = new ArrayList<>();
        List<ThInspection> thInspections = inspectionMapper.selectList(lambdaQueryWrapper);

        for (ThInspection thInspection : thInspections) {
            InspectionVO inspectionVO = new InspectionVO();
            BeanUtils.copyProperties(thInspection, inspectionVO);
            result.add(inspectionVO);
        }
        return result;
    }

    @Override
    public Integer track(InspectionRequest inspectionRequest) throws ServiceException {
        ThInspection inspection = new ThInspection(UpdateOrCreateEnum.CREATE.getCode());
        BeanUtils.copyProperties(inspectionRequest, inspection);
        //获取当前巡检正在执行的任务
        List<ThMission> thMissions = missionMapper.selectList(new LambdaQueryWrapper<ThMission>()
                .eq(ThMission::getInspectionLine, inspectionRequest.getInspectionId())
                .eq(ThMission::getStatus, TaskStatusEnum.FLIGHT.getCode())
                .eq(ThMission::getMark, MarkTypeEnum.VALID.getCode()).orderByAsc(ThMission::getExecutionStartTime));
        if (ObjectUtil.isEmpty(thMissions) || thMissions.size() == 0) {
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "没有正在飞行的任务！");
        }
        ThMission mission = thMissions.get(0);
        inspection.setMissionId(mission.getId());
        inspection.setTenantId(mission.getTenantId());
        inspectionMapper.insert(inspection);
        return inspection.getId();
    }

    @Override
    public List<AirPortVO> airport() throws ServiceException, UnsupportedEncodingException {
        //这边需要配置到yml文件里面
        Tenant tenant = tenantMapper.selectById(ShiroUtils.getTenantId());
        String url = tenant.getAirportUrl() + "/api/airportInterface/airportList";
        String param = "page=1&limit=1000&tenantCode=" + tenant.getCode();
        log.info("****** airportList param tenantCode:{}", tenant.getCode());
        String airPortStr = HttpUtils.sendGet(url, param);
        JsonResult jsonResult = JacksonUtil.json2pojo(airPortStr, JsonResult.class);
        if (ObjectUtil.isEmpty(jsonResult) || (!ObjectUtil.isEmpty(jsonResult.getData()) && jsonResult.getCode() != 0)) {
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "获取机场信息失败，请重试");
        }
        return JSONObject.parseArray(JSONObject.parseObject(JSONObject.toJSONString(jsonResult.getData())).get("records").toString(), AirPortVO.class);
    }

    @Override
    public List<AirLineVO> airLine(Integer droneId) throws ServiceException {
        Tenant tenant = tenantMapper.selectById(ShiroUtils.getTenantId());
        //这边需要配置到yml文件里面
        String url = tenant.getAirportUrl() + "/api/airportInterface/taskByDroneId";
        String param = "page=1&limit=100&droneId=" + droneId;
        String airPortStr = HttpUtils.sendGet(url, param);
        JsonResult<AirLineVO> jsonResult = JacksonUtil.json2pojo(airPortStr, JsonResult.class);
        if (ObjectUtil.isEmpty(jsonResult) || (!ObjectUtil.isEmpty(Objects.requireNonNull(jsonResult).getData()) && jsonResult.getCode() != 0)) {
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "获取航线信息失败，请重试");
        }
        return JSONObject.parseArray(JSONObject.parseObject(JSONObject.toJSONString(jsonResult.getData())).get("records").toString(), AirLineVO.class);
    }

    @Override
    public JsonResult executeTask(String missionId, PushAndPullURLRequest pushAndPull) throws ServiceException {
        log.info("executeTask准备就绪");
        ThMission thMission = missionMapper.selectById(Integer.parseInt(missionId));
        log.info("mission查询完成");
        User user = userMapper.selectById(thMission.getCreateUser());
        log.info("user查询完成");
        Tenant tenant = tenantMapper.selectById(user.getTenantId());
        log.info("tenant查询完成");

        //这边需要配置到yml文件里面
        log.info("executeTask准备入参");
        String url = tenant.getAirportUrl() + "/api/airportInterface/executeTaskAnsy";
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", "lc");
        jsonObject.put("tenantCode", tenant.getCode());
        jsonObject.put("taskId", thMission.getInspectionLine());
        jsonObject.put("requestId", missionId);
        log.info("***** executeTask url:{};param:{}", url, jsonObject.toJSONString());
        String airPortStr = null;
        try {
            airPortStr = HttpUtils.doSend(url, jsonObject, null, "POST");
        } catch (Exception e) {
            log.error("调用机场executeTask接口异常：", e);
            return JsonResult.error("调用机场executeTask接口异常");
        }
        if (StringUtils.isEmpty(airPortStr)) {
            return JsonResult.error("机场接口返回数据为空");
        }
        JsonResult jsonResult = JacksonUtil.json2pojo(airPortStr, JsonResult.class);
        if (jsonResult.getCode() != 0) {
            return JsonResult.error(jsonResult.getMsg());
        }

        //将任务执行状态修改为已执行
        ThMission thMissionUpdate = new ThMission(UpdateOrCreateEnum.UPDATE.getCode());
        thMissionUpdate.setId(thMission.getId());
        thMissionUpdate.setExecutionStatus(2);
        missionMapper.updateById(thMissionUpdate);

        return JsonResult.success();
    }

    @Override
    public AirWeatherVO getWeather(Integer airportId) throws ServiceException {
        Tenant tenant = tenantMapper.selectById(ShiroUtils.getTenantId());
        //这边需要配置到yml文件里面
        String url = tenant.getAirportUrl() + "/api/airportInterface/getWeather";
        String param = "airportId=" + airportId;
        String weatherStr = HttpUtils.sendGet(url, param);
        JsonResult jsonResult;
        try {
            jsonResult = JacksonUtil.json2pojo(weatherStr, JsonResult.class);
            if (ObjectUtil.isEmpty(jsonResult) || Objects.requireNonNull(jsonResult).getCode() != 0) {
                throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "获取天气信息失败，请重试");
            }
            if (ObjectUtil.isEmpty(jsonResult.getData())) {
                return new AirWeatherVO();
            }
            return JSONObject.parseObject(JSONObject.toJSONString(jsonResult.getData()), AirWeatherVO.class);
        } catch (Exception e) {
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "获取天气信息失败，请重试");
        }
    }

    @Override
    public JsonResult lineTrack(Integer missionId) {
        Tenant tenant = tenantMapper.selectById(ShiroUtils.getTenantId());
        ThMission thMission = missionMapper.selectById(missionId);
        Assert.notNull(thMission, "任务不能为空！");
        Integer taskId = thMission.getInspectionLine();
        //解析标准srt文件里面的坐标，调用硬件接口，返回数据
        String url = tenant.getAirportUrl() + "/api/airportInterface/getLocationById";
        String param = "id=" + taskId;
        String airportLine = HttpUtils.sendGet(url, param);
        JsonResult jsonResult = JacksonUtil.json2pojo(airportLine, JsonResult.class);
        if (ObjectUtil.isEmpty(jsonResult) || Objects.requireNonNull(jsonResult).getCode() != 0) {
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "获取标准航线信息失败，请重试");
        }

        JSONArray resultData = JSONArray.parseArray(JSONObject.toJSONString(jsonResult.getData()));
        for (Object o : resultData) {
            JSONObject jsonObject = (JSONObject) o;
            jsonObject.put("lng", jsonObject.getString("lon"));
            jsonObject.remove("lon");
        }
        jsonResult.setData(resultData);

        System.out.println(jsonResult.getData().toString());
        return jsonResult;
    }

    @Override
    public JsonResult fightData(Integer id) {
        //校验
        if (null == id) {
            throw new ServiceException(ServiceExceptionEnum.PARAMETER_IS_NULL);
        }
        //根据任务id查询对应的遥测数据
        List<ThInspection> listData = inspectionMapper.selectListByMissionId(id, ShiroUtils.getTenantId());//xz

        return JsonResult.success(listData);
    }


}
