package com.tuoheng.admin.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.Question;
import com.tuoheng.admin.entity.domain.QuestionType;
import com.tuoheng.admin.entity.domain.ThInspection;
import com.tuoheng.admin.entity.domain.ThMission;
import com.tuoheng.admin.entity.request.*;
import com.tuoheng.admin.entity.vo.QuestionCountVO;
import com.tuoheng.admin.entity.vo.QuestionTypeCountVO;
import com.tuoheng.admin.enums.*;
import com.tuoheng.admin.mapper.QuestionMapper;
import com.tuoheng.admin.mapper.QuestionTypeMapper;
import com.tuoheng.admin.mapper.ThInspectionMapper;
import com.tuoheng.admin.mapper.ThMissionMapper;
import com.tuoheng.admin.service.IQuestionService;
import com.tuoheng.admin.service.IQuestionTypeService;
import com.tuoheng.common.common.BaseServiceImpl;
import com.tuoheng.common.exception.ServiceException;
import com.tuoheng.common.utils.JsonResult;
import com.tuoheng.common.utils.StringUtils;
import com.tuoheng.system.utils.ShiroUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 巡检问题表 服务实现类
 *
 * @author qiujinyang
 * @since 2022-08-03
 */
@Service
public class QuestionServiceImpl extends BaseServiceImpl<QuestionMapper, Question> implements IQuestionService {

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private QuestionTypeMapper questionTypeMapper;

    @Autowired
    private ThMissionMapper missionMapper;

    @Autowired
    private ThInspectionMapper inspectionMapper;

    @Autowired
    private IQuestionTypeService questionTypeService;

    private final static SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public IPage<Question> queryPage(QuestionQuery query) {
        if(null == query.getPage() || null == query.getLimit()){
            throw new ServiceException(ServiceExceptionEnum.PARAMETER_IS_NULL);
        }
        IPage<Question> pageData=null;
        try {
            // 获取分页数据
            IPage<Question> page = new Page<>(query.getPage(), query.getLimit());

            LambdaQueryWrapper<Question> questionLambdaQueryWrapper = new LambdaQueryWrapper<Question>()
                    .eq(ObjectUtil.isNotEmpty(query.getMissionId()), Question::getMissionId, query.getMissionId())
                    .like(ObjectUtil.isNotEmpty(query.getName()), Question::getMissionName, query.getName())
                    .eq(ObjectUtil.isNotEmpty(query.getType()), Question::getType, query.getType())
                    .eq(ObjectUtil.isNotEmpty(query.getStatus()), Question::getStatus, query.getStatus())
                    //.eq(Question::getTenantId, ShiroUtils.getTenantId())
                    .eq(Question::getMark, MarkTypeEnum.VALID.getCode()).orderByDesc(Question::getCreateTime);
            if(ObjectUtil.isNotEmpty(query.getStartTime()) && ObjectUtil.isNotEmpty(query.getEndTime())){
                query.setStartTime(query.getStartTime()+" 00:00:00");
                query.setEndTime(query.getEndTime()+" 23:59:59");
                questionLambdaQueryWrapper.between(Question::getCreateTime, dateformat.parse(query.getStartTime()), dateformat.parse(query.getEndTime()));
            }
            pageData  = questionMapper.selectPage(page, questionLambdaQueryWrapper);
        }catch (Exception e){
            e.printStackTrace();
            log.error("查询出错！");
        }
        return pageData;
    }

    @Override
    public List<Question> distributed(QuestionQuery query) {
        List<ThMission> thMissions = missionMapper.selectList(new LambdaQueryWrapper<ThMission>()
                .eq(ThMission::getMark, MarkTypeEnum.VALID.getCode())
                .in(ThMission::getStatus, Arrays.asList(TaskStatusEnum.FLIGHT.getCode(),TaskStatusEnum.FAIL.getCode(),TaskStatusEnum.COMPLETE.getCode()))
                .orderByDesc(ThMission::getUpdateTime));
        return getQuestions(query, thMissions);
    }

    private List<Question> getQuestions(QuestionQuery query, List<ThMission> thMissions) {
        if(thMissions.size()==0){
            return new ArrayList<>();
        }
        try {
            LambdaQueryWrapper<Question> questionLambdaQueryWrapper = new LambdaQueryWrapper<Question>()
                    .eq(ObjectUtil.isNotEmpty(query.getType()), Question::getType, query.getType())
                    .eq(Question::getStatus, QuestionStatusEnum.CONFIRM.getCode())
                    //.eq(Question::getTenantId, ShiroUtils.getTenantId())
                    .eq(Question::getMark, MarkTypeEnum.VALID.getCode()).orderByDesc(Question::getCreateTime);

            if(ObjectUtil.isNotEmpty(query.getStartTime()) && ObjectUtil.isNotEmpty(query.getEndTime())){
                query.setStartTime(query.getStartTime()+" 00:00:00");
                query.setEndTime(query.getEndTime()+" 23:59:59");
                questionLambdaQueryWrapper.between(Question::getCreateTime, dateformat.parse(query.getStartTime()), dateformat.parse(query.getEndTime()));
            }

            if((ObjectUtil.isNotEmpty(query.getStartTime()) && ObjectUtil.isNotEmpty(query.getEndTime()))
                    || StringUtils.isNotEmpty(query.getMissionName())){
                questionLambdaQueryWrapper.like(StringUtils.isNotEmpty(query.getMissionName()), Question::getMissionName, query.getMissionName());
            }else {
                //只需要取最上面的那一条
                questionLambdaQueryWrapper.eq(Question::getMissionId, thMissions.get(0).getId());
            }
            return questionMapper.selectList(questionLambdaQueryWrapper);
        }catch (Exception e){
            e.printStackTrace();
            log.error("查询出错！");
            return null;
        }
    }

    @Override
    public JsonResult<Boolean> check(QuestionStatusRequest entity) {
        //根据ID的数量来判断是否是批量确认和忽略
        Question question=new Question(UpdateOrCreateEnum.UPDATE.getCode());
        question.setStatus(entity.getStatus());
        int update;
        Integer qId;
        if(entity.getId().length>1){
            qId= entity.getId()[0];
            //批量
            update= questionMapper.update(question, new LambdaUpdateWrapper<Question>().in(Question::getId, Arrays.asList(entity.getId())));
        }else{
            //查询巡检问题分类
            List<QuestionType> questionTypeList = questionTypeMapper.selectList(new LambdaQueryWrapper<QuestionType>()
                    .eq(QuestionType::getCode, entity.getType())
                    .eq(QuestionType::getMark, 1));
            if(StringUtils.isNotEmpty(questionTypeList)){
                question.setQuestionName(questionTypeList.get(0).getContent());
                question.setQuestionDesc(questionTypeList.get(0).getContent());
            }
            //单个
            qId= entity.getId()[0];
            question.setId(qId);
            question.setType(entity.getType());
            update = questionMapper.updateById(question);
        }

        Integer missionId = questionMapper.selectById(qId).getMissionId();
        ThMission thMission=new ThMission(UpdateOrCreateEnum.UPDATE.getCode());
        thMission.setReportStatus(ReportStatusEnum.UPDATE.getCode());
        thMission.setId(missionId);
        missionMapper.updateById(thMission);


        return JsonResult.success(update>0);
    }

    @Override
    public JsonResult<List<QuestionCountVO>> analyze(Integer missionId) {
        List<QuestionCountVO> resultMap= questionMapper.analyze(missionId);
        return JsonResult.success(resultMap);
    }

    @Override
    public JsonResult<Map<String, Integer>> analyzeController(Integer missionId) {
        List<QuestionCountVO> questionCountVoList= questionMapper.analyze(missionId);
        Map<String,Integer> resultMap=new HashMap<>();
        for (QuestionCountVO questionCountVo : questionCountVoList) {
            setInfo(resultMap, questionCountVo,QuestionStatusEnum.CONFIRM.getCode(),QuestionStatusEnum.CONFIRM.name().toLowerCase());
            setInfo(resultMap, questionCountVo,QuestionStatusEnum.NEGLECT.getCode(),QuestionStatusEnum.NEGLECT.name().toLowerCase());
            setInfo(resultMap, questionCountVo,QuestionStatusEnum.NOTREVIEWED.getCode(),QuestionStatusEnum.NOTREVIEWED.name().toLowerCase());
        }
        int sum=0;
        if(!resultMap.containsKey(QuestionStatusEnum.CONFIRM.name().toLowerCase())){
            resultMap.put(QuestionStatusEnum.CONFIRM.name().toLowerCase(),0);
        }else{
            sum+=resultMap.get(QuestionStatusEnum.CONFIRM.name().toLowerCase());
        }

        if(!resultMap.containsKey(QuestionStatusEnum.NEGLECT.name().toLowerCase())){
            resultMap.put(QuestionStatusEnum.NEGLECT.name().toLowerCase(),0);
        }else{
            sum+=resultMap.get(QuestionStatusEnum.NEGLECT.name().toLowerCase());
        }
        resultMap.remove(QuestionStatusEnum.NEGLECT.name().toLowerCase());
        resultMap.put(QuestionStatusEnum.CONFIRM.name().toLowerCase(),sum);

        if(!resultMap.containsKey(QuestionStatusEnum.NOTREVIEWED.name().toLowerCase())){
            resultMap.put(QuestionStatusEnum.NOTREVIEWED.name().toLowerCase(),0);
        }
        return JsonResult.success(resultMap);
    }

    private static void setInfo(Map<String, Integer> resultMap, QuestionCountVO questionCountVo, Integer code, String name) {
        if(questionCountVo.getStatus().equals(code)){
            if(resultMap.containsKey(name)){
                Integer current = resultMap.get(name);
                current=current+questionCountVo.getQuantity();
                resultMap.put(name,current);
            }else{
                resultMap.put(name, questionCountVo.getQuantity());
            }
        }
    }

    @Override
    public JsonResult<List<QuestionTypeCountVO>> analyzeType(Integer missionId) {
        List<QuestionTypeCountVO> questionTypeCountList= questionMapper.analyzeType(missionId, ShiroUtils.getTenantId());

        //id
        //name
        //code
        //type
        //content

        //添加问题的分类
        List<QuestionType> questionTypeList=new ArrayList<>();
        try {
            questionTypeList = questionTypeService.getQuestionType();
        }catch (Exception e){
            e.printStackTrace();
        }
        Map<String,String> codeMap=new HashMap<>();
        for (QuestionType questionType : questionTypeList) {
            codeMap.put(questionType.getCode(),questionType.getContent());
        }
        for (QuestionTypeCountVO questionTypeCountVO : questionTypeCountList) {
            questionTypeCountVO.setContent(codeMap.get(questionTypeCountVO.getType()));
        }
        return JsonResult.success(questionTypeCountList);
    }

    @Override
    public JsonResult process(String requestId, CallbackRequest callbackRequest) throws ServiceException {

        ThMission mission = getThMission(requestId);
        Boolean aBoolean = saveQuestion(callbackRequest, mission);
        //如果任务已经完成就修改任务状态
        ThMission thMissionUpdate=new ThMission(UpdateOrCreateEnum.UPDATE.getCode());

        thMissionUpdate.setProgressbar(callbackRequest.getProgress());
        if(aBoolean){
            setComplate(callbackRequest, mission, thMissionUpdate);
        }else{
            setTaskStatusEnum(thMissionUpdate, TaskStatusEnum.FAIL, mission);
        }
        return JsonResult.success();
    }

    private void setTaskStatusEnum(ThMission thMissionUpdate, TaskStatusEnum statusEnum, ThMission mission) {
        thMissionUpdate.setStatus(statusEnum.getCode());
        thMissionUpdate.setId(mission.getId());
        thMissionUpdate.setExecutionEndTime(new Date());
        missionMapper.updateById(thMissionUpdate);
    }

    private void setComplate(CallbackRequest callbackRequest, ThMission mission, ThMission thMissionUpdate) {
        if(callbackRequest.getAnalyseStatus()== AiAnalyseStatusEnum.SUCCESS.getCode() || callbackRequest.getAnalyseStatus()== AiAnalyseStatusEnum.SUCCESS_TIMEOUT.getCode()){
            //这边存回放的视频地址
            thMissionUpdate.setVideoUrl(callbackRequest.getVideoUrl());
            thMissionUpdate.setAiVideoUrl(callbackRequest.getAiVideoUrl());

            if(callbackRequest.getAnalyseStatus()== AiAnalyseStatusEnum.SUCCESS_TIMEOUT.getCode()){
                thMissionUpdate.setAnalyseStatus(AiAnalyseStatusEnum.SUCCESS_TIMEOUT.getCode());
            }else{
                thMissionUpdate.setAnalyseStatus(AiAnalyseStatusEnum.SUCCESS.getCode());
            }

            setTaskStatusEnum(thMissionUpdate, TaskStatusEnum.COMPLETE, mission);
        }else if(callbackRequest.getAnalyseStatus()== AiAnalyseStatusEnum.FAILED.getCode()){
            setTaskStatusEnum(thMissionUpdate, TaskStatusEnum.FAIL, mission);
        }else{
            thMissionUpdate.setAnalyseStatus(AiAnalyseStatusEnum.RUNNING.getCode());
            setTaskStatusEnum(thMissionUpdate, TaskStatusEnum.FLIGHT, mission);
        }

    }

    private Boolean saveQuestion(CallbackRequest callbackRequest, ThMission mission) {
        List<CallbackRequest.QuestionFilesDTO> questionFiles = callbackRequest.getQuestionFiles();
        //获取当前飞行坐标，存问题的经纬度
        List<ThInspection> flightDataList = getThInspections(mission);
        List<Question> questionList = getQuestionList(mission, questionFiles, flightDataList);
        if(questionList.size()==0){
            return true;
        }
        return saveBatch(questionList);
    }

    private List<ThInspection> getThInspections(ThMission mission) {
        return inspectionMapper.selectList(new LambdaQueryWrapper<ThInspection>()
                .eq(ThInspection::getMissionId, mission.getId())
                .eq(ThInspection::getMark, MarkTypeEnum.VALID.getCode())
                .orderByDesc(ThInspection::getCreateTime));
    }

    private List<Question> getQuestionList(ThMission mission, List<CallbackRequest.QuestionFilesDTO> questionFiles, List<ThInspection> flightDataList) {
        List<Question> questionList=new ArrayList<>();
        if(ObjectUtil.isEmpty(questionFiles)){
            return questionList;
        }

        List<QuestionType> questionType = questionTypeService.getQuestionType();
        Map<String,QuestionType> typeMap=new HashMap<>();
        for (QuestionType type : questionType) {
            typeMap.put(type.getCode(),type);
        }
        for (CallbackRequest.QuestionFilesDTO questionFile : questionFiles) {
            Question question=new Question(UpdateOrCreateEnum.CREATE.getCode());
            BeanUtils.copyProperties(questionFile,question);
            ThInspection flightDataByTime = getFlightDataByTime(flightDataList, questionFile.getAnalyseTime().getTime());
            question.setMissionId(mission.getId());
            question.setMissionName(mission.getName());
            question.setLat(flightDataByTime.getLat());
            question.setLng(flightDataByTime.getLng());
            //待确认
            question.setStatus(QuestionStatusEnum.NOTREVIEWED.getCode());
            //问题类型
            QuestionType questionTypeInfo = typeMap.get(questionFile.getQuestionCode());
            question.setType(ObjectUtil.isNotEmpty(questionTypeInfo)? questionTypeInfo.getCode():"");
            question.setQuestionName(ObjectUtil.isNotEmpty(questionTypeInfo)? questionTypeInfo.getContent():"");
            question.setQuestionDesc(ObjectUtil.isNotEmpty(questionTypeInfo)? questionTypeInfo.getDescription():"");
            questionList.add(question);
        }
        return questionList;
    }

    private ThMission getThMission(String requestId) {
        LambdaQueryWrapper<ThMission> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ThMission::getMark,MarkTypeEnum.VALID.getCode())
                          .eq(ThMission::getRequestId, requestId)
                          .eq(ThMission::getStatus,TaskStatusEnum.FLIGHT.getCode()).orderByDesc(ThMission::getExecutionStartTime);
        List<ThMission> thMissions = missionMapper.selectList(lambdaQueryWrapper);
        if(ObjectUtil.isEmpty(thMissions) || thMissions.size()==0){
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(),"正在执行的任务不存在！");
        }
        return thMissions.get(0);
    }


    /**
     * 获取飞行坐标
     *
     * @param inspectionList 飞行坐标集合
     * @param time           当前时间
     * @return 当前飞行对象
     */
    private ThInspection getFlightDataByTime(List<ThInspection> inspectionList, long time) {
        if (CollectionUtils.isEmpty(inspectionList)) {
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "获取无人机飞行坐标失败！");
        }
        List<ThInspection> inspectionData =new ArrayList<>();
        for (ThInspection thInspection : inspectionList) {
            if(thInspection.getUpdateTime().getTime() <= time){
                inspectionData.add(thInspection);
            }
        }
        if (CollectionUtils.isEmpty(inspectionData)) {
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "获取无人机飞行坐标失败！");
        }
        return inspectionData.get(0);
    }
}
