package com.multictrl.modules.business.handler;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.multictrl.common.config.MinioConfig;
import com.multictrl.common.constant.BusinessConstant;
import com.multictrl.common.utils.CacheUtils;
import com.multictrl.common.utils.FfmpegUtils;
import com.multictrl.common.utils.JsonUtils;
import com.multictrl.common.utils.Utils;
import com.multictrl.modules.business.dao.HmsDao;
import com.multictrl.modules.business.dto.MediaFileDTO;
import com.multictrl.modules.business.entity.HmsEntity;
import com.multictrl.modules.business.entity.RemoteLogEntity;
import com.multictrl.modules.business.service.CommandService;
import com.multictrl.modules.business.service.MediaFileService;
import com.multictrl.modules.business.service.MqttPushService;
import com.multictrl.modules.business.service.RemoteLogService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * events事件消息处理
 *
 * @author Sdy
 * @since 1.0.0 2026/4/27
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class EventsHandler implements MessageHandler {
    private final MqttPushService mqttPushService;
    private final CommandService commandService;
    private final MediaFileService mediaFileService;
    private final RemoteLogService remoteLogService;
    private final MinioConfig minioConfig;
    private final HmsDao hmsDao;

    @Override
    public void handleMessage(String topic, String payload, String gateway) {
//        log.debug("events --> topic: {}, payload: {}", topic, payload);
        JSONObject message = JsonUtils.parseObject(payload, JSONObject.class);
        if (message != null) {
            //不能写在这里，有airsense_warning(航班告警)，data为list，无需回复
//            JSONObject data = message.getJSONObject(BusinessConstant.DATA);
            Integer needReply = message.getInt(BusinessConstant.NEED_REPLY);
            if (needReply != null && needReply == 1) {
                log.debug("events --> 需要回复，topic: {}, payload: {}", topic, message);
                JSONObject data;
                Object dataObject = message.get(BusinessConstant.DATA);
                if (dataObject instanceof JSONObject) {
                    data = (JSONObject) dataObject;
                } else /*if(dataObject instanceof JSONArray)*/ {
                    data = new JSONObject();
                    message.set(BusinessConstant.DATA, data);
                }
                data.clear();
                data.set("result", 0);
                message.remove(BusinessConstant.NEED_REPLY);
                message.remove(BusinessConstant.GATEWAY);
                mqttPushService.pushMessageByClient1(topic + BusinessConstant._REPLY, message.toString());
                log.debug("events --> 回复成功，topic: {}, payload: {}", topic + BusinessConstant._REPLY, message);
            }
            message = JsonUtils.parseObject(payload, JSONObject.class);
            if (message == null) {
                return;
            }
            String method = message.getStr(BusinessConstant.METHOD);
            if (BusinessConstant.FLIGHTTASK_PROGRESS.equals(method)) {//航线任务进度上报
                log.debug("events --> 航线任务进度上报: {}", payload);
                JSONObject data = message.getJSONObject(BusinessConstant.DATA);
                //缓存起来，定频发送给web端
                CacheUtils.set(BusinessConstant.FLIGHT_TASK_PROGRESS + gateway, payload);
                if (data != null && data.containsKey("output")) {
                    JSONObject output = data.getJSONObject("output");
                    if (output.containsKey("status")) {
                        CacheUtils.set(BusinessConstant.FLIGHT_TASK_PROGRESS_STATUS + gateway, output.getStr("status"));
                    }
                    if (output.containsKey("ext")) {
                        JSONObject ext = output.getJSONObject("ext");
                        CacheUtils.set(BusinessConstant.FLIGHT_TASK_PROGRESS_FLIGHT_ID + gateway, ext.getStr("flight_id"));
                    }
                }
            } else if (BusinessConstant.TAKEOFF_TO_POINT_PROGRESS.equals(method)) {
                log.debug("events --> 一键起飞结果上报: {}", payload);
                JSONObject data = message.getJSONObject(BusinessConstant.DATA);
                String status = data.getStr("status");
                if ("wayline_ok".equals(status)) {
                    log.debug("收到一键起飞到点通知：{}争夺控制", gateway);
                    commandService.seizingControl(gateway);
                }
            } else if (BusinessConstant.FLY_TO_POINT_PROGRESS.equals(method)) {
                log.debug("events --> flyto执行结果上报: {}", payload);
                JSONObject data = message.getJSONObject(BusinessConstant.DATA);
                String status = data.getStr("status");
                if ("wayline_ok".equals(status)) {
                    log.debug("收到flyto到点通知：{}争夺控制", gateway);
                    commandService.seizingControl(gateway);
                }
            } else if (BusinessConstant.FILE_UPLOAD_CALLBACK.equals(method)) {
                log.debug("events --> 文件上传上报: {}", payload);
                JSONObject data = message.getJSONObject(BusinessConstant.DATA);
                MediaFileDTO mediaFile = new MediaFileDTO();
                if (data.containsKey("file")) {
                    JSONObject file = data.getJSONObject("file");
                    if (file == null) {
                        return;
                    }
                    String name = file.getStr("name");
                    if (!name.contains(".jpeg") && !name.contains(".mp4")) {//不接收MRK NAV OBS RTK数据包
                        return;
                    }
                    mediaFile.setName(name);
                    mediaFile.setPath(file.getStr("path"));
                    JSONObject ext = file.getJSONObject("ext");
                    if (ext != null) {
                        mediaFile.setTaskId(ext.getStr("flight_id"));
                        mediaFile.setOriginal(ext.getBool("is_original"));
                        mediaFile.setPayloadModelKey(ext.getStr("payload_model_key"));
                        mediaFile.setDroneModelKey(ext.getStr("drone_model_key"));
                    }
                    JSONObject metadata = file.getJSONObject("metadata");
                    if (metadata != null) {
                        mediaFile.setAbsoluteAltitude(metadata.getStr("absolute_altitude"));
                        mediaFile.setGimbalYawDegree(metadata.getStr("gimbal_yaw_degree"));
                        if (metadata.containsKey("shoot_position")) {
                            mediaFile.setLatitude(metadata.getJSONObject("shoot_position").getStr("lat"));
                            mediaFile.setLongitude(metadata.getJSONObject("shoot_position").getStr("lng"));
                        }
                        mediaFile.setRelativeAltitude(metadata.getStr("relative_altitude"));
                        String createdTime = metadata.getStr("created_time");
                        if (StrUtil.isNotBlank(createdTime)) {
                            OffsetDateTime offsetDateTime = OffsetDateTime.parse(createdTime);
                            mediaFile.setCreatedTime(Date.from(offsetDateTime.toInstant()));
                        }
                    }

                    if (file.containsKey("object_key")) {
                        mediaFile.setObjectKey(file.getStr("object_key"));
                        String filePath = minioConfig.getOther().getDataPath() + "/" + BusinessConstant.DOCK_MEDIA_BUCKET + "/" + mediaFile.getObjectKey();
                        long time = 0;
                        if (mediaFile.getObjectKey().contains(".jpeg")) {
                            //获取文件的subFileType,用来区分是正常的图片还是全景图(pano是全景图)
                            mediaFile.setSubFileType(Utils.getImageWindowsXpKeywords(filePath));
                            time = Utils.getImageTime(filePath);
                        } else if (mediaFile.getObjectKey().contains(".mp4")) {
                            time = Utils.getVideoTime(filePath);
                            mediaFile.setSubFileType("video");
                            //使用ffmpeg从视频中取一帧转换为图片，作为视频的封面
                            FfmpegUtils.generateVideoCover(filePath, filePath.replace(".mp4", "_cover.jpeg"));
                        }
                        log.info("time:{}", time);
                        if (time > 0) {
                            mediaFile.setCreatedTime(new Date(time));
                        }
                    }
                }
                mediaFile.setDockSn(gateway);
                mediaFileService.save(mediaFile);
            } else if (BusinessConstant.HMS.equals(method)) {
//                log.debug("events --> hms上报: {}", payload);
                JSONObject data = message.getJSONObject(BusinessConstant.DATA);
                String dockSn = message.getStr(BusinessConstant.GATEWAY);
                if (data != null) {
                    JSONArray list = data.getJSONArray("list");
                    if (list != null) {
                        List<HmsEntity> hmsList = new ArrayList<>();
                        for (Object object : list) {
                            JSONObject hms = (JSONObject) object;
                            HmsEntity hmsEntity = new HmsEntity();
                            hmsEntity.setGateway(gateway);
                            hmsEntity.setDockSn(dockSn);
                            hmsEntity.setDeviceType(hms.getStr("device_type"));
                            hmsEntity.setCode(hms.getStr("code"));
                            //是否为及时性的 {"0":"否","1":"是"}
                            hmsEntity.setImminent(hms.getInt("imminent") == 1 ? "是" : "否");
                            //是否飞行 {"0":"在地上","1":"在天上"}
                            hmsEntity.setInTheSky(hms.getInt("in_the_sky") == 1 ? "在天上" : "在地上");
                            //告警等级 {"0":"通知","1":"提醒","2":"警告"}
                            hmsEntity.setLevel(hms.getInt("level"));
                            //事件模块 {"0":"飞行任务","1":"设备管理","2":"媒体","3":"hms"}
                            int module = hms.getInt("module");
                            hmsEntity.setModule(module == 0 ? "飞行任务" : module == 1 ? "设备管理" : module == 2 ? "媒体" : "hms");
                            hmsEntity.setReportDate(new Date(message.getLong("timestamp")));
                            hmsList.add(hmsEntity);
                        }
                        hmsDao.insert(hmsList);
                    }
                }
            } else if (BusinessConstant.FILEUPLOAD_PROGRESS.equals(method)) {
                log.debug("events --> 远程日志上报: {}", payload);
                JSONObject data = message.getJSONObject(BusinessConstant.DATA);
                if (!data.containsKey("output") || !data.getJSONObject("output").containsKey("ext") ||
                        !data.getJSONObject("output").getJSONObject("ext").containsKey("files")) {
                    log.debug("无文件上传进度");
                    return;
                }
                JSONArray files = data.getJSONObject("output").getJSONObject("ext").getJSONArray("files");
                for (int i = 0; i < files.size(); i++) {
                    JSONObject file = files.getJSONObject(i);
                    JSONObject progress = file.getJSONObject("progress");
                    if (progress == null) {
                        log.debug("无文件上传进度,{},跳过", file);
                        continue;
                    }
                    String key = file.getStr("key");
                    String[] keys = key.split("/");
                    if (keys.length < 3) {
                        log.debug("文件路径错误,{},跳过", key);
                        continue;
                    }
                    RemoteLogEntity remoteLogEntity = remoteLogService.getDao().selectOne(
                            new QueryWrapper<RemoteLogEntity>().eq("dock_sn", keys[0])
                                    .eq("module", keys[1])
                                    .eq("filename", keys[2]));
                    if (remoteLogEntity == null) {
                        log.debug("无此文件,{},跳过", key);
                        continue;
                    }
                    remoteLogEntity.setStatus(progress.getStr("status"));
                    remoteLogEntity.setCurrentStep(progress.getInt("current_step", -1));
                    remoteLogEntity.setTotalStep(progress.getInt("total_step", -1));
                    int uploadRate = progress.getInt("upload_rate", 0);
                    if (uploadRate > 0) {
                        remoteLogEntity.setUploadRate(uploadRate);
                    }
                    remoteLogEntity.setSize(file.getLong("size") != null ? file.getLong("size") : -1);
                    remoteLogEntity.setCode(progress.getInt("result", -1));
                    if ("ok".equals(progress.getStr("status"))) {
                        remoteLogEntity.setPath(key);
                    }
                    remoteLogService.getDao().updateById(remoteLogEntity);
                }
            } else if (BusinessConstant.OTA_PROGRESS.equals(method)) {
                log.debug("events --> 固件升级进度: {}", payload);
            }
        } else {
            log.debug("events --> payload解析失败，解析后为null");
        }
    }
}
