#include "mqtt_controller.hpp"
#include <iostream>
#include <utility>
#include "mylog.hpp"

// 构造函数：初始化客户端和回调处理器
MqttController::MqttController(const std::string& broker_address, const std::string& client_id)
    : client_(new mqtt::async_client(broker_address, client_id)),
      callback_handler_(*this),
      is_connected_(false)
{
    // 将回调处理器与客户端关联起来
    client_->set_callback(callback_handler_);
}

// 析构函数：确保断开连接
MqttController::~MqttController() {
    disconnect();
}

// 连接到代理
bool MqttController::connect(const std::string& username, const std::string& password, bool automatic_reconnect) {
    if (isConnected()) {
        return true;
    }
    
    mqtt::connect_options conn_opts;
    conn_opts.set_keep_alive_interval(60);
    conn_opts.set_clean_session(true);
    conn_opts.set_automatic_reconnect(automatic_reconnect); // 设置自动重连

    if (!username.empty()) {
        conn_opts.set_user_name(username);
        conn_opts.set_password(password);
    }

    try {
        mylog_info("正在连接到 MQTT 代理...");
        // connect是异步的，它会立即返回。连接过程在后台进行。
        client_->connect(conn_opts)->wait(); // 使用 wait() 使其变为同步调用，简化示例
    } catch (const mqtt::exception& exc) {
        mylog_error("错误：连接时发生异常 - {}",exc.what());
        is_connected_ = false; // 确保状态正确
        return false;
    }
    return true;
}

// 断开连接
void MqttController::disconnect() {
    if (isConnected()) {
        try {
            mylog_info("正在断开与 MQTT 代理的连接...");
            // disconnect是异步的，我们等待它完成
            client_->disconnect()->wait();
            mylog_info("已断开连接。" );
        } catch (const mqtt::exception& exc) {
            mylog_error("错误：断开连接时发生异常 - " ,exc.what());
        }
    }
    is_connected_ = false; // 确保状态被更新
}

bool MqttController::isConnected() const {
    return is_connected_;
}

void MqttController::setOnConnectSuccessCallback(ConnectionSuccessCallback cb) {
    on_connect_success_cb_ = std::move(cb);
}

void MqttController::setOnConnectionLostCallback(ConnectionLostCallback cb) {
    on_connection_lost_cb_ = std::move(cb);
}

// 订阅主题，并为这个主题的后续消息设置回调
void MqttController::subscribe(const std::string& topic, int qos, MessageCallback callback) {
    if (!isConnected()) {
        mylog_error("错误：未连接，无法订阅主题 {}",topic );
        return;
    }

    std::lock_guard<std::mutex> lock(callbacks_mutex_);
    topic_callbacks_[topic] = std::move(callback);
    
    try {
        mylog_info("正在订阅主题: ") ;
        client_->subscribe(topic, qos);
    } catch (const mqtt::exception& exc) {
        mylog_error("订阅错误: {}" , exc.what()); 
        // 如果订阅失败，移除回调以避免混淆
        topic_callbacks_.erase(topic);
    }
}

void MqttController::subscribe(const std::vector<std::string>& topics, int qos, MessageCallback callback) {
    if (!isConnected()) {
        mylog_error("未连接，无法订阅多个主题" );
        return;
    }

    std::lock_guard<std::mutex> lock(callbacks_mutex_);
    for (const auto& topic : topics) {
        topic_callbacks_[topic] = callback; // 使用相同的回调
    }

    // Paho V1.2.0及以上版本支持批量订阅
    auto topic_collection = std::make_shared<mqtt::string_collection>();
    for (const auto& topic : topics) {
        topic_collection->push_back(topic);
    }
    std::vector<int> qos_levels(topics.size(), qos);

    try {
        mylog_info("正在批量订阅主题...");
        client_->subscribe(topic_collection, qos_levels);
    } catch (const mqtt::exception& exc) {
        mylog_error("批量订阅错误: {}",exc.what()) ;
        // 如果失败，移除所有刚刚添加的回调
        for (const auto& topic : topics) {
            topic_callbacks_.erase(topic);
        }
    }
}

void MqttController::unsubscribe(const std::string& topic) {
    if (!isConnected()) {
        mylog_error( "错误：未连接，无法取消订阅主题 {} ",topic);
        return;
    }
    
    std::lock_guard<std::mutex> lock(callbacks_mutex_);
    topic_callbacks_.erase(topic);
    
    try {
        std::cout << "正在取消订阅主题: " << topic << std::endl;
        client_->unsubscribe(topic);
    } catch (const mqtt::exception& exc) {
        std::cerr << "取消订阅错误: " << exc.what() << std::endl;
    }
}

// 发布消息
void MqttController::publish(const std::string& topic, const std::string& payload, int qos, bool retained) {
    if (!isConnected()) {
        std::cerr << "错误：未连接，无法发布消息到主题 \"" << topic << "\"" << std::endl;
        return;
    }
    
    try {
        auto msg = mqtt::make_message(topic, payload);
        msg->set_qos(qos);
        msg->set_retained(retained);
        client_->publish(msg);
    } catch (const mqtt::exception& exc) {
        std::cerr << "错误：发布消息时发生异常 - " << exc.what() << std::endl;
    }
}

// --- 内部回调处理类的实现 ---

void MqttController::CallbackHandler::connected(const std::string& /*cause*/) {
    std::cout << "连接成功！" << std::endl;
    controller_.is_connected_ = true;
    if (controller_.on_connect_success_cb_) {
        controller_.on_connect_success_cb_();
    }
}

void MqttController::CallbackHandler::connection_lost(const std::string& cause) {
    std::cerr << "错误：连接已丢失。原因: " << cause << std::endl;
    controller_.is_connected_ = false;
    if (controller_.on_connection_lost_cb_) {
        controller_.on_connection_lost_cb_(cause);
    }
}

void MqttController::CallbackHandler::message_arrived(mqtt::const_message_ptr msg) {
    std::lock_guard<std::mutex> lock(controller_.callbacks_mutex_);
    const std::string received_topic = msg->get_topic();
    const std::string payload = msg->to_string();
    bool matched = false;

    // 遍历所有注册的回调，查找匹配的订阅（支持通配符）
    for (const auto& pair : controller_.topic_callbacks_) {
        const std::string& subscribed_topic = pair.first;
        if (topic_matches_sub(subscribed_topic, received_topic)) {
            if (pair.second) {
                pair.second(received_topic, payload);
                matched = true;
            }
        }
    }
    
    if (!matched) {
        std::cout << "收到消息，但未匹配任何已注册的回调: " << received_topic << std::endl;
    }
}

// --- 静态通配符匹配函数 ---
bool MqttController::topic_matches_sub(const std::string& sub, const std::string& topic) {
    auto sub_it = sub.begin();
    auto topic_it = topic.begin();

    while (sub_it != sub.end() && topic_it != topic.end()) {
        if (*sub_it == *topic_it) {
            sub_it++;
            topic_it++;
        } else if (*sub_it == '+') {
            // '+' 匹配一个层级
            sub_it++;
            while (topic_it != topic.end() && *topic_it != '/') {
                topic_it++;
            }
        } else if (*sub_it == '#') {
            // '#' 必须是订阅的最后一个字符，匹配所有剩余层级
            return sub_it + 1 == sub.end();
        } else {
            return false;
        }
    }

    // 如果订阅以 "/#" 结尾，它可以匹配没有后续层级的主题
    if (topic_it == topic.end() && sub_it != sub.end()) {
        if (*sub_it == '/' && (sub_it + 1) != sub.end() && *(sub_it + 1) == '#') {
            return (sub_it + 2) == sub.end();
        }
    }

    return sub_it == sub.end() && topic_it == topic.end();
}