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

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tuoheng.admin.entity.domain.Business;
import com.tuoheng.admin.entity.domain.FlightData;
import com.tuoheng.admin.entity.domain.Inspection;
import com.tuoheng.admin.entity.domain.QuestionType;
import com.tuoheng.admin.enums.*;
import com.tuoheng.admin.mapper.*;
import com.tuoheng.admin.entity.request.third.DspCallbackRequest;
import com.tuoheng.admin.entity.request.third.QuestionFile;
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.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * DSP回调 服务实现类
 *
 * @author WangHaoran
 * @since 2021-09-01
 */
@Slf4j
@Service
public class DspCallbackServiceImpl implements IDspCallbackService {

    @Autowired
    private BusinessMapper businessMapper;

    @Autowired
    private InspectionMapper inspectionMapper;

    @Autowired
    private FlightDataMapper flightDataMapper;

    @Autowired
    private QuestionTypeMapper questionTypeMapper;

    /**
     * 保存DSP回调数据
     *
     * @param requestId          请求id
     * @param dspCallbackRequest 回调请求体
     * @return
     */
    @Override
    public JsonResult saveCallbackData(String requestId, DspCallbackRequest dspCallbackRequest) {
        log.info("DSP服务回调地址接收成功, requestId：{}, callbackRequest:{}", requestId, JacksonUtil.obj2StringPretty(dspCallbackRequest));
        log.info("以下为打印的回调参数");
        log.info("requestId为：{}", requestId);
        log.info(JSON.toJSONString(dspCallbackRequest));

        // 查询业务表数据
        Business business = businessMapper.selectOne(new LambdaQueryWrapper<Business>()
                .eq(Business::getMsgId, requestId)
                .eq(Business::getType, 1)
                .last("limit 1"));
        if (StringUtils.isNull(business)) {
            log.info("业务关系数据不存在，requestId：{}", requestId);
            throw new ServiceException(0, "业务数据不存在");
        }
        if (StringUtils.isNull(business.getTypeId())) {
            log.info("业务关系数据，巡检任务ID不存在，typeId：{}", business.getTypeId());
            throw new ServiceException(0, "业务数据中巡检任务ID不存在");
        }
        log.info("业务关系数据, business：{}", business);

        // 查询任务
        Inspection inspection = inspectionMapper.selectOne(new LambdaQueryWrapper<Inspection>()
                .eq(Inspection::getId, business.getTypeId())
                .eq(Inspection::getTenantId, business.getTenantId()));
        if (ObjectUtil.isNull(inspection)) {
            log.info("任务不存在");
            throw new ServiceException(0, "巡检任务不存在");
        }
        log.info("巡检任务查询成功，分析状态为：{}", dspCallbackRequest.getAnalyseStatus());
        // 分析状态处理: 5：waiting(等待)、10：running(分析中)、15：success(分析完成)、20：timeout(成功超时)、25：failed(分析失败)
        if (dspCallbackRequest.getAnalyseStatus().equals(5)) {
            // 等待
            inspection.setAnalyseStatus(2);
        } else if (dspCallbackRequest.getAnalyseStatus().equals(10)) {
            // 分析中
            inspection.setAnalyseStatus(3);
        } else if (dspCallbackRequest.getAnalyseStatus().equals(15)) {
            // 分析完成
            inspection.setAnalyseStatus(4);
        } else if (dspCallbackRequest.getAnalyseStatus().equals(20)) {
            // 成功超时
            inspection.setAnalyseStatus(5);
        } else if (dspCallbackRequest.getAnalyseStatus().equals(25)) {
            // 分析失败
            inspection.setAnalyseStatus(6);
        }
        // 分析进度
        log.info("巡检任务查询成功，分析进度为：{}", dspCallbackRequest.getProgress());
        inspection.setProgressbar(dspCallbackRequest.getProgress());
        // 视频处理
        if (dspCallbackRequest.getType().equals(1)) {
            // 实时直播
            log.info("实时直播视频处理");
            log.info("实时直播视频，原视频地址：{}", dspCallbackRequest.getVideoUrl());
            log.info("实时直播视频，分析后视频地址：{}", dspCallbackRequest.getAiVideoUrl());
            if (StringUtils.isNotBlank(dspCallbackRequest.getVideoUrl())) {
                inspection.setVideoUrl(StringUtils.removeHost(dspCallbackRequest.getVideoUrl(), CommonConfig.videoURL));
            }
            if (StringUtils.isNotBlank(dspCallbackRequest.getAiVideoUrl())) {
                inspection.setAiVideoUrl(StringUtils.removeHost(dspCallbackRequest.getAiVideoUrl(), CommonConfig.videoURL));
            }
        } else if (dspCallbackRequest.getType().equals(2)) {
            // 离线识别
            log.info("离线检测视频处理");
            log.info("离线检测视频，分析后视频地址：{}", dspCallbackRequest.getAiVideoUrl());
            if (StringUtils.isNotBlank(dspCallbackRequest.getAiVideoUrl())) {
                inspection.setAiVideoUrl(StringUtils.removeHost(dspCallbackRequest.getAiVideoUrl(), CommonConfig.videoURL));
            }
        }
        inspection.setUpdateTime(DateUtils.now());
        inspectionMapper.updateByPrimaryKey(inspection);
        log.info("巡检任务状态更新成功");

        log.info("巡检任务分析问题图片处理开始，此处图片数量为：{}张", StringUtils.isNull(dspCallbackRequest.getQuestionFiles()) ? 0 : dspCallbackRequest.getQuestionFiles().size());

        // 分析处理图片并入库
        log.info("以下为本地问题图片信息：");
        log.info(JSON.toJSONString(dspCallbackRequest.getQuestionFiles()));
        List<QuestionFile> questionFiles = dspCallbackRequest.getQuestionFiles();
        if (!CollectionUtils.isEmpty(questionFiles)) {
            log.info("问题图片处理开始, 图片数量：{}", questionFiles.size());
            // 坐标
            boolean online_condition = AiAnalyseTypeEnum.ONLINE.getCode() == inspection.getIsLive();
            boolean offline_condition = AiAnalyseTypeEnum.OFFLINE.getCode() == inspection.getIsLive();
            log.info("在线：{}, 离线：{}", online_condition, offline_condition);
            List<FlightData> flightDataList = flightDataMapper.selectList(new LambdaQueryWrapper<FlightData>()
                    .eq(FlightData::getInspectionId, business.getTypeId())
                    .notLike(online_condition, FlightData::getLng, "E-")
                    .notLike(online_condition, FlightData::getLng, "0.0")
                    .notLike(online_condition, FlightData::getLat, "E-")
                    .notLike(online_condition, FlightData::getLat, "0.0")
                    .orderByDesc(FlightData::getTimestamp));
            if (!CollectionUtils.isEmpty(flightDataList)) {
                log.info("飞行坐标大小：{}", flightDataList.size());
            }
        }
        return JsonResult.success();
    }

    /**
     * 根据问题类型封装成map
     * @return
     */
    private Map<String, QuestionType> getStringQuestionTypeMap() {
        List<QuestionType> questionTypeList = questionTypeMapper.selectList(Wrappers.<QuestionType>lambdaQuery()
                .eq(QuestionType::getMark, MarkEnum.VALID.getCode()));
        Map<String, QuestionType> questionTypeMap = new HashMap<>();
        for (QuestionType type : questionTypeList) {
            questionTypeMap.put(type.getCode(), type);
        }
        return questionTypeMap;
    }

    /**
     * 获取飞行坐标
     *
     * @param flightDataList 飞行坐标集合
     * @param time           当前时间
     * @return 当前飞行对象
     */
    private FlightData getFlightDataByTime(List<FlightData> flightDataList, long time) {
        if (CollectionUtils.isEmpty(flightDataList)) {
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "获取无人机飞行坐标失败！");
        }
        List<FlightData> flightData = flightDataList.stream().filter(data -> {
            try {
                return Long.valueOf(data.getTimestamp()) <= time;
            } catch (Exception e) {
                log.error("获取飞行数据异常：", e);
                log.error("批量插入问题图片数据:{}", JacksonUtil.obj2StringPretty(data));
                return false;
            }
        }).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(flightData)) {
            throw new ServiceException(HttpStatus.BAD_REQUEST.value(), "获取无人机飞行坐标失败！");
        }
        return flightData.get(0);
    }

}
