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.*;
import com.multictrl.modules.business.q20.service.Q20CommandService;
import com.multictrl.modules.business.service.DJIBaseService;
import com.multictrl.modules.business.service.MqttPushService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * Q20控制指令服务实现
 *
 * @author 938693313@qq.com
 * @since 1.0.0 2026/5/20
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class Q20CommandServiceImpl implements Q20CommandService {

    private final DJIBaseService djiBaseService;
    private final MqttPushService mqttPushService;

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

    private String execCmd(String deviceSn, String method, JSONObject data) {
        String topic = String.format(SERVICES_TOPIC, deviceSn);
        JSONObject payload = djiBaseService.getPayload(method, data);
        payload.set("gateway", deviceSn);
        payload.set("need_reply", 1);
        return djiBaseService.sendWaitReplyJudgeResult(topic, payload);
    }

    private JSONObject execCmdGetReply(String deviceSn, String method, JSONObject data) {
        String topic = String.format(SERVICES_TOPIC, deviceSn);
        JSONObject payload = djiBaseService.getPayload(method, data);
        payload.set("gateway", deviceSn);
        payload.set("need_reply", 1);
        JSONObject reply = djiBaseService.sendWaitReply(topic, payload);
        if (reply == null) {
            throw new RenException("设备未响应，请检查设备是否在线");
        }
        return reply;
    }

    // ==================== 飞行控制 ====================

    @Override
    public String takeoff(String deviceSn, Q20TakeoffDTO dto) {
        JSONObject data = new JSONObject();
        data.set("mode", dto.getMode());
        data.set("altitude", dto.getAltitude());
        return execCmd(deviceSn, "takeoff", data);
    }

    @Override
    public String land(String deviceSn, Q20LandDTO dto) {
        JSONObject data = new JSONObject();
        data.set("mode", dto.getMode());
        data.set("qr_code", dto.getQrCode());
        return execCmd(deviceSn, "land", data);
    }

    @Override
    public String stop(String deviceSn) {
        JSONObject data = new JSONObject();
        data.set("value", 1);
        return execCmd(deviceSn, "stop", data);
    }

    @Override
    public String goHome(String deviceSn, Q20GoHomeDTO dto) {
        if (dto.getMode() == 1 && dto.getSafeAltitude() == null) {
            throw new RenException("返航模式为安全高度返回(mode=1)时，必须填写安全返航高度(safe_altitude)");
        }
        if (dto.getSpecificHome() != null && dto.getSpecificHome() == 1 && dto.getHomePoint() == null) {
            throw new RenException("指定返航点(specific_home=1)时，必须填写返航点坐标(home_point)");
        }
        JSONObject data = new JSONObject();
        data.set("mode", dto.getMode());
        if (dto.getSafeAltitude() != null) {
            data.set("safe_altitude", dto.getSafeAltitude());
        }
        if (dto.getSpeed() != null) {
            data.set("speed", dto.getSpeed());
        }
        if (dto.getSpecificHome() != null) {
            data.set("specific_home", dto.getSpecificHome());
        }
        if (dto.getHomePoint() != null) {
            Q20GoHomeDTO.HomePoint hp = dto.getHomePoint();
            JSONObject homePoint = new JSONObject();
            homePoint.set("longitude", hp.getLongitude());
            homePoint.set("latitude", hp.getLatitude());
            homePoint.set("altitude", hp.getAltitude());
            homePoint.set("heading", hp.getHeading());
            data.set("home_point", homePoint);
        }
        return execCmd(deviceSn, "go_home", data);
    }

    @Override
    public String setHome(String deviceSn, Q20SetHomeDTO dto) {
        JSONObject data = new JSONObject();
        data.set("longitude", dto.getLongitude());
        data.set("latitude", dto.getLatitude());
        data.set("altitude", dto.getAltitude());
        data.set("heading", dto.getHeading());
        if (dto.getCurrentGps() != null) {
            data.set("current_gps", dto.getCurrentGps());
        }
        return execCmd(deviceSn, "set_home", data);
    }

    @Override
    public String navigate(String deviceSn, Q20NavigateDTO dto) {
        JSONObject data = new JSONObject();
        data.set("longitude", dto.getLongitude());
        data.set("latitude", dto.getLatitude());
        data.set("altitude", dto.getAltitude());
        data.set("speed", dto.getSpeed());
        data.set("action", dto.getAction());
        if (dto.getQrCode() != null) {
            data.set("qr_code", dto.getQrCode());
        }
        return execCmd(deviceSn, "navigate", data);
    }

    // ==================== 云台相机 ====================

    @Override
    public String gimbalControl(String deviceSn, Q20GimbalControlDTO dto) {
        JSONObject data = new JSONObject();
        data.set("device_id", dto.getDeviceId());
        data.set("mode", dto.getMode());
        data.set("roll", dto.getRoll());
        data.set("yaw", dto.getYaw());
        data.set("pitch", dto.getPitch());
        return execCmd(deviceSn, "gimbal_control", data);
    }

    @Override
    public String mountTda(String deviceSn, Q20MountTdaDTO dto) {
        JSONObject data = new JSONObject();
        data.set("payload_index", dto.getPayloadIndex());
        data.set("tda_length", dto.getTdaLength());
        data.set("tda", dto.getTda());
        return execCmd(deviceSn, "mount_tda", data);
    }

    @Override
    public String cameraPhotoTake(String deviceSn, Q20CameraDTO dto) {
        JSONObject data = buildCameraData(dto);
        return execCmd(deviceSn, "camera_photo_take", data);
    }


    @Override
    public String cameraRecordingStart(String deviceSn, Q20CameraDTO dto) {
        JSONObject data = buildCameraData(dto);
        return execCmd(deviceSn, "camera_recording_start", data);
    }

    @Override
    public String cameraRecordingStop(String deviceSn, Q20CameraDTO dto) {
        JSONObject data = buildCameraData(dto);
        return execCmd(deviceSn, "camera_recording_stop", data);
    }

    @Override
    public String cameraFocalLengthSet(String deviceSn, Q20CameraFocalLengthDTO dto) {
        JSONObject data = new JSONObject();
        data.set("payload_index", dto.getPayloadIndex());
        data.set("device_id", dto.getDeviceId());
        data.set("camera_type", dto.getCameraType());
        data.set("zoom_factor", dto.getZoomFactor());
        data.set("zoom_type", dto.getZoomType());
        data.set("zoom_mode", dto.getZoomMode());
        return execCmd(deviceSn, "camera_focal_length_set", data);
    }

    private JSONObject buildCameraData(Q20CameraDTO dto) {
        JSONObject data = new JSONObject();
        if (dto.getDeviceId() != null) {
            data.set("device_id", dto.getDeviceId());
        }
        data.set("payload_index", dto.getPayloadIndex());
        data.set("camera_type", dto.getCameraType());
        return data;
    }

    // ==================== 直播 ====================

    @Override
    public String liveStartPush(String deviceSn, Q20LiveStartDTO dto) {
        JSONObject data = new JSONObject();
        data.set("payload_index", dto.getPayloadIndex());
        data.set("url_type", dto.getUrlType());
        data.set("url", dto.getUrl());
        data.set("video", dto.getVideo());
        data.set("video_id", dto.getVideoId());
        data.set("video_type", dto.getVideoType());
        return execCmd(deviceSn, "live_start_push", data);
    }

    @Override
    public String liveStopPush(String deviceSn, int payloadIndex, int video) {
        JSONObject data = new JSONObject();
        data.set("payload_index", payloadIndex);
        data.set("video", video);
        return execCmd(deviceSn, "live_stop_push", data);
    }

    @Override
    public String imageSwitch(String deviceSn, Q20ImageSwitchDTO dto) {
        JSONObject data = new JSONObject();
        data.set("device_id", dto.getDeviceId());
        data.set("laser_enable", dto.getLaserEnable());
        data.set("visible_enable", dto.getVisibleEnable());
        data.set("ir_enable", dto.getIrEnable());
        data.set("ir_type", dto.getIrType());
        data.set("stream_type", dto.getStreamType());
        return execCmd(deviceSn, "image_switch", data);
    }

    // ==================== 设备控制 ====================

    @Override
    public String deviceCharge(String deviceSn, int value, int version) {
        JSONObject data = new JSONObject();
        data.set("value", value);
        data.set("version", version);
        return execCmd(deviceSn, "device_charge", data);
    }

    @Override
    public String deviceBoot(String deviceSn, int value) {
        JSONObject data = new JSONObject();
        data.set("value", value);
        return execCmd(deviceSn, "device_boot", data);
    }

    @Override
    public String safetySwitch(String deviceSn, int value) {
        JSONObject data = new JSONObject();
        data.set("value", value);
        return execCmd(deviceSn, "safety_switch", data);
    }

    // ==================== 负载 ====================

    @Override
    public String throwingLock(String deviceSn, Q20ThrowingDTO dto) {
        JSONObject data = new JSONObject();
        data.set("device_id", dto.getDeviceId());
        data.set("value", dto.getValue());
        return execCmd(deviceSn, "throwing_lock", data);
    }

    @Override
    public String throwingExecution(String deviceSn, long deviceId) {
        JSONObject data = new JSONObject();
        data.set("device_id", deviceId);
        return execCmd(deviceSn, "throwing_execution", data);
    }

    @Override
    public String halyarding(String deviceSn, Q20HalyardingDTO dto) {
        JSONObject data = new JSONObject();
        data.set("device_id", dto.getDeviceId());
        data.set("action", dto.getAction());
        data.set("rope_position", dto.getRopePosition());
        data.set("rope_status", dto.getRopeStatus());
        return execCmd(deviceSn, "halyarding", data);
    }

    @Override
    public String logistics(String deviceSn, int value, boolean force) {
        JSONObject data = new JSONObject();
        data.set("value", value);
        data.set("force", force);
        return execCmd(deviceSn, "logistics", data);
    }

    // ==================== 虚拟摇杆（高频，不等回复） ====================

    @Override
    public void drc(String deviceSn, Q20DrcDTO dto) {
        JSONObject data = new JSONObject();
        data.set("vx", dto.getVx());
        data.set("vy", dto.getVy());
        data.set("vz", dto.getVz());
        data.set("vyaw", dto.getVyaw());
        String topic = String.format(SERVICES_TOPIC, deviceSn);
        JSONObject payload = djiBaseService.getPayload("drc", data);
        payload.set("gateway", deviceSn);
        mqttPushService.pushMessageByClient1(topic, payload.toString());
    }

    // ==================== 安全/降落伞 ====================

    @Override
    public String setAutoParachute(String deviceSn, int value) {
        JSONObject data = new JSONObject();
        data.set("value", value);
        return execCmd(deviceSn, "set_auto_parachute", data);
    }

    @Override
    public JSONObject getEmergencyStopOtp(String deviceSn) {
        JSONObject data = new JSONObject();
        data.set("value", 0);
        return execCmdGetReply(deviceSn, "get_emergency_stop_otp", data);
    }

    @Override
    public String emergencyStop(String deviceSn, Q20EmergencyStopDTO dto) {
        JSONObject data = new JSONObject();
        data.set("otp", dto.getOtp());
        return execCmd(deviceSn, "emergency_stop", data);
    }

    @Override
    public JSONObject getParachuteOtp(String deviceSn) {
        JSONObject data = new JSONObject();
        data.set("value", 0);
        return execCmdGetReply(deviceSn, "get_parachute_otp", data);
    }

    @Override
    public String openParachute(String deviceSn, Q20OpenParachuteDTO dto) {
        JSONObject data = new JSONObject();
        data.set("otp", dto.getOtp());
        return execCmd(deviceSn, "open_parachute", data);
    }

    @Override
    public String confirmParachuteSafety(String deviceSn, int value) {
        JSONObject data = new JSONObject();
        data.set("value", value);
        return execCmd(deviceSn, "confirm_parachute_safety", data);
    }

    // ==================== 状态/信息 ====================

    @Override
    public JSONObject queryStatus(String deviceSn, Q20QueryStatusDTO dto) {
        JSONObject data = new JSONObject();
        data.set("query_value", dto.getQueryValue());
        if (dto.getBid() != null) {
            data.set("bid", dto.getBid());
        }
        if (dto.getType() != null) {
            data.set("type", dto.getType());
        }
        if (dto.getWayline() != null) {
            data.set("wayline", dto.getWayline());
        }
        if (dto.getCode() != null) {
            data.set("code", dto.getCode());
        }
        return execCmdGetReply(deviceSn, "query_status", data);
    }

    @Override
    public JSONObject getConfig(String deviceSn) {
        JSONObject data = new JSONObject();
        data.set("value", 1);
        return execCmdGetReply(deviceSn, "get_config", data);
    }

    @Override
    public String stereoImage(String deviceSn, int value) {
        JSONObject data = new JSONObject();
        data.set("value", value);
        return execCmd(deviceSn, "stereo_image", data);
    }

    @Override
    public JSONObject version(String deviceSn) {
        JSONObject data = new JSONObject();
        data.set("value", 0);
        return execCmdGetReply(deviceSn, "version", data);
    }

    // ==================== 日志 ====================

    @Override
    public JSONObject logCount(String deviceSn) {
        JSONObject data = new JSONObject();
        data.set("value", 0);
        return execCmdGetReply(deviceSn, "log_count", data);
    }

    @Override
    public JSONObject logList(String deviceSn, Q20LogListDTO dto) {
        JSONObject data = new JSONObject();
        data.set("start", dto.getStart());
        data.set("end", dto.getEnd());
        return execCmdGetReply(deviceSn, "log_list", data);
    }

    @Override
    public String logData(String deviceSn, Q20LogDataDTO dto) {
        JSONObject data = new JSONObject();
        data.set("id", dto.getId());
        data.set("url", dto.getUrl());
        return execCmd(deviceSn, "log_data", data);
    }

    // ==================== OTA ====================

    @Override
    public String otaUpgrade(String deviceSn, Q20OtaUpgradeDTO dto) {
        JSONObject data = new JSONObject();
        data.set("sn", dto.getSn());
        data.set("model", dto.getModel());
        data.set("url", dto.getUrl());
        data.set("md5", dto.getMd5());
        data.set("package_name", dto.getPackageName());
        data.set("version", dto.getVersion());
        data.set("amend", dto.getAmend());
        return execCmd(deviceSn, "ota_upgrade", data);
    }
}
