package com.multictrl.modules.business.q20.service.impl;

import cn.hutool.json.JSONObject;
import com.multictrl.common.exception.RenException;
import com.multictrl.modules.business.q20.dto.Q20ParamsDTO;
import com.multictrl.modules.business.q20.service.Q20ParamService;
import com.multictrl.modules.business.service.DJIBaseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * Q20参数指令服务实现
 * 复用 DJIBaseService 的 send/wait 机制，仅替换 topic 为 thing/device/ 前缀
 *
 * @author 938693313@qq.com
 * @since 1.0.0 2026/5/20
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class Q20ParamServiceImpl implements Q20ParamService {

    private final DJIBaseService djiBaseService;

    private static final String SERVICES_TOPIC = "thing/device/%s/services";

    // ────────────────────────────────────────────────
    // 内部通用方法
    // ────────────────────────────────────────────────

    /** set类指令：发送并等待回复，返回结果描述 */
    private String execSet(String deviceSn, String method, JSONObject data) {
        String topic = String.format(SERVICES_TOPIC, deviceSn);
        return djiBaseService.sendWaitReplyJudgeResult(topic, djiBaseService.getPayload(method, data));
    }

    /** get类指令：发送并等待回复，返回 param_value 字段值 */
    private Object execGet(String deviceSn, String method) {
        String topic = String.format(SERVICES_TOPIC, deviceSn);
        JSONObject data = new JSONObject();
        data.set("value", 0);
        JSONObject reply = djiBaseService.sendWaitReply(topic, djiBaseService.getPayload(method, data));
        if (reply == null) {
            throw new RenException("设备未响应，请检查设备是否在线");
        }
        if (reply.getInt("result", -1) != 0) {
            throw new RenException("设备返回错误: " + reply.getStr("message", "未知错误"));
        }
        return reply.get("param_value");
    }

    private JSONObject floatData(float value) {
        JSONObject d = new JSONObject();
        d.set("value", value);
        return d;
    }

    private JSONObject intData(int value) {
        JSONObject d = new JSONObject();
        d.set("value", value);
        return d;
    }

    private JSONObject strData(String value) {
        JSONObject d = new JSONObject();
        d.set("value", value);
        return d;
    }

    // ────────────────────────────────────────────────
    // 高度/距离限制
    // ────────────────────────────────────────────────

    @Override
    public String setHeightLimit(String deviceSn, float value) {
        return execSet(deviceSn, "set_height_limit", floatData(value));
    }

    @Override
    public Object getHeightLimit(String deviceSn) {
        return execGet(deviceSn, "get_height_limit");
    }

    @Override
    public String setDistanceLimit(String deviceSn, float value) {
        return execSet(deviceSn, "set_distance_limit", floatData(value));
    }

    @Override
    public Object getDistanceLimit(String deviceSn) {
        return execGet(deviceSn, "get_distance_limit");
    }

    // ────────────────────────────────────────────────
    // 围栏
    // ────────────────────────────────────────────────

    @Override
    public String setGeofenceAction(String deviceSn, String value) {
        return execSet(deviceSn, "set_geofence_action", strData(value));
    }

    @Override
    public Object getGeofenceAction(String deviceSn) {
        return execGet(deviceSn, "get_geofence_action");
    }

    // ────────────────────────────────────────────────
    // 返航
    // ────────────────────────────────────────────────

    @Override
    public String setReturnHeight(String deviceSn, float value) {
        return execSet(deviceSn, "set_return_height", floatData(value));
    }

    @Override
    public Object getReturnHeight(String deviceSn) {
        return execGet(deviceSn, "get_return_height");
    }

    @Override
    public String setReturnType(String deviceSn, String value) {
        return execSet(deviceSn, "set_return_type", strData(value));
    }

    @Override
    public Object getReturnType(String deviceSn) {
        return execGet(deviceSn, "get_return_type");
    }

    // ────────────────────────────────────────────────
    // 电池阈值
    // ────────────────────────────────────────────────

    @Override
    public String setBatteryLowThreshold(String deviceSn, float value) {
        return execSet(deviceSn, "set_battery_low_threshold", floatData(value));
    }

    @Override
    public Object getBatteryLowThreshold(String deviceSn) {
        return execGet(deviceSn, "get_battery_low_threshold");
    }

    @Override
    public String setBatteryCriticalThreshold(String deviceSn, float value) {
        return execSet(deviceSn, "set_battery_critical_threshold", floatData(value));
    }

    @Override
    public Object getBatteryCriticalThreshold(String deviceSn) {
        return execGet(deviceSn, "get_battery_critical_threshold");
    }

    @Override
    public String setBatteryEmergencyThreshold(String deviceSn, float value) {
        return execSet(deviceSn, "set_battery_emergency_threshold", floatData(value));
    }

    @Override
    public Object getBatteryEmergencyThreshold(String deviceSn) {
        return execGet(deviceSn, "get_battery_emergency_threshold");
    }

    @Override
    public String setLowBatteryAction(String deviceSn, String value) {
        return execSet(deviceSn, "set_low_battery_action", strData(value));
    }

    @Override
    public Object getLowBatteryAction(String deviceSn) {
        return execGet(deviceSn, "get_low_battery_action");
    }

    // ────────────────────────────────────────────────
    // 降落
    // ────────────────────────────────────────────────

    @Override
    public String setAprilTagId(String deviceSn, int value) {
        return execSet(deviceSn, "set_april_tag_id", intData(value));
    }

    @Override
    public Object getAprilTagId(String deviceSn) {
        return execGet(deviceSn, "get_april_tag_id");
    }

    @Override
    public String setPrecisionLandMode(String deviceSn, String value) {
        return execSet(deviceSn, "set_precision_land_mode", strData(value));
    }

    @Override
    public Object getPrecisionLandMode(String deviceSn) {
        return execGet(deviceSn, "get_precision_land_mode");
    }

    // ────────────────────────────────────────────────
    // 避障/传感器
    // ────────────────────────────────────────────────

    @Override
    public String setObstacleAvoidanceEnable(String deviceSn, int value) {
        return execSet(deviceSn, "set_obstacle_avoidance_enable", intData(value));
    }

    @Override
    public Object getObstacleAvoidanceEnable(String deviceSn) {
        return execGet(deviceSn, "get_obstacle_avoidance_enable");
    }

    @Override
    public String setObstacleAvoidanceDistance(String deviceSn, float value) {
        return execSet(deviceSn, "set_obstacle_avoidance_distance", floatData(value));
    }

    @Override
    public Object getObstacleAvoidanceDistance(String deviceSn) {
        return execGet(deviceSn, "get_obstacle_avoidance_distance");
    }

    @Override
    public String setVisualSensorEnable(String deviceSn, int value) {
        return execSet(deviceSn, "set_visual_sensor_enable", intData(value));
    }

    @Override
    public Object getVisualSensorEnable(String deviceSn) {
        return execGet(deviceSn, "get_visual_sensor_enable");
    }

    // ────────────────────────────────────────────────
    // 其他开关
    // ────────────────────────────────────────────────

    @Override
    public String setRtkEnable(String deviceSn, int value) {
        return execSet(deviceSn, "set_rtk_enable", intData(value));
    }

    @Override
    public Object getRtkEnable(String deviceSn) {
        return execGet(deviceSn, "get_rtk_enable");
    }

    @Override
    public String setUatMultCtrlEnable(String deviceSn, int value) {
        return execSet(deviceSn, "set_uat_mult_ctrl_enable", intData(value));
    }

    @Override
    public Object getUatMultCtrlEnable(String deviceSn) {
        return execGet(deviceSn, "get_uat_mult_ctrl_enable");
    }

    @Override
    public String setParachuteSafetyEnable(String deviceSn, int value) {
        return execSet(deviceSn, "set_parachute_safety_enable", intData(value));
    }

    @Override
    public Object getParachuteSafetyEnable(String deviceSn) {
        return execGet(deviceSn, "get_parachute_safety_enable");
    }

    // ────────────────────────────────────────────────
    // 批量
    // ────────────────────────────────────────────────

    @Override
    public String setParams(String deviceSn, Q20ParamsDTO dto) {
        JSONObject data = new JSONObject();
        if (dto.getBatteryLowThreshold() != null)       data.set("battery_low_threshold", dto.getBatteryLowThreshold());
        if (dto.getBatteryCriticalThreshold() != null)  data.set("battery_critical_threshold", dto.getBatteryCriticalThreshold());
        if (dto.getBatteryEmergencyThreshold() != null) data.set("battery_emergency_threshold", dto.getBatteryEmergencyThreshold());
        if (dto.getLowBatteryAction() != null)          data.set("low_battery_action", dto.getLowBatteryAction());
        if (dto.getHeightLimit() != null)               data.set("height_limit", dto.getHeightLimit());
        if (dto.getDistanceLimit() != null)             data.set("distance_limit", dto.getDistanceLimit());
        if (dto.getGeofenceAction() != null)            data.set("geofence_action", dto.getGeofenceAction());
        if (dto.getReturnHeight() != null)              data.set("return_height", dto.getReturnHeight());
        if (dto.getReturnSpeed() != null)               data.set("return_speed", dto.getReturnSpeed());
        if (dto.getReturnType() != null)                data.set("return_type", dto.getReturnType());
        if (dto.getObstacleAvoidanceEnable() != null)   data.set("obstacle_avoidance_enable", dto.getObstacleAvoidanceEnable());
        if (dto.getObstacleAvoidanceDistance() != null) data.set("obstacle_avoidance_distance", dto.getObstacleAvoidanceDistance());
        if (dto.getVisualSensorEnable() != null)        data.set("visual_sensor_enable", dto.getVisualSensorEnable());
        if (dto.getAprilTagId() != null)                data.set("april_tag_id", dto.getAprilTagId());
        if (dto.getPrecisionLandMode() != null)         data.set("precision_land_mode", dto.getPrecisionLandMode());
        if (dto.getDataLinkLossAction() != null)        data.set("data_link_loss_action", dto.getDataLinkLossAction());
        if (dto.getRcLossAction() != null)              data.set("rc_loss_action", dto.getRcLossAction());
        if (dto.getParachuteSafetyEnable() != null)     data.set("parachute_safety_enable", dto.getParachuteSafetyEnable());
        return execSet(deviceSn, "set_params", data);
    }

    @Override
    public JSONObject getParams(String deviceSn) {
        String topic = String.format(SERVICES_TOPIC, deviceSn);
        JSONObject data = new JSONObject();
        data.set("value", 0);
        JSONObject reply = djiBaseService.sendWaitReply(topic, djiBaseService.getPayload("get_params", data));
        if (reply == null) {
            throw new RenException("设备未响应，请检查设备是否在线");
        }
        if (reply.getInt("result", -1) != 0) {
            throw new RenException("设备返回错误: " + reply.getStr("message", "未知错误"));
        }
        return reply.getJSONObject("params");
    }
}
