#include "mqtt_handler.h"
#include "config.h" // 确保config.h被包含以获取定义
#include <WiFi.h>

// ----------- 全局MQTT相关变量 -----------
WiFiClient espClient;
PubSubClient mqttClient(espClient);
CommandCallback global_command_callback = nullptr;

// 主题字符串
String topic_uplink_to_backend;
String topic_downlink_from_backend;

// 将RobotStatus枚举转换为字符串 (与后端DTO的actualRobotStatus对应)
const char* robotStatusToString(RobotStatus status) {
    switch (status) {
        case IDLE: return "IDLE";
        case MOVING: return "MOVING";
        case CHARGING: return "CHARGING";
        case COMPLETED: return "COMPLETED";
        case FAULTED: return "FAULTED"; // 或 "ERROR"
        default: return "UNKNOWN";
    }
}

void callback(char* topic, byte* payload, unsigned int length) {
    Serial.print("消息抵达, 主题: ");
    Serial.println(topic);

    char message[length + 1];
    memcpy(message, payload, length);
    message[length] = '\0';
    Serial.print("消息内容: ");
    Serial.println(message);

    if (String(topic) != topic_downlink_from_backend) {
        Serial.println("消息非来自预期的指令主题，忽略。");
        return;
    }

    StaticJsonDocument<256> doc;
    DeserializationError error = deserializeJson(doc, message);

    if (error) {
        Serial.print("JSON 解析失败: ");
        Serial.println(error.f_str());
        // 可以在这里发送一个格式错误的ACK，但通常不建议对无法解析的taskId发ACK
        return;
    }

    const char* cmdType = nullptr;
    if (doc.containsKey("commandType")) {
        cmdType = doc["commandType"];
    } else if (doc.containsKey("command")) {
        cmdType = doc["command"];
    }
    const char* taskId = doc["taskId"];

    if (cmdType == nullptr || taskId == nullptr) {
        Serial.println("指令JSON缺少 commandType/command 或 taskId 字段。");
        // 尝试发送ACK，即使taskId可能为null，但通常最好有taskId
        mqtt_publish_ack(taskId, false, "Command JSON invalid (missing commandType/command or taskId)", IDLE /*随便给个状态*/, nullptr);
        return;
    }

    const char* targetSpot = nullptr;
    if (doc.containsKey("spotId")) {
        targetSpot = doc["spotId"].as<const char*>();
    } else if (doc.containsKey("target_spot_uid")) {
        targetSpot = doc["target_spot_uid"].as<const char*>();
    }

    Serial.printf("解析到指令: Type=%s, TaskID=%s, TargetSpot=%s\n", cmdType, taskId, targetSpot ? targetSpot : "N/A");

    if (global_command_callback) {
        global_command_callback(cmdType, taskId, targetSpot);
    } else {
        Serial.println("错误: 指令回调函数未设置!");
    }
}

void connect_wifi() {
    Serial.println("正在连接 Wi-Fi...");
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("\nWi-Fi 连接成功!");
    Serial.print("IP 地址: ");
    Serial.println(WiFi.localIP());
}

void reconnect_mqtt() {
    while (!mqttClient.connected()) {
        Serial.print("尝试连接 MQTT Broker: ");
        Serial.println(MQTT_BROKER_HOST);
        String clientId = "esp32-robot-" + String(DEVICE_UID) + "-" + String(random(0xffff), HEX);
        Serial.printf("客户端 ID: %s \n", clientId.c_str());

        if (mqttClient.connect(clientId.c_str(), MQTT_USERNAME, MQTT_PASSWORD)) {
            Serial.println("MQTT Broker 连接成功!");
            mqttClient.subscribe(topic_downlink_from_backend.c_str());
            Serial.println("已订阅指令主题: " + topic_downlink_from_backend);
            // 连接成功后可以发送一次初始状态，但这通常由主逻辑决定
        } else {
            Serial.print("连接失败, rc=");
            Serial.print(mqttClient.state());
            Serial.println(" 2秒后重试...");
            delay(2000);
        }
    }
}

// ----------- Public Functions -----------
void mqtt_setup(CommandCallback cmd_callback) {
    global_command_callback = cmd_callback;

    // 构建主题字符串
    String base_topic_path = MQTT_TOPIC_BASE;
    topic_uplink_to_backend = base_topic_path + "/status/" + String(DEVICE_UID);
    topic_downlink_from_backend = base_topic_path + "/command/" + String(DEVICE_UID);

    Serial.println("MQTT 主题初始化完成:");
    Serial.println("  上行主题: " + topic_uplink_to_backend);
    Serial.println("  下行主题: " + topic_downlink_from_backend);

    connect_wifi();
    mqttClient.setServer(MQTT_BROKER_HOST, MQTT_BROKER_PORT);
    mqttClient.setCallback(callback);
}

void mqtt_loop() {
    if (!mqttClient.connected()) {
        reconnect_mqtt();
    }
    mqttClient.loop();
}

void mqtt_publish_status_update(
    RobotStatus current_status, 
    const char* location, 
    int battery_level, 
    const char* current_task_id, // 这个字段在我们的状态消息中通常不直接用，但保留参数以备将来
    const char* target_spot, 
    const char* current_spot, 
    unsigned long charge_duration_seconds,
    int error_code,       
    const char* error_message 
) {
    StaticJsonDocument<512> doc;
    doc["robotUid"] = DEVICE_UID;
    doc["actualRobotStatus"] = robotStatusToString(current_status);

    if (location) doc["location"] = location;
    doc["battery"] = battery_level;

    // 根据状态添加特定字段
    switch (current_status) {
        case MOVING:
            if (target_spot) doc["targetSpot"] = target_spot;
            break;
        case CHARGING:
            if (current_spot) doc["spotId"] = current_spot;
            doc["durationSeconds"] = charge_duration_seconds;
            break;
        case COMPLETED:
            if (current_spot) doc["spotId"] = current_spot;
            // totalDurationSeconds 通常在特定完成事件的ACK中上报更准确
            break;
        case FAULTED:
            doc["errorCode"] = error_code; // 仅在FAULTED状态下发送错误码
            if (error_message) doc["message"] = error_message;
            break;
        default:
            break;
    }
    // 注意：移除了常规状态更新中的errorCode，除非状态是FAULTED

    String jsonBuffer;
    serializeJson(doc, jsonBuffer);
    Serial.print("发送 StatusUpdate 到主题 [");
    Serial.print(topic_uplink_to_backend);
    Serial.print("]: ");
    Serial.println(jsonBuffer);

    if (mqttClient.publish(topic_uplink_to_backend.c_str(), jsonBuffer.c_str())) {
        Serial.println("StatusUpdate 发送成功");
    } else {
        Serial.println("StatusUpdate 发送失败");
    }
}

void mqtt_publish_ack(
    const char* task_id, 
    bool success, 
    const char* message, 
    RobotStatus current_robot_status_at_ack, 
    const char* ack_context_spot_id,
    const char* command_ack_chinese_value
) {
    if (!task_id) {
        Serial.println("无法发送ACK: taskId 为空");
        return;
    }
    if (!command_ack_chinese_value) {
        Serial.println("无法发送ACK: command_ack_chinese_value 为空");
        // 或者根据实际情况决定是否发送一个不带 command_ack 的ACK，但后端可能不认
        return;
    }

    StaticJsonDocument<384> doc; // 适当调整JSON文档大小
    doc["robotUid"] = DEVICE_UID;
    
    // 关键修改：符合后端期望的ACK格式
    doc["command_ack"] = command_ack_chinese_value; // 使用传入的中文描述
    doc["task_id"] = atol(task_id); // 将 task_id (字符串) 转换为 long (数字类型)
                                     // 注意：如果 task_id 本身就应该是数字类型传来，则更好
                                     // 但当前task_id通常作为字符串处理，这里做转换
                                     // 后端期望 task_id 是数字
    doc["success"] = success; // 布尔类型

    if (message) doc["message"] = message;
    doc["actualRobotStatus"] = robotStatusToString(current_robot_status_at_ack);
    if (ack_context_spot_id) {
        doc["spotId"] = ack_context_spot_id; 
    }

    String jsonBuffer;
    serializeJson(doc, jsonBuffer);
    Serial.print("发送 ACK/TaskUpdate 到主题 [");
    Serial.print(topic_uplink_to_backend);
    Serial.print("]: ");
    Serial.println(jsonBuffer);

    if (mqttClient.publish(topic_uplink_to_backend.c_str(), jsonBuffer.c_str())) {
        Serial.println("ACK/TaskUpdate 发送成功");
    } else {
        Serial.println("ACK/TaskUpdate 发送失败");
    }
}

// 这个函数可以移除或重新设计，因为状态现在由主逻辑管理并通过参数传递给 publish 函数
// RobotStatus mqtt_get_current_robot_status_commanded() { 
//     return IDLE; // Placeholder
// } 