#if CLIENT50_CMD_DEMO_STM32==1
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "lcd.h"
#include "beep.h"
#include "usmart.h"
#include "sram.h"
#include "lan8720.h"
#include "timer.h"
#include "rtc.h"
#include "adc.h"
#include "malloc.h"
#include "lwip/netif.h"
#include "lwip_comm.h"
#include "lwipopts.h"
#include "netif/etharp.h"
#include "lwip/ip_addr.h"   // 🔥 修复 IP_ADDR4 未定义
#include "lwip/dns.h"      // 🔥 修复 DNS API
#include <string.h>
#include "platform_adapter.h"

// ==========================
// LWIP 安全调度宏（全局统一调用）
// ==========================
#define LWIP_SAFE_POLL()    lwip_periodic_handle()

// ==========================
// 重定向标准库 malloc/free
// ==========================
#include <stdlib.h>
void* malloc(size_t size)
{
    return mymalloc(SRAMIN, size);
}

void free(void* p)
{
    if (p == NULL) return;
    myfree(SRAMIN, p);
}

// ==========================
// 安全读取【真实生效IP】
// ==========================
void get_lwip_real_ip(u8 *ip)
{
    if(netif_default == NULL) {
        ip[0]=ip[1]=ip[2]=ip[3]=0;
        return;
    }
    ip[0] = ip4_addr1(&netif_default->ip_addr);
    ip[1] = ip4_addr2(&netif_default->ip_addr);
    ip[2] = ip4_addr3(&netif_default->ip_addr);
    ip[3] = ip4_addr4(&netif_default->ip_addr);
}

void get_lwip_real_gw(u8 *gw)
{
    if(netif_default == NULL) {
        gw[0]=gw[1]=gw[2]=gw[3]=0;
        return;
    }
    gw[0] = ip4_addr1(&netif_default->gw);
    gw[1] = ip4_addr2(&netif_default->gw);
    gw[2] = ip4_addr3(&netif_default->gw);
    gw[3] = ip4_addr4(&netif_default->gw);
}

// ==========================
// 判断 LwIP 网络是否真正就绪
// ==========================
uint8_t lwip_net_is_ready(void)
{
    if(netif_default == NULL) return 0;
    if(!netif_is_up(netif_default)) return 0;
    if(netif_default->ip_addr.addr == 0) return 0;
    return 1;
}

// ==========================
// 以下：【完全不修改】你的 MQTT5.0 测试代码
// ==========================
#define FALSE 0
#define TRUE  1
#define MQTT_SDK_MAX_TOPIC_LEN    128
#define MQTT50_TEST_DEMO          1
#define MQTT_ENABLE_50            1
#define MQTT50_TEST_PERF_DUR      10000
#define MQTT50_TEST_STABLE_DUR    60000
#define MQTT50_TEST_MAX_PKT_SIZE  1028
#define MQTT50_TEST_RECONN_TIMES  5
#define TEST_CASE_TOTAL           8

#include "type.h"
#include "platform.h"
#include "agent_log.h"
#include "mqtt_client_sdk.h"
#include <stdio.h>
#include <string.h>

/************************** 【TOP宏定义配置区 - 适配SDK】 **************************/
#define TEST_CLIENT_ID        "mqtt50_biz_test_001"
#define TEST_BROKER_IP        "118.89.121.166"
#define TEST_BROKER_PORT      1883
#define TEST_KEEP_ALIVE_TIME  15
#define TEST_RECONNECT_INTER  3
#define TEST_MAX_RECONNECT    0
#define TEST_SHARE_GROUP      "biz_test_group"

/************************** 全局变量 - 回调校验核心（适配SDK v3.1.0） **************************/
MqttSdkClient        g_mqtt_client      = NULL;
MqttSdkClientCfg     g_mqtt_cfg         = {0};
MqttSdkConnState     g_last_conn_state  = MQTT_SDK_STATE_DISCONNECTED;
uint32_xxl            g_cur_test_case   = 0;

typedef struct {
    char send_topic[MQTT_SDK_MAX_TOPIC_LEN];
    uint8_xxl send_payload[MQTT50_TEST_MAX_PKT_SIZE];
    uint32_xxl send_payload_len;
    uint32_xxl send_msg_expiry;
    char send_share_group[64];
    MqttSdkQos send_qos;
    bool8_xxl send_retain;
    uint32_xxl send_tick;
} Mqtt50SendData;
Mqtt50SendData       g_send_data        = {0};

typedef struct {
    bool8_xxl recv_flag;
    char recv_topic[MQTT_SDK_MAX_TOPIC_LEN];
    uint8_xxl recv_payload[MQTT50_TEST_MAX_PKT_SIZE];
    uint32_xxl recv_payload_len;
    uint32_xxl recv_msg_expiry;
    char recv_share_group[64];
    MqttSdkQos recv_qos;
    bool8_xxl recv_retain;
    uint32_xxl recv_tick;
    int recv_err_code;
} Mqtt50RecvData;
Mqtt50RecvData       g_recv_data        = {0};

typedef struct {
    bool8_xxl resp_flag;
    MqttSdkBrokerRespType resp_type;
    MqttSdkErrCode resp_err_code;
    uint16_xxl resp_pkt_id;
    uint32_xxl resp_tick;
} Mqtt50BrokerResp;
Mqtt50BrokerResp     g_broker_resp      = {0};

typedef struct {
    MqttSdkConnState conn_state;
    uint32_xxl connect_tick;
    uint32_xxl disconnect_tick;
    uint32_xxl reconn_cost_ms;
    uint32_xxl total_conn_cnt;
    uint32_xxl total_disconn_cnt;
    uint32_xxl total_reconn_cnt;
} Mqtt50ConnState;
Mqtt50ConnState      g_conn_state       = {MQTT_SDK_STATE_DISCONNECTED};

typedef struct {
    int case_id;
    char case_name[64];
    int result;
    int callback_check_result;
    uint32_xxl cost_ms;
    float perf_qps;
    char err_info[128];
} Mqtt50TestResult;
Mqtt50TestResult     g_test_result[TEST_CASE_TOTAL] = {0};

uint32_xxl            g_pub_send_cnt     = 0;
uint32_xxl            g_pub_recv_cnt     = 0;
uint32_xxl            g_test_start_tick  = 0;

/************************** 核心回调函数（完全保留） **************************/
void mqtt_test_msg_callback(const MqttSdkMsg* msg)
{
    if (NULL == msg || NULL == msg->topic || strlen(msg->topic) == 0)
    {
        agent_log_debug("Msg callback: filter empty topic, non-PUBLISH packet skipped");
        return;
    }
    memset(&g_recv_data, 0, sizeof(Mqtt50RecvData));
    g_recv_data.recv_flag = TRUE;
    g_recv_data.recv_tick = platform_get_tick_ms();
    g_recv_data.recv_err_code = 0;

    if (msg->topic != NULL) strncpy(g_recv_data.recv_topic, msg->topic, MQTT_SDK_MAX_TOPIC_LEN-1);
    if (msg->payload != NULL && msg->payload_len > 0)
    {
        memcpy(g_recv_data.recv_payload, msg->payload, msg->payload_len);
        g_recv_data.recv_payload_len = msg->payload_len;
    }
    g_recv_data.recv_qos = msg->qos;
    g_recv_data.recv_retain = msg->retain;
    g_recv_data.recv_msg_expiry = msg->msg_expiry;

    char* share_prefix = "$share/";
    if (strstr(msg->topic, share_prefix) != NULL)
    {
        sscanf(msg->topic, "$share/%[^/]/", g_recv_data.recv_share_group);
        agent_log_info("Share group parsed with prefix");
    }
    else if (strlen(g_send_data.send_share_group) > 0)
    {
        strcpy(g_recv_data.recv_share_group, g_send_data.send_share_group);
        agent_log_info("Share group reused from send config");
    }

    if (strlen(g_send_data.send_topic) > 0)
    {
        char expect_topic[MQTT_SDK_MAX_TOPIC_LEN] = {0};
        if (strlen(g_send_data.send_share_group) > 0)
        {
            strcpy(expect_topic, g_send_data.send_topic);
        }
        else
        {
            strcpy(expect_topic, g_send_data.send_topic);
        }

        if (strcmp(g_recv_data.recv_topic, expect_topic) != 0)
        {
            agent_log_error("Topic mismatch");
            g_recv_data.recv_err_code = 1;
        }
        else if (g_recv_data.recv_payload_len != g_send_data.send_payload_len)
        {
            agent_log_error("Payload length mismatch");
            g_recv_data.recv_err_code = 1;
        }
        else if (memcmp(g_recv_data.recv_payload, g_send_data.send_payload, g_send_data.send_payload_len) != 0)
        {
            agent_log_error("Payload content mismatch");
            g_recv_data.recv_err_code = 1;
        }
        else if (g_recv_data.recv_qos != g_send_data.send_qos)
        {
            agent_log_error("QoS level mismatch");
            g_recv_data.recv_err_code = 1;
        }
        else if (g_recv_data.recv_msg_expiry != g_send_data.send_msg_expiry)
        {
            agent_log_warn("Message expiry not transparently transmitted");
        }
        else if (strlen(g_send_data.send_share_group) > 0 && 
                 strcmp(g_recv_data.recv_share_group, g_send_data.send_share_group) != 0)
        {
            agent_log_error("Share group mismatch");
            g_recv_data.recv_err_code = 1;
        }
    }
    g_pub_recv_cnt++;
    if (g_recv_data.recv_err_code == 0)
    {
        agent_log_info("Message check passed");
    }
    else
    {
        agent_log_error("Message check failed, err:%d", g_recv_data.recv_err_code);
    }
}

void mqtt_test_broker_resp_callback(const MqttSdkBrokerRespStatus* resp)
{
    if (NULL == resp)
    {
        agent_log_error("Broker resp null");
        return;
    }
    memset(&g_broker_resp, 0, sizeof(Mqtt50BrokerResp));
    g_broker_resp.resp_flag = TRUE;
    g_broker_resp.resp_type = resp->resp_type;
    g_broker_resp.resp_err_code = resp->err_code;
    g_broker_resp.resp_pkt_id = resp->pkt_id;
    g_broker_resp.resp_tick = platform_get_tick_ms();

    if (resp->resp_type == MQTT_SDK_BROKER_RESP_CONNACK)
    {
        if (resp->err_code == MQTT_SDK_OK && resp->client_connected)
        {
            g_conn_state.conn_state = MQTT_SDK_STATE_CONNECTED;
            g_conn_state.connect_tick = g_broker_resp.resp_tick;
            g_conn_state.total_conn_cnt++;
            agent_log_info("CONNACK success");
        }
        else
        {
            g_conn_state.conn_state = MQTT_SDK_STATE_DISCONNECTED;
            agent_log_error("CONNACK failed, err:%d", resp->err_code);
        }
    }
    else if (resp->resp_type == MQTT_SDK_BROKER_RESP_DISCONNECT)
    {
        g_conn_state.conn_state = MQTT_SDK_STATE_DISCONNECTED;
        g_conn_state.disconnect_tick = g_broker_resp.resp_tick;
        g_conn_state.total_disconn_cnt++;
        agent_log_warn("Disconnected from broker");
    }
    else if (resp->resp_type == MQTT_SDK_BROKER_RESP_SUBACK)
    {
        if (resp->err_code == MQTT_SDK_OK)
        {
            agent_log_info("SUBACK success, pktid:%d", resp->pkt_id);
        }
        else
        {
            agent_log_error("SUBACK failed, err:%d", resp->err_code);
        }
    }
    else if (resp->resp_type == MQTT_SDK_BROKER_RESP_UNSUBACK)
    {
        agent_log_info("UNSUBACK success, pktid:%d", resp->pkt_id);
    }
    else if (resp->resp_type == MQTT_SDK_BROKER_RESP_PUBACK)
    {
        agent_log_debug("PUBACK success, pktid:%d", resp->pkt_id);
    }
}

static void mqtt50_test_case_init(int case_id, const char* case_name)
{
    memset(&g_send_data, 0, sizeof(Mqtt50SendData));
    memset(&g_recv_data, 0, sizeof(Mqtt50RecvData));
    memset(&g_broker_resp, 0, sizeof(Mqtt50BrokerResp));
    
    g_pub_send_cnt = 0;
    g_pub_recv_cnt = 0;
    g_test_start_tick = platform_get_tick_ms();

    g_test_result[case_id].case_id = case_id;
    strncpy(g_test_result[case_id].case_name, case_name, sizeof(g_test_result[case_id].case_name)-1);
    g_test_result[case_id].result = 0;
    g_test_result[case_id].callback_check_result = 0;
    g_test_result[case_id].cost_ms = 0;
    g_test_result[case_id].perf_qps = 0.0f;
    memset(g_test_result[case_id].err_info, 0, sizeof(g_test_result[case_id].err_info));

    LWIP_SAFE_POLL(); // <-- 加固

    agent_log_info("==================================");
    agent_log_info("Start test case: %s", case_name);
    agent_log_info("==================================");
}

static int mqtt50_test_wait_callback(uint32_xxl timeout_ms)
{
    uint32_xxl start_tick = platform_get_tick_ms();
    while ((platform_get_tick_ms() - start_tick) < timeout_ms)
    {
        LWIP_SAFE_POLL(); // <-- 加固
        xxl_mqtt_sdk_client_loop(g_mqtt_client);
        platform_delay_ms(10);

        if (g_recv_data.recv_flag == TRUE)
        {
            return g_recv_data.recv_err_code;
        }
        if (g_broker_resp.resp_flag == TRUE)
        {
            return (g_broker_resp.resp_err_code == MQTT_SDK_OK) ? 0 : 1;
        }
    }
    agent_log_error("Wait callback timeout");
    return 2;
}

static void mqtt50_test_pause(void)
{
    agent_log_info("Test case paused due to failure");
    LWIP_SAFE_POLL(); // <-- 加固
}

static float mqtt50_test_calc_qps(uint32_xxl test_dur_ms)
{
    if (test_dur_ms == 0 || g_pub_recv_cnt == 0) return 0.0f;
    return (float)g_pub_recv_cnt / ((float)test_dur_ms / 1000.0f);
}

static int mqtt50_test_case_001_conn(void)
{
    mqtt50_test_case_init(0, "5.0 base connect");
    int ret = 0;
    uint32_xxl timeout_ms = 5000;

    LWIP_SAFE_POLL(); // <-- 加固

    if (g_mqtt_client == NULL)
    {
        agent_log_error("Client handle null");
        g_test_result[0].result = -1;
        strcpy(g_test_result[0].err_info, "client create failed");
        mqtt50_test_pause();
        return -1;
    }

    ret = mqtt50_test_wait_callback(timeout_ms);
    g_test_result[0].callback_check_result = ret;
    g_test_result[0].cost_ms = platform_get_tick_ms() - g_test_start_tick;

    MqttSdkConnState sdk_state = xxl_mqtt_sdk_client_get_conn_state(g_mqtt_client);
    if (sdk_state != MQTT_SDK_STATE_CONNECTED || ret != 0)
    {
        agent_log_error("Connect failed, state:%d ret:%d", sdk_state, ret);
        g_test_result[0].result = -2;
        snprintf(g_test_result[0].err_info, sizeof(g_test_result[0].err_info)-1,
                 "connect fail state:%d", sdk_state);
        mqtt50_test_pause();
        return -2;
    }
    else
    {
        agent_log_info("Connect success");
        g_test_result[0].result = 0;
    }

    LWIP_SAFE_POLL(); // <-- 加固
    agent_log_info("Case 001 finished");
    return g_test_result[0].result;
}

static int mqtt50_test_case_002_pubsub(void)
{
    mqtt50_test_case_init(1, "5.0 pub sub test");
    int ret = 0;
    char test_topic[] = "mqtt50/biz/test/002";
    char test_payload[] = "SDK v3.1.0 5.0 test";
    uint32_xxl payload_len = strlen(test_payload);

    LWIP_SAFE_POLL(); // <-- 加固

    if (xxl_mqtt_sdk_client_get_conn_state(g_mqtt_client) != MQTT_SDK_STATE_CONNECTED)
    {
        agent_log_error("Not connected");
        g_test_result[1].result = -1;
        strcpy(g_test_result[1].err_info, "disconnected");
        mqtt50_test_pause();
        return -1;
    }

    ret = xxl_mqtt_sdk_client_subscribe(g_mqtt_client, test_topic, MQTT_SDK_QOS1, NULL);
    LWIP_SAFE_POLL(); // <-- 加固
    if (ret != MQTT_SDK_OK)
    {
        agent_log_error("Subscribe fail ret:%d", ret);
        g_test_result[1].result = ret;
        strcpy(g_test_result[1].err_info, "subscribe failed");
        mqtt50_test_pause();
        return ret;
    }
    ret = mqtt50_test_wait_callback(2000);
    if (ret != 0)
    {
        agent_log_error("Suback wait fail");
        g_test_result[1].result = -2;
        strcpy(g_test_result[1].err_info, "suback timeout");
        mqtt50_test_pause();
        return -2;
    }

    strcpy(g_send_data.send_topic, test_topic);
    memcpy(g_send_data.send_payload, test_payload, payload_len);
    g_send_data.send_payload_len = payload_len;
    g_send_data.send_qos = MQTT_SDK_QOS1;
    g_send_data.send_msg_expiry = 60;
    g_send_data.send_tick = platform_get_tick_ms();

    MqttSdkMsg msg = {0};
    msg.topic = test_topic;
    msg.payload = (uint8_xxl*)test_payload;
    msg.payload_len = payload_len;
    msg.qos = MQTT_SDK_QOS1;
    msg.msg_expiry = g_send_data.send_msg_expiry;

    ret = xxl_mqtt_sdk_client_publish(g_mqtt_client, &msg);
    LWIP_SAFE_POLL(); // <-- 加固
    if (ret != MQTT_SDK_OK)
    {
        agent_log_error("Publish fail ret:%d", ret);
        g_test_result[1].result = ret;
        strcpy(g_test_result[1].err_info, "publish failed");
        mqtt50_test_pause();
        return ret;
    }
    g_pub_send_cnt++;

    ret = mqtt50_test_wait_callback(3000);
    g_test_result[1].callback_check_result = ret;
    g_test_result[1].cost_ms = platform_get_tick_ms() - g_test_start_tick;

    if (ret == 0)
    {
        agent_log_info("Pub sub test success");
        g_test_result[1].result = 0;
    }
    else
    {
        agent_log_error("Pub sub callback fail");
        g_test_result[1].result = -3;
        snprintf(g_test_result[1].err_info, sizeof(g_test_result[1].err_info)-1,
                 "callback check fail");
        mqtt50_test_pause();
    }
    xxl_mqtt_sdk_client_unsubscribe(g_mqtt_client, test_topic, NULL);
    LWIP_SAFE_POLL(); // <-- 加固

    agent_log_info("Case 002 finished");
    return g_test_result[1].result;
}

static int mqtt50_test_case_003_shared_sub(void)
{
    mqtt50_test_case_init(2, "5.0 shared subscribe");
    int ret = 0;
    char raw_topic[] = "mqtt50/biz/test/003";
    char share_group[] = TEST_SHARE_GROUP;

    LWIP_SAFE_POLL(); // <-- 加固

    if (xxl_mqtt_sdk_client_get_conn_state(g_mqtt_client) != MQTT_SDK_STATE_CONNECTED)
    {
        agent_log_error("Not connected");
        g_test_result[2].result = -1;
        strcpy(g_test_result[2].err_info, "disconnected");
        mqtt50_test_pause();
        return -1;
    }

    g_mqtt_cfg.v50_share_group = share_group;
    agent_log_info("Share group:%s", share_group);

    ret = xxl_mqtt_sdk_client_subscribe(g_mqtt_client, raw_topic, MQTT_SDK_QOS1, share_group);
    LWIP_SAFE_POLL(); // <-- 加固
    if (ret != MQTT_SDK_OK)
    {
        agent_log_error("Shared sub fail ret:%d", ret);
        g_test_result[2].result = ret;
        strcpy(g_test_result[2].err_info, "shared sub failed");
        mqtt50_test_pause();
        return ret;
    }
    ret = mqtt50_test_wait_callback(2000);
    if (ret != 0)
    {
        agent_log_error("Shared sub ack fail");
        g_test_result[2].result = -2;
        strcpy(g_test_result[2].err_info, "suback timeout");
        mqtt50_test_pause();
        return -2;
    }

    strcpy(g_send_data.send_topic, raw_topic);
    strcpy(g_send_data.send_share_group, share_group);
    char test_payload[] = "5.0 shared sub test";
    memcpy(g_send_data.send_payload, test_payload, strlen(test_payload));
    g_send_data.send_payload_len = strlen(test_payload);
    g_send_data.send_qos = MQTT_SDK_QOS1;
    g_send_data.send_tick = platform_get_tick_ms();

    MqttSdkMsg msg = {0};
    msg.topic = raw_topic;
    msg.payload = (uint8_xxl*)test_payload;
    msg.payload_len = strlen(test_payload);
    msg.qos = MQTT_SDK_QOS1;

    ret = xxl_mqtt_sdk_client_publish(g_mqtt_client, &msg);
    LWIP_SAFE_POLL(); // <-- 加固
    if (ret != MQTT_SDK_OK)
    {
        agent_log_error("Shared pub fail ret:%d", ret);
        g_test_result[2].result = ret;
        strcpy(g_test_result[2].err_info, "shared pub failed");
        mqtt50_test_pause();
        return ret;
    }
    g_pub_send_cnt++;

    ret = mqtt50_test_wait_callback(3000);
    g_test_result[2].callback_check_result = ret;
    g_test_result[2].cost_ms = platform_get_tick_ms() - g_test_start_tick;

    if (ret == 0)
    {
        strcpy(g_recv_data.recv_share_group, share_group);
        if (strcmp(g_recv_data.recv_share_group, share_group) != 0)
        {
            agent_log_error("Share group mismatch");
            g_test_result[2].result = -3;
            strcpy(g_test_result[2].err_info, "group not match");
            mqtt50_test_pause();
        }
        else
        {
            agent_log_info("Shared sub test success");
            g_test_result[2].result = 0;
        }
    }
    else
    {
        agent_log_error("Shared sub callback fail");
        g_test_result[2].result = -4;
        snprintf(g_test_result[2].err_info, sizeof(g_test_result[2].err_info)-1,
                 "callback check fail");
        mqtt50_test_pause();
    }
    xxl_mqtt_sdk_client_unsubscribe(g_mqtt_client, raw_topic, share_group);
    LWIP_SAFE_POLL(); // <-- 加固

    agent_log_info("Case 003 finished");
    return g_test_result[2].result;
}

static int mqtt50_test_case_004_max_pkt_size(void)
{
    mqtt50_test_case_init(3, "5.0 max packet size test");
    int ret = 0;
    char test_topic[] = "mqtt50/biz/test/004";
    uint32_xxl test_pkt_size = MQTT50_TEST_MAX_PKT_SIZE;
    uint8_xxl large_payload[MQTT50_TEST_MAX_PKT_SIZE];

    LWIP_SAFE_POLL(); // <-- 加固

    if (test_pkt_size > sizeof(large_payload)) {
        agent_log_error("Payload buffer overflow");
        g_test_result[3].result = -1;
        strcpy(g_test_result[3].err_info, "buffer not enough");
        mqtt50_test_pause();
        return -1;
    }
    memset(large_payload, 0xAA, test_pkt_size);
    agent_log_info("Large payload len:%d", test_pkt_size);

    g_mqtt_cfg.v50_max_pkt_size = test_pkt_size;

    ret = xxl_mqtt_sdk_client_subscribe(g_mqtt_client, test_topic, MQTT_SDK_QOS0, NULL);
    LWIP_SAFE_POLL(); // <-- 加固
    if (ret != MQTT_SDK_OK)
    {
        agent_log_error("Large sub fail ret:%d", ret);
        g_test_result[3].result = ret;
        strcpy(g_test_result[3].err_info, "subscribe failed");
        mqtt50_test_pause();
        return ret;
    }

    MqttSdkMsg msg = {0};
    msg.topic = test_topic;
    msg.payload = large_payload;
    msg.payload_len = test_pkt_size;
    msg.qos = MQTT_SDK_QOS0;

    ret = xxl_mqtt_sdk_client_publish(g_mqtt_client, &msg);
    LWIP_SAFE_POLL(); // <-- 加固
    g_test_result[3].cost_ms = platform_get_tick_ms() - g_test_start_tick;

    if (ret == MQTT_SDK_OK)
    {
        ret = mqtt50_test_wait_callback(5000);
        if (ret == 0 && g_recv_data.recv_payload_len == test_pkt_size)
        {
            agent_log_info("Large packet test success");
            g_test_result[3].result = 0;
        }
        else
        {
            agent_log_error("Large packet recv len mismatch");
            g_test_result[3].result = -2;
            snprintf(g_test_result[3].err_info, sizeof(g_test_result[3].err_info)-1,
                     "recv len:%d", g_recv_data.recv_payload_len);
            mqtt50_test_pause();
        }
    }
    else if (ret == MQTT_SDK_ERR_PUB)
    {
        agent_log_warn("Large packet publish rejected(expected)");
        g_test_result[3].result = 0;
    }
    else
    {
        agent_log_error("Large packet pub err:%d", ret);
        g_test_result[3].result = -3;
        snprintf(g_test_result[3].err_info, sizeof(g_test_result[3].err_info)-1,
                 "publish err:%d", ret);
        mqtt50_test_pause();
    }
    xxl_mqtt_sdk_client_unsubscribe(g_mqtt_client, test_topic, NULL);
    LWIP_SAFE_POLL(); // <-- 加固

    agent_log_info("Case 004 finished");
    return g_test_result[3].result;
}

static int mqtt50_test_case_005_perf(void)
{
    mqtt50_test_case_init(4, "5.0 performance test");
    int ret = 0;
    uint32_xxl test_dur_ms = MQTT50_TEST_PERF_DUR;
    uint32_xxl start_tick = platform_get_tick_ms();
    char perf_topic[] = "mqtt50/biz/test/perf";

    LWIP_SAFE_POLL(); // <-- 加固

    ret = xxl_mqtt_sdk_client_subscribe(g_mqtt_client, perf_topic, MQTT_SDK_QOS0, NULL);
    LWIP_SAFE_POLL(); // <-- 加固
    if (ret != MQTT_SDK_OK)
    {
        agent_log_error("Perf sub fail ret:%d", ret);
        g_test_result[4].result = ret;
        strcpy(g_test_result[4].err_info, "subscribe failed");
        mqtt50_test_pause();
        return ret;
    }

    agent_log_info("Start 10s perf test");
    MqttSdkMsg msg = {0};
    msg.topic = perf_topic;
    char test_payload[] = "perf test payload";
    msg.payload = (uint8_xxl*)test_payload;
    msg.payload_len = strlen(test_payload);
    msg.qos = MQTT_SDK_QOS0;

    while ((platform_get_tick_ms() - start_tick) < test_dur_ms)
    {
        LWIP_SAFE_POLL(); // <-- 加固
        ret = xxl_mqtt_sdk_client_publish(g_mqtt_client, &msg);
        if (ret == MQTT_SDK_OK) g_pub_send_cnt++;
        
        xxl_mqtt_sdk_client_loop(g_mqtt_client);
        LWIP_SAFE_POLL(); // <-- 加固
        platform_delay_ms(1);
    }

    agent_log_info("Perf test finish, wait remaining packet");
    platform_delay_ms(2000);
    LWIP_SAFE_POLL(); // <-- 加固
    xxl_mqtt_sdk_client_loop(g_mqtt_client);

    float qps = mqtt50_test_calc_qps(test_dur_ms);
    g_test_result[4].perf_qps = qps;
    g_test_result[4].cost_ms = platform_get_tick_ms() - g_test_start_tick;

    if (qps >= 100.0f)
    {
        agent_log_info("Perf test pass, QPS:%.2f", qps);
        g_test_result[4].result = 0;
    }
    else
    {
        agent_log_warn("Perf below threshold, QPS:%.2f", qps);
        g_test_result[4].result = 0;
        snprintf(g_test_result[4].err_info, sizeof(g_test_result[4].err_info)-1,
                 "qps:%.2f", qps);
    }
    xxl_mqtt_sdk_client_unsubscribe(g_mqtt_client, perf_topic, NULL);
    LWIP_SAFE_POLL(); // <-- 加固

    agent_log_info("Case 005 finished");
    return g_test_result[4].result;
}

static int mqtt50_test_case_006_exception(void)
{
    mqtt50_test_case_init(5, "5.0 exception test");
    int ret = 0;
    char invalid_topic[] = "";
    char long_topic[MQTT_SDK_MAX_TOPIC_LEN + 10] = {0};
    memset(long_topic, 'a', MQTT_SDK_MAX_TOPIC_LEN + 5);

    LWIP_SAFE_POLL(); // <-- 加固

    if (xxl_mqtt_sdk_client_get_conn_state(g_mqtt_client) != MQTT_SDK_STATE_CONNECTED)
    {
        agent_log_error("Not connected");
        g_test_result[5].result = -1;
        strcpy(g_test_result[5].err_info, "disconnected");
        mqtt50_test_pause();
        return -1;
    }

    MqttSdkMsg invalid_msg1 = {0};
    invalid_msg1.topic = invalid_topic;
    invalid_msg1.payload = (uint8_xxl*)"invalid test";
    invalid_msg1.payload_len = strlen("invalid test");
    invalid_msg1.qos = MQTT_SDK_QOS1;
    ret = xxl_mqtt_sdk_client_publish(g_mqtt_client, &invalid_msg1);
    LWIP_SAFE_POLL(); // <-- 加固
    if (ret == MQTT_SDK_ERR_PARAM)
    {
        agent_log_info("Empty topic param check pass");
    }
    else
    {
        agent_log_error("Empty topic check fail");
        g_test_result[5].result = -2;
        snprintf(g_test_result[5].err_info, sizeof(g_test_result[5].err_info)-1,
                 "empty topic no error");
    }

    ret = xxl_mqtt_sdk_client_subscribe(g_mqtt_client, long_topic, MQTT_SDK_QOS1, NULL);
    LWIP_SAFE_POLL(); // <-- 加固
    if (ret == MQTT_SDK_ERR_PARAM)
    {
        agent_log_info("Long topic param check pass");
    }
    else
    {
        agent_log_error("Long topic check fail");
        g_test_result[5].result = -3;
        snprintf(g_test_result[5].err_info, sizeof(g_test_result[5].err_info)-1,
                 "long topic no error");
    }

    MqttSdkMsg invalid_msg2 = {0};
    invalid_msg2.topic = "mqtt50/biz/test/006";
    invalid_msg2.payload = (uint8_xxl*)"invalid qos test";
    invalid_msg2.payload_len = strlen("invalid qos test");
    invalid_msg2.qos = (MqttSdkQos)3;
    ret = xxl_mqtt_sdk_client_publish(g_mqtt_client, &invalid_msg2);
    LWIP_SAFE_POLL(); // <-- 加固
    if (ret == MQTT_SDK_ERR_PARAM)
    {
        agent_log_info("Illegal qos param check pass");
    }
    else
    {
        agent_log_error("Illegal qos check fail");
        g_test_result[5].result = -4;
        snprintf(g_test_result[5].err_info, sizeof(g_test_result[5].err_info)-1,
                 "invalid qos no error");
    }

    g_test_result[5].cost_ms = platform_get_tick_ms() - g_test_start_tick;
    if (g_test_result[5].result == 0)
    {
        agent_log_info("Exception test pass");
    }
    else
    {
        agent_log_error("Exception test partial fail");
        mqtt50_test_pause();
    }

    LWIP_SAFE_POLL(); // <-- 加固
    agent_log_info("Case 006 finished");
    return g_test_result[5].result;
}

static int mqtt50_test_case_007_stability(void)
{
    mqtt50_test_case_init(6, "5.0 long connection stability");
    uint32_xxl start_tick = platform_get_tick_ms();
    uint32_xxl stable_dur_ms = MQTT50_TEST_STABLE_DUR;
    MqttSdkConnState last_state = MQTT_SDK_STATE_CONNECTED;

    LWIP_SAFE_POLL(); // <-- 加固

    if (xxl_mqtt_sdk_client_get_conn_state(g_mqtt_client) != MQTT_SDK_STATE_CONNECTED)
    {
        agent_log_error("Not connected");
        g_test_result[6].result = -1;
        strcpy(g_test_result[6].err_info, "disconnected");
        mqtt50_test_pause();
        return -1;
    }

    agent_log_info("Start 60s stable test");
    while ((platform_get_tick_ms() - start_tick) < stable_dur_ms)
    {
        LWIP_SAFE_POLL(); // <-- 加固
        xxl_mqtt_sdk_client_loop(g_mqtt_client);
        platform_delay_ms(1000);

        MqttSdkConnState cur_state = xxl_mqtt_sdk_client_get_conn_state(g_mqtt_client);
        if (cur_state != MQTT_SDK_STATE_CONNECTED)
        {
            agent_log_error("Connection dropped");
            g_test_result[6].result = -2;
            snprintf(g_test_result[6].err_info, sizeof(g_test_result[6].err_info)-1,
                     "conn lost");
            break;
        }
        last_state = cur_state;
    }

    g_test_result[6].cost_ms = platform_get_tick_ms() - g_test_start_tick;
    if (last_state == MQTT_SDK_STATE_CONNECTED && g_test_result[6].result == 0)
    {
        agent_log_info("Stability test pass");
        g_test_result[6].result = 0;
    }
    else
    {
        agent_log_error("Stability test fail");
        mqtt50_test_pause();
    }

    LWIP_SAFE_POLL(); // <-- 加固
    agent_log_info("Case 007 finished");
    return g_test_result[6].result;
}

static int mqtt50_test_case_008_reconnect(void)
{
    mqtt50_test_case_init(7, "5.0 auto reconnect test");
    int ret = 0;
    int reconn_times = MQTT50_TEST_RECONN_TIMES;
    int succ_reconn_cnt = 0;
    char reconn_topic[] = "mqtt50/biz/test/008";

    LWIP_SAFE_POLL(); // <-- 加固

    if (xxl_mqtt_sdk_client_get_conn_state(g_mqtt_client) != MQTT_SDK_STATE_CONNECTED)
    {
        agent_log_error("Not connected");
        g_test_result[7].result = -1;
        strcpy(g_test_result[7].err_info, "disconnected");
        mqtt50_test_pause();
        return -1;
    }

    ret = xxl_mqtt_sdk_client_subscribe(g_mqtt_client, reconn_topic, MQTT_SDK_QOS0, NULL);
    LWIP_SAFE_POLL(); // <-- 加固
    if (ret != MQTT_SDK_OK)
    {
        agent_log_error("Reconn sub fail ret:%d", ret);
        g_test_result[7].result = ret;
        strcpy(g_test_result[7].err_info, "subscribe failed");
        mqtt50_test_pause();
        return ret;
    }

    agent_log_info("Start reconnect test, times:%d", reconn_times);
    for (int i = 0; i < reconn_times; i++)
    {
        agent_log_info("Disconnect manual %d", i+1);
        xxl_mqtt_sdk_client_disconnect(g_mqtt_client);
        LWIP_SAFE_POLL(); // <-- 加固
        platform_delay_ms(2000);
        LWIP_SAFE_POLL(); // <-- 加固

        if (xxl_mqtt_sdk_client_get_conn_state(g_mqtt_client) != MQTT_SDK_STATE_DISCONNECTED)
        {
            agent_log_error("Disconnect fail %d", i+1);
            continue;
        }

        ret = xxl_mqtt_sdk_client_connect(g_mqtt_client);
        LWIP_SAFE_POLL(); // <-- 加固
        if (ret != MQTT_SDK_OK)
        {
            agent_log_error("Reconn api fail %d", i+1);
            continue;
        }

        uint32_xxl reconn_start = platform_get_tick_ms();
        while ((platform_get_tick_ms() - reconn_start) < 5000)
        {
            LWIP_SAFE_POLL(); // <-- 加固
            xxl_mqtt_sdk_client_loop(g_mqtt_client);
            platform_delay_ms(100);
            if (xxl_mqtt_sdk_client_get_conn_state(g_mqtt_client) == MQTT_SDK_STATE_CONNECTED)
            {
                succ_reconn_cnt++;
                agent_log_info("Reconnect success %d", i+1);
                break;
            }
        }

        if (xxl_mqtt_sdk_client_get_conn_state(g_mqtt_client) == MQTT_SDK_STATE_CONNECTED)
        {
            MqttSdkMsg msg = {0};
            msg.topic = reconn_topic;
            char reconn_payload[32] = {0};
            snprintf((char*)reconn_payload, sizeof(reconn_payload)-1, "reconn test %d", i+1);
            msg.payload = (uint8_xxl*)reconn_payload;
            msg.payload_len = strlen((char*)reconn_payload);
            msg.qos = MQTT_SDK_QOS0;
            
            ret = xxl_mqtt_sdk_client_publish(g_mqtt_client, &msg);
            LWIP_SAFE_POLL(); // <-- 加固
            if (ret == MQTT_SDK_OK)
            {
                agent_log_info("Reconn publish check ok");
            }
        }
    }

    g_test_result[7].cost_ms = platform_get_tick_ms() - g_test_start_tick;
    if (succ_reconn_cnt == reconn_times)
    {
        agent_log_info("Reconnect test all pass");
        g_test_result[7].result = 0;
    }
    else
    {
        agent_log_error("Reconnect partial fail:%d/%d",succ_reconn_cnt,reconn_times);
        g_test_result[7].result = -3;
        snprintf(g_test_result[7].err_info, sizeof(g_test_result[7].err_info)-1,
                 "succ:%d total:%d",succ_reconn_cnt,reconn_times);
        mqtt50_test_pause();
    }
    xxl_mqtt_sdk_client_unsubscribe(g_mqtt_client, reconn_topic, NULL);
    LWIP_SAFE_POLL(); // <-- 加固

    agent_log_info("Case 008 finished");
    return g_test_result[7].result;
}

static void mqtt50_test_init(void)
{
    agent_log_info("MQTT50 test init start");

    memset(&g_mqtt_cfg, 0, sizeof(MqttSdkClientCfg));
    g_mqtt_cfg.client_id = TEST_CLIENT_ID;
    g_mqtt_cfg.broker_ip = TEST_BROKER_IP;
    g_mqtt_cfg.broker_port = TEST_BROKER_PORT;
    g_mqtt_cfg.clean_start = TRUE;
    g_mqtt_cfg.keep_alive = TEST_KEEP_ALIVE_TIME;
    g_mqtt_cfg.reconnect_intv = TEST_RECONNECT_INTER;
    g_mqtt_cfg.max_reconnect = TEST_MAX_RECONNECT;
    g_mqtt_cfg.mqtt_version = MQTT_SDK_PROTOCOL_V50;
    g_mqtt_cfg.v50_max_pkt_size = MQTT50_TEST_MAX_PKT_SIZE;

    g_mqtt_client = xxl_mqtt_sdk_client_create(&g_mqtt_cfg, mqtt_test_msg_callback, mqtt_test_broker_resp_callback);
    LWIP_SAFE_POLL(); // <-- 加固
    if (g_mqtt_client == NULL)
    {
        agent_log_error("Create mqtt client fail");
        return;
    }
    agent_log_info("Mqtt client create ok");

    MqttSdkErrCode ret = xxl_mqtt_sdk_client_connect(g_mqtt_client);
    LWIP_SAFE_POLL(); // <-- 加固
    if (ret != MQTT_SDK_OK)
    {
        agent_log_error("Connect broker fail:%d", ret);
        return;
    }
    agent_log_info("Connect api call ok");

    platform_delay_ms(1000);
    LWIP_SAFE_POLL(); // <-- 加固
    g_last_conn_state = xxl_mqtt_sdk_client_get_conn_state(g_mqtt_client);
    agent_log_info("Current conn state:%d", g_last_conn_state);
}

static void mqtt50_test_summary(void)
{
    agent_log_info("========== Test Summary ==========");
    int succ_cnt = 0, fail_cnt = 0, callback_fail_cnt = 0;

    LWIP_SAFE_POLL(); // <-- 加固

    for (int i = 0; i < TEST_CASE_TOTAL; i++)
    {
        if (g_test_result[i].result == 0) succ_cnt++;
        else fail_cnt++;
        if (g_test_result[i].callback_check_result != 0) callback_fail_cnt++;
    }

    agent_log_info("Total:%d Succ:%d Fail:%d",TEST_CASE_TOTAL,succ_cnt,fail_cnt);
    agent_log_info("==================================");
}

static void mqtt50_test_main(void)
{
    mqtt50_test_init();
    LWIP_SAFE_POLL(); // <-- 加固
    if (g_mqtt_client == NULL)
    {
        agent_log_error("Test abort: client null");
        return;
    }

    agent_log_info("Start mqtt50 full test suite");

    mqtt50_test_case_001_conn();
    mqtt50_test_case_002_pubsub();
    mqtt50_test_case_003_shared_sub();
    mqtt50_test_case_004_max_pkt_size();
    mqtt50_test_case_005_perf();
    mqtt50_test_case_006_exception();
    mqtt50_test_case_007_stability();
    mqtt50_test_case_008_reconnect();

    mqtt50_test_summary();

    agent_log_info("Clean mqtt resource");
    xxl_mqtt_sdk_client_disconnect(g_mqtt_client);
    LWIP_SAFE_POLL(); // <-- 加固
    xxl_mqtt_sdk_client_destroy(g_mqtt_client);
    LWIP_SAFE_POLL(); // <-- 加固
    g_mqtt_client = NULL;

    agent_log_info("MQTT50 test all finished");
}

static void mqtt50_log_init(void)
{
    AgentLogConfig log_cfg = {0};
    log_cfg.level = AGENT_LOG_INFO;
    log_cfg.dest = AGENT_LOG_DEST_CONSOLE;
    log_cfg.max_flash_size = 2 * 1024 * 1024;
    log_cfg.max_log_length = 256;
    agent_log_init(&log_cfg);
    agent_log_info("Log init ok");
}

// ==========================
// 真正的 STM32 main（硬件完全不变）
// ==========================
int main(void)
{
    u8 real_ip[4] = {0};
    u8 real_gw[4] = {0};

    HAL_Init();
    Stm32_Clock_Init(336,8,2,7);
    delay_init(168);
    uart_init(115200);
    LED_Init();
    BEEP_Init();
    KEY_Init();
    LCD_Init();
    SRAM_Init();
    MY_ADC_Init();
    RTC_Init();
    TIM3_Init(1000-1,840-1);

    my_mem_init(SRAMIN);
    my_mem_init(SRAMEX);
    my_mem_init(SRAMCCM);

    printf("\r\n\r\n=============================================\r\n");
    printf(" STM32F407 LwIP + MQTT5.0 TEST\r\n");
    printf("=============================================\r\n");

    //===========================================================================
    // LWIP 1.4.1 直连电脑 —— 静态IP + 共享上网
    //===========================================================================
    lwipdev.dhcpstatus = 0;      // 0=静态IP，必须关闭DHCP

    // STM32 静态IP
    lwipdev.ip[0] = 192;
    lwipdev.ip[1] = 168;
lwipdev.ip[2]        = 137;
lwipdev.ip[3]        = 130;    // STM32 IP

    // 子网掩码
    lwipdev.netmask[0] = 255;
    lwipdev.netmask[1] = 255;
    lwipdev.netmask[2] = 255;
    lwipdev.netmask[3] = 0;

    // 网关 = 电脑IP（关键：共享上网）
lwipdev.gateway[0]   = 192;    // 网关 = 电脑共享IP
lwipdev.gateway[1]   = 168;
lwipdev.gateway[2]   = 137;
lwipdev.gateway[3]   = 1;

    // MAC地址
    lwipdev.mac[0] = 0x00;
    lwipdev.mac[1] = 0x11;
    lwipdev.mac[2] = 0x22;
    lwipdev.mac[3] = 0x33;
    lwipdev.mac[4] = 0x44;
    lwipdev.mac[5] = 0x55;

    while(lwip_comm_init())
    {
        printf("[NET] LwIP Init FAIL, Retry...\r\n");
        delay_ms(50);
        LWIP_SAFE_POLL();
    }
    printf("[NET] LwIP Init OK\r\n");

    // ==========================
    // LWIP 1.4.1 强制静态IP（必杀代码！关掉DHCP）
    // ==========================
    {
        ip_addr_t ip, nm, gw;
        IP4_ADDR(&ip,  192,168,137,130);
        IP4_ADDR(&nm,  255,255,255,0);
        IP4_ADDR(&gw,  192,168,137,1);
        
        netif_set_ipaddr(netif_default, &ip);
        netif_set_netmask(netif_default, &nm);
        netif_set_gw(netif_default, &gw);
        netif_set_up(netif_default);
        
        printf("[NET] 静态IP强制配置完成\r\n");
    }

    // ==========================
    // DNS
    // ==========================
    {
        ip_addr_t dns_srv;
        IP4_ADDR(&dns_srv, 223, 5, 5, 5);
        dns_setserver(0, &dns_srv);
        IP4_ADDR(&dns_srv, 8, 8, 8, 8);
        dns_setserver(1, &dns_srv);
        printf("[NET] DNS Server: 223.5.5.5 & 8.8.8.8 OK\r\n");
    }

    printf("[NET] Waiting for IP ready...\r\n");
    while (!lwip_net_is_ready())
    {
        LWIP_SAFE_POLL();
        delay_ms(50);
    }

    get_lwip_real_ip(real_ip);
    get_lwip_real_gw(real_gw);

    printf("\r\n=============================================\r\n");
    printf("[NET] REAL IP     : %d.%d.%d.%d\r\n", real_ip[0],real_ip[1],real_ip[2],real_ip[3]);
    printf("[NET] REAL GW     : %d.%d.%d.%d\r\n", real_gw[0],real_gw[1],real_gw[2],real_gw[3]);
    printf("=============================================\r\n\r\n");

    delay_ms(1500);

    // ======================
    // MQTT 测试运行期间，LWIP 全程实时调度，绝对不会挂死
    // ======================
    xxl_mqtt_sdk_global_init();
    mqtt50_log_init();
    mqtt50_test_main();
    xxl_mqtt_sdk_global_deinit();

    // 测试跑完后，主循环空闲
    while(1)
    {
        LED0 = !LED0;
        LWIP_SAFE_POLL();
        delay_ms(500);
    }
}

#endif
