package com.tuoheng.admin.service.impl;

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.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tuoheng.admin.common.ServiceExceptionEnum;
import com.tuoheng.admin.entity.domain.*;
import com.tuoheng.admin.entity.request.MissionRequest;
import com.tuoheng.admin.entity.request.MissionQuery;
import com.tuoheng.admin.entity.request.MissionStatusRequest;
import com.tuoheng.admin.entity.request.airport.ExecuteTaskStatusRequest;
import com.tuoheng.admin.entity.request.emergency.QueryEmergencyListRequest;
import com.tuoheng.admin.entity.request.emergency.QueryMissionListRequest;
import com.tuoheng.admin.entity.vo.AirWeatherVO;
import com.tuoheng.admin.entity.vo.LiveChannelVO;
import com.tuoheng.admin.entity.vo.MissionLiveVO;
import com.tuoheng.admin.entity.vo.MissionVO;
import com.tuoheng.admin.enums.*;
import com.tuoheng.admin.mapper.*;
import com.tuoheng.admin.service.IDspService;
import com.tuoheng.admin.service.IMissionService;
import com.tuoheng.admin.service.IThInspectionService;
import com.tuoheng.admin.service.mission.query.QueryEmergencyListService;
import com.tuoheng.admin.service.mission.query.QueryMissionListService;
import com.tuoheng.admin.service.third.airport.AirportCallBackUpdateStatusService;
import com.tuoheng.admin.utils.CodeUtil;
import com.tuoheng.admin.utils.TimeUtil;
import com.tuoheng.admin.utils.WeatherUtil;
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.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.*;

/**
 * 巡检任务接口实现
 *
 * @author: qiujinyang
 * @date: 2022/8/3
 */
@Service
@Slf4j
public class MissionServiceImpl extends BaseServiceImpl<ThMissionMapper, ThMission> implements IMissionService {

    @Autowired
    private ThMissionMapper thMissionMapper;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private ThInspectionMapper inspectionMapper;

    @Autowired
    private ReportMapper reportMapper;

    @Autowired
    private UserMapper userMapper;

    @Resource
    @Lazy
    private IThInspectionService inspectionService;

    @Resource
    private QueryMissionListService queryMissionListService;

    @Resource
    private QueryEmergencyListService queryEmergencyListService;

    @Resource
    private AirportCallBackUpdateStatusService airportCallBackUpdateStatusService;

    @Override
    public Integer addMission(MissionRequest addThMissionRequest) throws ServiceException {

        ThMission tm=new ThMission(UpdateOrCreateEnum.CREATE.getCode());
        tm.setCreateUser(ShiroUtils.getUserId());
        tm.setUpdateUser(ShiroUtils.getUserId());
        BeanUtils.copyProperties(addThMissionRequest,tm);

        //任务名称不能重复
        List<ThMission> thMissions = thMissionMapper.selectList(new LambdaQueryWrapper<ThMission>()
                        .eq(ThMission::getTenantId, ShiroUtils.getTenantId())//xz
                        .eq(ThMission::getName, addThMissionRequest.getName())
                        .eq(ThMission::getMark, MarkTypeEnum.VALID.getCode()));

        if(thMissions.size()>0){
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(),"任务名称不能重复!");
        }

        // 根据当前时间，生成任务编码
        String code = "XJRW" +CodeUtil.createCodeNo();
        tm.setCode(code);
        tm.setReportStatus(ReportStatusEnum.GENERATE.getCode());
        tm.setTenantId(ShiroUtils.getTenantId());//xz
        thMissionMapper.insert(tm);
        return tm.getId();
    }


    @Override
    public List<ThMission> getList(LambdaQueryWrapper<ThMission> lambdaQueryWrapper) {
        return thMissionMapper.selectList(lambdaQueryWrapper);
    }

    /**
     * 被硬件调用，执行任务后，回调执行状态
     */
    @Override
    public JsonResult updateExecuteTaskStatus(ExecuteTaskStatusRequest executeTaskStatusRequest) {
        JsonResult result = this.check(executeTaskStatusRequest);
        if (0 != result.getCode()) {
            log.info("被硬件调用，执行任务后，回调执行状态业务：校验失败：{}", result.getMsg());
            return result;
        }
        ThMission mission = (ThMission) result.getData();
        if (!"0".equals(executeTaskStatusRequest.getCode())) {
            log.info("被硬件调用，执行任务后，回调执行状态业务, 机场接口返回结果：失败：{}", executeTaskStatusRequest.getMsg());
            mission.setStatus(TaskStatusEnum.FAIL.getCode());
            this.updateMission(null, mission);

        } else {
            mission.setStatus(TaskStatusEnum.FLIGHT.getCode());
            this.updateMission(null, mission);
        }
        log.info("被硬件调用，任务执行后，回调执行状态业务成功");
        return JsonResult.success("被硬件调用，任务执行后，回调执行状态业务成功");
    }

    /**
     * 检查参数
     *
     * @param executeTaskStatusRequest
     * @return
     */
    private JsonResult check(ExecuteTaskStatusRequest executeTaskStatusRequest) {
        //查询出对应的巡检任务
        ThMission mission = thMissionMapper.selectOne(new LambdaQueryWrapper<ThMission>()
                .eq(ThMission::getMark, MarkEnum.VALID.getCode())
                .eq(ThMission::getId, executeTaskStatusRequest.getRequestId()));
        if (ObjectUtil.isEmpty(mission)) {
            log.info("任务不存在, missionId:{}", executeTaskStatusRequest.getRequestId());
            return JsonResult.error(500, "任务不存在" + executeTaskStatusRequest.getRequestId());
        }
        return JsonResult.success(mission);
    }

    /**
     * 修改任务执行时数据
     *
     * @param userId
     * @param mission
     */
    private void updateMission(Integer userId, ThMission mission) {
        mission.setStatus(mission.getStatus());
        mission.setUpdateUser(userId);
        mission.setUpdateTime(DateUtils.now());
        mission.setExecutionStartTime(DateUtils.now());
        thMissionMapper.updateById(mission);
    }

    /**
     * 机场平台回调，修改任务状态
     *
     * @param request
     * @return
     * @throws ServiceException
     */
    @Override
    public boolean updateStatus(MissionStatusRequest request) throws ServiceException {
        return airportCallBackUpdateStatusService.updateStatus(request);
    }

    @Override
    public IPage<MissionVO> findList(MissionQuery queryInspectionRequest) {
        Page<ThMission> page = new Page<>();
        page.setSize(queryInspectionRequest.getLimit());
        page.setCurrent(queryInspectionRequest.getPage());
        LambdaQueryWrapper<ThMission> queryMission=new LambdaQueryWrapper<>();
        queryParam(queryInspectionRequest, queryMission);
        queryMission.eq(ThMission::getTenantId, ShiroUtils.getTenantId())//xz
                .eq(ThMission::getMark,MarkTypeEnum.VALID.getCode())
                .orderByDesc(ThMission::getCreateTime);

        IPage<ThMission> thMissionIPage = thMissionMapper.selectPage(page, queryMission);
        List<ThMission> records = thMissionIPage.getRecords();

        Map<Integer, String> userName = getUserNameMap(records);
        List<MissionVO> result=new ArrayList<>();
        records.forEach(mission->{
            MissionVO missionVO=new MissionVO();
            BeanUtils.copyProperties(mission,missionVO);

            //获取最后一次的飞行时间
            getFlyTime(mission, missionVO);
            missionVO.setCreateUser(userName.get(mission.getCreateUser()));
            result.add(missionVO);
        });

        IPage<MissionVO> resultPage=new Page<>();
        resultPage.setCurrent(thMissionIPage.getCurrent());
        resultPage.setPages(thMissionIPage.getPages());
        resultPage.setSize(thMissionIPage.getSize());
        resultPage.setTotal(thMissionIPage.getTotal());
        resultPage.setRecords(result);
        return resultPage;
    }

    private void getFlyTime(ThMission mission, MissionVO missionVO) {
        if(missionVO.getStatus().equals(TaskStatusEnum.COMPLETE.getCode()) || missionVO.getStatus().equals(TaskStatusEnum.FLIGHT.getCode())) {
            LambdaQueryWrapper<ThInspection> lambdaInspection = new LambdaQueryWrapper<>();
            lambdaInspection.eq(ThInspection::getMissionId, mission.getId());
            lambdaInspection.eq(ThInspection::getMark, MarkTypeEnum.VALID.getCode()).orderByDesc(ThInspection::getCreateTime);
            List<ThInspection> thInspections = inspectionMapper.selectList(lambdaInspection);
            if (ObjectUtil.isNotEmpty(thInspections) && thInspections.size() > 0) {
                ThInspection temp = thInspections.get(0);
                missionVO.setFlyTime(TimeUtil.getFormatFlyTime(temp.getFlyTime() * 1000));
            }
        }
    }

    private Map<Integer, String> getUserNameMap(List<ThMission> records) {
        if(records.size()==0){
            return new HashMap<>();
        }
        Map<Integer,String> userName=new HashMap<>();
        Set<Integer> userId=new HashSet<>();
        records.forEach(thMission -> {
            userId.add(thMission.getCreateUser());
        });

        List<User> users = userMapper.selectList(new LambdaQueryWrapper<User>().in(User::getId, userId));
        for (User user : users) {
            userName.put(user.getId(),user.getRealname());
        }
        return userName;
    }

    private void queryParam(MissionQuery queryInspectionRequest, LambdaQueryWrapper<ThMission> queryInspection) {
        //编号
        queryInspection.like(StringUtils.isNotEmpty(queryInspectionRequest.getCode()),ThMission::getCode, queryInspectionRequest.getCode());
        //任务名称
        queryInspection.like(StringUtils.isNotEmpty(queryInspectionRequest.getName()),ThMission::getName, queryInspectionRequest.getName());
        //任务类型
        queryInspection.like(ObjectUtil.isNotEmpty(queryInspectionRequest.getType()),ThMission::getType, queryInspectionRequest.getType());
        //任务状态
        queryInspection.eq(ObjectUtil.isNotEmpty(queryInspectionRequest.getStatus()),ThMission::getStatus, queryInspectionRequest.getStatus());
        //巡检机场
        queryInspection.eq(ObjectUtil.isNotEmpty(queryInspectionRequest.getAirportId()),ThMission::getAirportId, queryInspectionRequest.getAirportId());
        //巡检线路
        queryInspection.eq(ObjectUtil.isNotEmpty(queryInspectionRequest.getInspectionLine()),ThMission::getInspectionLine, queryInspectionRequest.getInspectionLine());
        //巡检类型
        //queryInspection.eq(ObjectUtil.isNotEmpty(queryInspectionRequest.getInspectionType()),ThMission::getInspectionType, queryInspectionRequest.getInspectionType());
    }

    @Override
    public MissionVO findById(Integer id) {
        MissionVO missionVO=new MissionVO();
        LambdaQueryWrapper<ThMission> queryWrapper = new LambdaQueryWrapper<>();//xz
        queryWrapper.eq(ThMission::getTenantId, ShiroUtils.getTenantId()).eq(ThMission::getId, id);//xz
        BeanUtils.copyProperties(thMissionMapper.selectOne(queryWrapper),missionVO);//xz
        return missionVO;
    }


    @Override
    public boolean deleteBatch(List<Integer> idList) {
        //Integer updateUser = ShiroUtils.getUserId();
        ThMission mission=new ThMission(UpdateOrCreateEnum.UPDATE.getCode());
        mission.setMark(MarkTypeEnum.NOTVALID.getCode());
        boolean result=false;
        //如果成功更新
        if(thMissionMapper.update(mission,new LambdaUpdateWrapper<ThMission>().in(ThMission::getId,idList))>0){
            Integer missionId = mission.getId();
            questionMapper.delete(new LambdaQueryWrapper<Question>().eq(Question::getMissionId,missionId));
            inspectionMapper.delete(new LambdaQueryWrapper<ThInspection>().eq(ThInspection::getMissionId,missionId));
            reportMapper.delete(new LambdaQueryWrapper<Report>().eq(Report::getMissionId,missionId));
            result=true;
        }
        return result;
    }

    @Override
    public MissionLiveVO live(Integer id) {
        //根据机场的Id查询出来直播的对象
        LambdaQueryWrapper<ThMission> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ThMission::getTenantId,ShiroUtils.getTenantId());//xz
        lambdaQueryWrapper.eq(ThMission::getMark,MarkTypeEnum.VALID.getCode());
        lambdaQueryWrapper.eq(ThMission::getAirportId,id);
        lambdaQueryWrapper.eq(ThMission::getStatus,TaskStatusEnum.FLIGHT.getCode()).orderByDesc(ThMission::getExecutionStartTime);
        List<ThMission> thMissions = thMissionMapper.selectList(lambdaQueryWrapper);
        //一般不会出现多条，如果出现，就说明有问题，应该取最后执行的那一条
        ThMission thMission= ObjectUtil.isEmpty(thMissions)? null :thMissions.get(0);
        MissionLiveVO missionLiveVO=null;
        if(ObjectUtil.isNotEmpty(thMission)){
            missionLiveVO=new MissionLiveVO();
            BeanUtils.copyProperties(thMission,missionLiveVO);
        }
        return missionLiveVO;
    }

    @Override
    public JsonResult getVideoById(String id) {
        if (StringUtils.isEmpty(id)) {
            return JsonResult.error(QueryVideoServiceEnum.MISSION_ID_IS_NULL.getCode(), QueryVideoServiceEnum.MISSION_ID_IS_NULL.getMsg());
        }
        LambdaQueryWrapper<ThMission> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ThMission::getTenantId, ShiroUtils.getTenantId()).eq(ThMission::getId, id);
        ThMission thMission = thMissionMapper.selectOne(queryWrapper);//xz
        if (ObjectUtil.isNull(thMission)) {
            return JsonResult.error(QueryVideoServiceEnum.MISSION_IS_NOT_EXIST.getCode(), QueryVideoServiceEnum.MISSION_IS_NOT_EXIST.getMsg());

        }
        LiveChannelVO liveChannelVo = new LiveChannelVO();
        if(TaskStatusEnum.FLIGHT.getCode() == thMission.getStatus()){
            //任务飞行中进行直播
            if(StringUtils.isNotEmpty(thMission.getAipullUrl())){
                liveChannelVo.setAiPullUrl(thMission.getAipullUrl());
            }
        }
        if(TaskStatusEnum.COMPLETE.getCode() == thMission.getStatus()){
            //任务飞行完成,回放视频
            if(StringUtils.isNotEmpty(thMission.getAiVideoUrl())){
                liveChannelVo.setAiVideoUrl(thMission.getAiVideoUrl());
            }
        }
        return JsonResult.success(liveChannelVo);
    }

    /**
     * 查询任务列表
     *
     * @return
     */
    @Override
    public JsonResult getList(QueryMissionListRequest request) {
        return queryMissionListService.getList(request);
    }

    @Override
    public JsonResult getEmergencyList(QueryEmergencyListRequest request) {
        return queryEmergencyListService.getList(request);
    }

}