package com.multictrl.modules.business.q20.handler;

import cn.hutool.json.JSONObject;
import com.multictrl.common.constant.BusinessConstant;
import com.multictrl.common.utils.CacheUtils;
import com.multictrl.common.utils.JsonUtils;
import com.multictrl.modules.business.handler.MessageHandler;
import com.multictrl.modules.business.service.MqttPushService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * Q20设备事件消息处理（topic: thing/device/{device_sn}/events）
 * 若need_reply=1需回复 events_reply 主题
 * method: liftoff(起飞事件) | arrival(到达事件) | takeoff(起飞指令进度) | land(降落指令进度) |
 * navigate(指点飞行进度) | route_upload(航线上传结果) | route_execute(航线执行进度) |
 * route_auto(一键飞行进度) | ota(固件升级进度)
 *
 * @author 938693313@qq.com
 * @since 1.0.0 2026/5/12
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class Q20EventsHandler implements MessageHandler {

    private final MqttPushService mqttPushService;

    @Override
    public void handleMessage(String topic, String payload, String gateway) {
        JSONObject message = JsonUtils.parseObject(payload, JSONObject.class);
        if (message == null) {
            log.debug("Q20 events --> payload解析失败，解析后为null");
            return;
        }

        String deviceSn = message.getStr(BusinessConstant.GATEWAY);
        Integer needReply = message.getInt(BusinessConstant.NEED_REPLY);
        if (needReply != null && needReply == 1) {
            JSONObject data;
            Object dataObject = message.get(BusinessConstant.DATA);
            if (dataObject instanceof JSONObject) {
                data = (JSONObject) dataObject;
            } else {
                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("Q20 events --> 已回复, deviceSn: {}, topic: {}", deviceSn, topic + BusinessConstant._REPLY);
        }

        // 重新解析，避免回复时修改了data对象
        message = JsonUtils.parseObject(payload, JSONObject.class);
        if (message == null) {
            return;
        }
        String method = message.getStr(BusinessConstant.METHOD);
        if (method == null) {
            log.debug("Q20 events --> method字段缺失, topic: {}", topic);
            return;
        }
        JSONObject data = message.getJSONObject(BusinessConstant.DATA);
        if (data == null) {
            return;
        }

        switch (method) {
            case Q20Constant.METHOD_LIFTOFF:
                handleLiftoff(deviceSn, data);
                break;
            case Q20Constant.METHOD_ARRIVAL:
                handleArrival(deviceSn, data);
                break;
            case Q20Constant.METHOD_TAKEOFF:
                handleProgress(deviceSn, "起飞指令", data);
                break;
            case Q20Constant.METHOD_LAND:
                handleProgress(deviceSn, "降落指令", data);
                break;
            case Q20Constant.METHOD_NAVIGATE:
                handleProgress(deviceSn, "指点飞行", data);
                break;
            case Q20Constant.METHOD_ROUTE_UPLOAD:
                handleRouteUpload(deviceSn, data);
                break;
            case Q20Constant.METHOD_ROUTE_EXECUTE:
                handleRouteExecute(deviceSn, data);
                break;
            case Q20Constant.METHOD_ROUTE_AUTO:
                handleRouteAuto(deviceSn, data);
                break;
            case Q20Constant.METHOD_OTA:
                handleOta(deviceSn, data);
                break;
            default:
                log.debug("Q20 events --> 未知method: {}, deviceSn: {}", method, deviceSn);
        }
    }

    /**
     * 起飞事件：飞机从停机状态转变到起飞状态时上报
     * type: command(指令飞行) | waypoint(航线飞行) | leapfrog(蛙跳飞行) | manual(手动飞行)
     */
    private void handleLiftoff(String deviceSn, JSONObject data) {
        CacheUtils.set(Q20Constant.Q20_LIFTOFF + deviceSn, data);
        log.info("Q20 events --> 起飞事件, deviceSn: {}, type: {}, wayline: {}",
                deviceSn, data.getStr("type"), data.getStr("wayline"));
    }

    /**
     * 到达事件：飞机飞到某位置停降时上报
     * type: land(直接降落) | preLand(准备降落) | emergency(应急降落)
     */
    private void handleArrival(String deviceSn, JSONObject data) {
        CacheUtils.set(Q20Constant.Q20_ARRIVAL + deviceSn, data);
        log.info("Q20 events --> 到达事件, deviceSn: {}, type: {}, code: {}",
                deviceSn, data.getStr("type"), data.getStr("code"));
    }

    /**
     * 通用指令进度：takeoff / land / navigate
     * status: in_progress | ok | failed | canceled 等
     */
    private void handleProgress(String deviceSn, String label, JSONObject data) {
        String status = data.getStr("status");
        JSONObject progress = data.getJSONObject("progress");
        int percent = progress != null ? progress.getInt("percent", 0) : 0;
        log.debug("Q20 events --> {}进度, deviceSn: {}, status: {}, percent: {}%",
                label, deviceSn, status, percent);
    }

    /**
     * 航线上传结果（need_reply=1已在上方统一处理）
     */
    private void handleRouteUpload(String deviceSn, JSONObject data) {
        String status = data.getStr("status");
        JSONObject progress = data.getJSONObject("progress");
        String stepKey = progress != null ? progress.getStr("step_key") : null;
        log.info("Q20 events --> 航线上传结果, deviceSn: {}, status: {}, step: {}",
                deviceSn, status, stepKey);
    }

    /**
     * 航线执行进度：缓存最新进度供前端轮询
     * progress含: step_key, percent, remaining_distance, first_point_distance,
     * first_point_remaining_time, first_point_progress, landing_progress
     */
    private void handleRouteExecute(String deviceSn, JSONObject data) {
        CacheUtils.set(Q20Constant.Q20_ROUTE_EXECUTE + deviceSn, data);
        String status = data.getStr("status");
        JSONObject progress = data.getJSONObject("progress");
        if (progress != null) {
            log.debug("Q20 events --> 航线执行进度, deviceSn: {}, status: {}, step: {}, percent: {}%, remain: {}m",
                    deviceSn, status, progress.getStr("step_key"),
                    progress.getInt("percent"), progress.getInt("remaining_distance"));
        } else {
            log.debug("Q20 events --> 航线执行进度, deviceSn: {}, status: {}", deviceSn, status);
        }
    }

    /**
     * 一键飞行执行进度：缓存最新进度供前端轮询
     */
    private void handleRouteAuto(String deviceSn, JSONObject data) {
        CacheUtils.set(Q20Constant.Q20_ROUTE_AUTO + deviceSn, data);
        String status = data.getStr("status");
        JSONObject progress = data.getJSONObject("progress");
        if (progress != null) {
            log.debug("Q20 events --> 一键飞行进度, deviceSn: {}, status: {}, step: {}, percent: {}%, remain: {}m",
                    deviceSn, status, progress.getStr("step_key"),
                    progress.getInt("percent"), progress.getInt("remaining_distance"));
        } else {
            log.debug("Q20 events --> 一键飞行进度, deviceSn: {}, status: {}", deviceSn, status);
        }
    }

    /**
     * 固件升级进度
     */
    private void handleOta(String deviceSn, JSONObject data) {
        String status = data.getStr("status");
        JSONObject progress = data.getJSONObject("progress");
        int percent = progress != null ? progress.getInt("percent", 0) : 0;
        log.info("Q20 events --> 固件升级进度, deviceSn: {}, status: {}, step: {}, percent: {}%",
                deviceSn, status,
                progress != null ? progress.getStr("step_key") : null, percent);
    }
}
