#include "link_uart.h"
#include "remote_control.h"
#include "wifidevnum_config.h"
#include "device_nvs.h"
#include "rc_pwm_control.h"
#include "esp_log.h"
#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "link_dma_uart.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>

#include "sdkconfig.h"

#include "core/build_config.h"
#include "task_manager.h"

#if BUILD_IS_DEBUG
/* Debug 固定仅打印 JSON 级日志；RAW 日志关闭，避免刷屏 */
#define UART_LINK_LOG_TX_JSON 1
#define UART_LINK_LOG_TX_RAW  0
#define UART_LINK_LOG_RX_JSON 1
#define UART_LINK_LOG_RX_RAW  0
#else
#define UART_LINK_LOG_TX_JSON 0
#define UART_LINK_LOG_TX_RAW  0
#define UART_LINK_LOG_RX_JSON 0
#define UART_LINK_LOG_RX_RAW  0
#endif
#include "heart_payload.h"
#include "ota_offer_protocol.h"
#include "ota_frame_protocol.h"
#include "ota_uart_tune.h"

/* OTA 二进制流模块 */
#include "ota_binary_stream.h"
#include "cJSON.h"

static const char *tag_s = "LINK_UART";

/* UART 配置 */
#define UART_LINK_PORT          UART_NUM_1

/* JSON 接收缓冲 */
#define UART_JSON_MAX_BYTES     REMOTE_CTRL_JSON_MAX_BYTES

/* 心跳周期 */
#ifndef UART_HEART_PERIOD_MS
#define UART_HEART_PERIOD_MS    3000
#endif

/* 心跳：对端曾 RX 且在此窗口内（允许 App 只收不发） */
#define UART_LINK_ALIVE_MS      (UART_HEART_PERIOD_MS + 5000)
/* 拔线/无字节：超过此时间无 RX 即停停车推送 */
#define UART_PEER_UNPLUG_MS          1200
/* OTA 已武装、尚未 BEGIN：允许 App 在 0 后等待 active/BEGIN（对齐 App OTA_ACTIVE_WAIT_MS） */
#define UART_OTA_ARMED_IDLE_MS       15000
/* OTA 二进制传输中：无手机 RX 超时由 ota_uart_tune_transfer_idle_ms() 按波特率计算 */

/*
 * UART RX 环形缓冲区：esp_ota_begin / flash 写不得在 uart_evt_rx(4KB 栈) 内同步执行。
 * 每槽 1024B，可容纳一整帧 OT DATA（876B 载荷 + 帧头 ≈ 886B）。
 * worker 按槽逐段喂入解析器，禁止合并截断（旧版 512B cap 会在 seq≈35 处 CRC 失败）。
 * 动态栈：平时 8KB，OTA 切 16KB，结束切回。
 */
#define UART_RX_RING_SLOTS           32
#define UART_RX_SLOT_SIZE            1024
#define UART_RX_WORKER_STACK_NORMAL  8192
#define UART_RX_WORKER_STACK_OTA     16384
#define UART_RX_WORKER_PRIO           5

typedef struct {
    volatile uint8_t write_idx;   /* DMA 回调写入 */
    volatile uint8_t read_idx;    /* worker 读出 */
    uint16_t len[UART_RX_RING_SLOTS];
    uint8_t  data[UART_RX_RING_SLOTS][UART_RX_SLOT_SIZE];
} uart_rx_ring_t;

/* 协议帧分隔符（使用换行符作为 JSON 分隔） */
#define UART_FRAME_DELIMITER    '\n'

/* 函数前向声明 */
static int uart_link_send_json_line(const char *json);
static void uart_send_heartbeat_once(void);

static TaskHandle_t rx_task_handle_s = NULL;
static TaskHandle_t hb_task_handle_s = NULL;
static TaskHandle_t uart_rx_worker_handle_s = NULL;
static volatile bool link_up_s = false;

/* OTA 期间动态栈管理 */
static volatile bool uart_rx_worker_is_ota_stack_s = false;
static SemaphoreHandle_t uart_rx_worker_mutex_s = NULL;
/** 上次从 UART1 RX 收到对端数据的时刻；0=从未收到 */
static volatile uint32_t last_peer_rx_ms = 0;

/* 发送互斥 */
static SemaphoreHandle_t tx_mutex_s = NULL;

/* 接收 JSON 缓冲区 */
static char rx_json_buf_s[UART_JSON_MAX_BYTES + 1];
static size_t rx_buf_pos_s = 0;

/* OTA 状态缓冲 */
static char last_ota_stat_json_s[192];
static bool uart_ota_framed_mode_s = false;

#if BUILD_IS_RELEASE
static bool uart_log_hook_installed_s;
static volatile bool uart_log_forward_busy_s;
#endif

static uint32_t get_current_time_ms(void)
{
    return (uint32_t)(xTaskGetTickCount() * portTICK_PERIOD_MS);
}

/* UART OTA 状态：仅缓存供调试，不向串口发 JSON（固件数据按字节回传） */
static void uart_ota_status_callback(const char *json)
{
    if (json == NULL) {
        return;
    }
    strncpy(last_ota_stat_json_s, json, sizeof(last_ota_stat_json_s) - 1);
    last_ota_stat_json_s[sizeof(last_ota_stat_json_s) - 1] = '\0';
}

/* UART OTA 初始化 */
static void uart_ota_init(void)
{
    /* 初始化通用 OTA 模块 */
    esp_err_t err = ota_binary_stream_init(OTA_TRANSPORT_UART, uart_ota_status_callback, NULL);
    if (err != ESP_OK) {
        ESP_LOGE(tag_s, "UART OTA init failed: %s", esp_err_to_name(err));
    } else {
        ESP_LOGI(tag_s, "UART OTA initialized");
    }
}

#if UART_LINK_LOG_TX_JSON
static const char *uart_tx_json_kind_hint(const char *json)
{
    if (!json) {
        return "JSON";
    }
    if (strstr(json, "\"message_type\":1002") != NULL) {
        return "OTA(1002)";
    }
    if (strstr(json, "\"message_type\":1}") != NULL ||
        strstr(json, "\"message_type\": 1}") != NULL ||
        strstr(json, "\"message_type\":1,") != NULL ||
        strstr(json, "\"message_type\": 1,") != NULL) {
        return "心跳(1)";
    }
    if (strstr(json, "\"message_type\":3") != NULL) {
        return "停车/状态(3)";
    }
    if (strstr(json, "\"message_type\":4") != NULL ||
        strstr(json, "\"message_type\": 4") != NULL) {
        return "告警(4)";
    }
    if (strstr(json, "\"message_type\":5") != NULL ||
        strstr(json, "\"message_type\": 5") != NULL) {
        return "错误(5)";
    }
    return "JSON";
}
#endif

static void uart_link_log_tx_json(const char *json)
{
#if UART_LINK_LOG_TX_JSON
    if (json) {
        ESP_LOGI(tag_s, "UART1 TX %s: %s", uart_tx_json_kind_hint(json), json);
    }
#else
    (void)json;
#endif
}

static void uart_link_log_tx_raw(const uint8_t *data, size_t len)
{
#if UART_LINK_LOG_TX_RAW
    if (!data || len == 0) {
        return;
    }
    /* 仅打印长度和 ASCII 预览，省略 hex dump 便于阅读 */
    char ascii[65];
    size_t n = len > sizeof(ascii) - 1 ? sizeof(ascii) - 1 : len;
    for (size_t i = 0; i < n; i++) {
        uint8_t c = data[i];
        ascii[i] = (c >= 32 && c < 127) ? (char)c : '.';
    }
    ascii[n] = '\0';
    if (len > n) {
        ESP_LOGI(tag_s, "UART1 TX %u bytes: \"%s\"...", (unsigned)len, ascii);
    } else {
        ESP_LOGI(tag_s, "UART1 TX %u bytes: \"%s\"", (unsigned)len, ascii);
    }
#else
    (void)data;
    (void)len;
#endif
}

static int uart_link_send_internal(const uint8_t *data, size_t len)
{
    if (!data || len == 0) {
        return -1;
    }
    return link_dma_uart_send(data, len, 200);
}

static bool uart_link_tx_acquire(TickType_t timeout)
{
    if (tx_mutex_s == NULL) {
        return false;
    }
    if (xSemaphoreTake(tx_mutex_s, timeout) != pdTRUE) {
        ESP_LOGW(tag_s, "UART1 TX 互斥等待超时");
        return false;
    }
    return true;
}

static void uart_link_tx_release(void)
{
    if (tx_mutex_s != NULL) {
        xSemaphoreGive(tx_mutex_s);
    }
}

static int uart_link_tx(const uint8_t *data, size_t len, TickType_t mutex_timeout)
{
    if (!data || len == 0) {
        return -1;
    }
    if (!uart_link_tx_acquire(mutex_timeout)) {
        return -2;
    }
    int ret = uart_link_send_internal(data, len);
    if (ret > 0) {
        uart_link_log_tx_raw(data, len);
    }
    uart_link_tx_release();
    return ret;
}

static void uart_link_note_peer_rx(void)
{
    last_peer_rx_ms = get_current_time_ms();
    link_up_s = true;
}

int link_uart_send_raw(const uint8_t *data, size_t len)
{
    return uart_link_tx(data, len, portMAX_DELAY);
}

static int uart_link_send_json_line(const char *json)
{
    if (!json) {
        return -1;
    }

    size_t len = strlen(json);
    if (len == 0 || len > 1024) {
        return -1;
    }

    if (!uart_link_tx_acquire(portMAX_DELAY)) {
        return -2;
    }

    int ret = uart_link_send_internal((const uint8_t *)json, len);
    if (ret > 0) {
        ret += uart_link_send_internal((const uint8_t *)"\n", 1);
        uart_link_log_tx_json(json);
    }

    uart_link_tx_release();
    return ret;
}

int link_uart_send_heartbeat(const char *json)
{
    return uart_link_send_json_line(json);
}

int link_uart_send_log(const char *json)
{
    return uart_link_send_json_line(json);
}

#if BUILD_IS_RELEASE
static void uart_log_line_to_msg(const char *line, char *msg, size_t msg_cap)
{
    const char *colon = strchr(line, ':');
    if (colon != NULL && colon[1] == ' ') {
        strncpy(msg, colon + 2, msg_cap - 1U);
    } else {
        strncpy(msg, line, msg_cap - 1U);
    }
    msg[msg_cap - 1U] = '\0';
    size_t ml = strlen(msg);
    while (ml > 0U && (msg[ml - 1U] == '\n' || msg[ml - 1U] == '\r')) {
        msg[--ml] = '\0';
    }
}

static int uart_log_vprintf_hook(const char *fmt, va_list ap)
{
    (void)fmt;
    if (xPortInIsrContext() || uart_log_forward_busy_s || !link_uart_has_peer_seen()) {
        return 0;
    }
    /* OTA 期间 UART1 只走 OT 二进制 ACK，禁止插入 JSON 日志行以免 App 组帧失败 */
    if (ota_offer_session_busy()) {
        return 0;
    }

    char line[192];
    va_list ap_line;
    va_copy(ap_line, ap);
    int ln = vsnprintf(line, sizeof(line), fmt, ap_line);
    va_end(ap_line);
    if (ln <= 0) {
        return 0;
    }

    int msg_type = 0;
    if (line[0] == 'W') {
        msg_type = HEART_MSG_TYPE_LOG_WARN;
    } else if (line[0] == 'E') {
        msg_type = HEART_MSG_TYPE_LOG_ERROR;
    } else {
        return 0;
    }

    char msg[160];
    uart_log_line_to_msg(line, msg, sizeof(msg));

    char *json = heart_payload_alert_json_malloc(msg_type, msg);
    if (json == NULL) {
        return 0;
    }

    uart_log_forward_busy_s = true;
    (void)link_uart_send_log(json);
    uart_log_forward_busy_s = false;
    free(json);
    return 0;
}

static void uart_log_hook_install_if_needed(void)
{
    if (uart_log_hook_installed_s) {
        return;
    }
    (void)esp_log_set_vprintf(uart_log_vprintf_hook);
    uart_log_hook_installed_s = true;
}
#endif

static bool uart_peer_rx_recent(void)
{
    uint32_t last = last_peer_rx_ms;
    if (last == 0) {
        return false;
    }
    return (get_current_time_ms() - last) < UART_PEER_UNPLUG_MS;
}

bool link_uart_has_peer_seen(void)
{
    return last_peer_rx_ms != 0;
}

bool link_uart_is_connected(void)
{
    uint32_t last = last_peer_rx_ms;
    if (last == 0) {
        return false;
    }
    return (get_current_time_ms() - last) < UART_LINK_ALIVE_MS;
}

static void uart_send_ota_offer_json(const char *json)
{
    if (!json) {
        return;
    }
    (void)uart_link_send_json_line(json);
}

static void uart_ota_done_report(bool success, uint32_t bytes_written, const char *err_step)
{
    char devid[32] = {0};
    read_from_nvs(DEVICE_CFG_KEY_DEVICE_ID, devid, sizeof(devid));

    char *json = ota_offer_result_json_malloc(devid, success, bytes_written, err_step);
    if (json) {
        for (int i = 0; i < OTA_DONE_REPORT_COUNT; i++) {
            uart_send_ota_offer_json(json);
            ESP_LOGI(tag_s, "UART1 TX OTA done (1002) %d/%d", i + 1, OTA_DONE_REPORT_COUNT);
            if (i + 1 < OTA_DONE_REPORT_COUNT) {
                vTaskDelay(pdMS_TO_TICKS(OTA_DONE_REPORT_GAP_MS));
            }
        }
        free(json);
    }
    if (!success) {
        uart_send_heartbeat_once();
    }
}

static void uart_send_ota_active_notice(void)
{
    char devid[32] = {0};
    read_from_nvs(DEVICE_CFG_KEY_DEVICE_ID, devid, sizeof(devid));

    char *json = ota_offer_active_json_malloc(devid);
    if (json) {
        ESP_LOGI(tag_s, "UART1 TX OTA 进行中 (1002/active)");
        uart_send_ota_offer_json(json);
        free(json);
    }
}

/** 手机 message_type=6：回复 OTA 询问（每次重连串口可各发一次） */
static void uart_send_ota_query_on_link_ready(void)
{
    char devid[32] = {0};
    read_from_nvs(DEVICE_CFG_KEY_DEVICE_ID, devid, sizeof(devid));

    char *json = ota_offer_query_json_malloc(devid);
    if (json) {
        uart_send_ota_offer_json(json);
        free(json);
    }
}

static void link_uart_session_reset_ex(const char *ota_abort_err)
{
    if (ota_abort_err != NULL) {
        ota_offer_report_abort(ota_abort_err);
    }
    rx_buf_pos_s = 0;
    uart_ota_framed_mode_s = false;
    ota_frame_protocol_reset();
    remote_control_link_reset();
}

/* 处理接收到的 JSON（root 已由调用方解析） */
static void process_received_json(cJSON *root, const char *json)
{
    if (!root || !json || json[0] == '\0') {
        return;
    }

#if UART_LINK_LOG_RX_JSON
    ESP_LOGI(tag_s, "UART1 RX JSON line: %s", json);
#endif

    cJSON *head = cJSON_GetObjectItem(root, "head");
    cJSON *m_type = (head && cJSON_IsObject(head)) ? cJSON_GetObjectItem(head, "message_type") : NULL;

    if (m_type && cJSON_IsNumber(m_type) && m_type->valueint == REMOTE_CTRL_MSG_LINK_RESET) {
        link_uart_session_reset_ex("reset");
        ESP_LOGI(tag_s, "收到 message_type=2，已清空 UART 会话");
        return;
    }

    if (m_type && cJSON_IsNumber(m_type) && (int)m_type->valuedouble == REMOTE_CTRL_MSG_LINK_READY) {
        ESP_LOGI(tag_s, "UART1 收到 link_ready(6)，回复 OTA 询问 1002/query + 首条心跳");
        uart_send_ota_query_on_link_ready();
        uart_send_heartbeat_once();
        return;
    }

    if (ota_offer_parse_phone_response(root)) {
        ESP_LOGI(tag_s, "手机同意 OTA (head.message_type=0)，可发 OT 帧");
        uart_send_ota_active_notice();
        return;
    }

    remote_control_apply_json_root(root, json);
}

static const char *uart_ota_frame_op_name(uint8_t op)
{
    switch (op) {
    case OTA_FRAME_OP_BEGIN:
        return "BEGIN";
    case OTA_FRAME_OP_DATA:
        return "DATA";
    case OTA_FRAME_OP_END:
        return "END";
    case OTA_FRAME_OP_ACK:
        return "ACK";
    case OTA_FRAME_OP_NAK:
        return "NAK";
    default:
        return "OT";
    }
}

static void uart_ota_tx_frame(const uint8_t *frame, uint16_t len, void *ctx)
{
    (void)ctx;
    if (frame == NULL || len == 0) {
        return;
    }
    if (len >= 4) {
        ESP_LOGI(tag_s, "UART1 TX OTA %s (%u bytes, seq=%u)",
                 uart_ota_frame_op_name(frame[3]), (unsigned)len,
                 (unsigned)(frame[4] | ((uint16_t)frame[5] << 8)));
    }
    (void)uart_link_tx(frame, len, portMAX_DELAY);
}

/* 旧版裸字节回显（无 OT 帧头时兼容） */
static void uart_link_ota_ack_payload(const uint8_t *payload, uint16_t payload_len)
{
    for (uint16_t i = 0; i < payload_len; i++) {
        uint8_t b = payload[i];
        (void)uart_link_tx(&b, 1, portMAX_DELAY);
    }
}

/* 处理 OTA 数据包（0x01/0x02/0x03）；仅 0x02 固件载荷按字节回传 */
static void process_ota_packet(const uint8_t *data, uint16_t len)
{
    if (!data || len == 0) {
        return;
    }

    if (ota_frame_rx_looks_framed(data, len)) {
        ota_frame_rx_feed(data, len);
        return;
    }

    uint8_t op = data[0];
    int rc = ota_binary_stream_process_packet(data, len);

    if (rc == 0 && op == OTA_OP_DATA && len > 1) {
        uart_link_ota_ack_payload(data + 1, (uint16_t)(len - 1));
    }
}

/* 检查数据是否为 OTA 命令（以 0x01/0x02/0x03 开头） */
static bool is_ota_command(uint8_t first_byte)
{
    return (first_byte == 0x01 || first_byte == 0x02 || first_byte == 0x03);
}

static bool uart_rx_json_balanced(const char *s)
{
    int depth = 0;

    if (!s || s[0] != '{') {
        return false;
    }

    for (; *s != '\0'; s++) {
        if (*s == '{') {
            depth++;
        } else if (*s == '}') {
            depth--;
            if (depth < 0) {
                return false;
            }
        }
    }
    return depth == 0;
}

static void uart_rx_try_finish_json_line(void)
{
    if (rx_buf_pos_s == 0) {
        return;
    }
    rx_json_buf_s[rx_buf_pos_s] = '\0';

    if (rx_json_buf_s[0] != '{') {
        ESP_LOGW(tag_s, "UART1 RX 行结束但非 JSON (len=%u)", (unsigned)rx_buf_pos_s);
        rx_buf_pos_s = 0;
        return;
    }

    cJSON *root = cJSON_Parse(rx_json_buf_s);
    if (!root) {
        if (!uart_rx_json_balanced(rx_json_buf_s)) {
            /* 多行/分段 JSON 尚未收齐，继续累积 */
            return;
        }
        ESP_LOGW(tag_s, "UART1 RX JSON 无效 (len=%u)", (unsigned)rx_buf_pos_s);
        rx_buf_pos_s = 0;
        return;
    }

    process_received_json(root, rx_json_buf_s);
    cJSON_Delete(root);
    rx_buf_pos_s = 0;
}

/* 原始接收调试：本函数用 ESP_LOG 打印；输出在「控制台 UART」(默认 UART0/USB)，与 UART1 业务引脚可能相同，见文档 §1.5 */
static void log_uart1_rx_raw(const uint8_t *data, int len)
{
#if UART_LINK_LOG_RX_RAW
    if (!data || len <= 0) {
        return;
    }
    /* 仅打印长度和 ASCII 内容，省略 hex dump 便于阅读 JSON */
    char ascii[129];
    int n = len > (int)sizeof(ascii) - 1 ? (int)sizeof(ascii) - 1 : len;
    for (int i = 0; i < n; i++) {
        uint8_t c = data[i];
        ascii[i] = (c >= 32 && c < 127) ? (char)c : '.';
    }
    ascii[n] = '\0';
    if (len > n) {
        ESP_LOGI(tag_s, "UART1 RX %d bytes: \"%s\"...", len, ascii);
    } else {
        ESP_LOGI(tag_s, "UART1 RX %d bytes: \"%s\"", len, ascii);
    }
#else
    (void)data;
    (void)len;
#endif
}

/** 处理 JSON 行后的 OT 帧 / 裸 OTA 字节（同一 uart_read 内粘包） */
static void link_uart_feed_rx_binary_chunk(const uint8_t *data, int len)
{
    if (!data || len <= 0) {
        return;
    }

    bool frame_parser_active = ota_frame_rx_is_active();
    bool frame_header_complete = (len >= 2 && data[0] == OTA_FRAME_MAGIC0 && data[1] == OTA_FRAME_MAGIC1);
    if (uart_ota_framed_mode_s || frame_parser_active || ota_frame_rx_looks_framed(data, len)) {
        if (!ota_offer_is_armed() && !ota_binary_stream_is_active()) {
            ESP_LOGW(tag_s, "UART1 OT 帧在未 armed 时到达，将回 NAK（须先发 message_type=0）");
        }
        if (uart_ota_framed_mode_s || frame_parser_active || frame_header_complete) {
            uart_ota_framed_mode_s = true;
        }
        ESP_LOGD(tag_s, "UART1 OTA frame bytes (%d bytes)", len);
        ota_frame_rx_feed(data, (uint16_t)len);
        return;
    }

    if (is_ota_command(data[0])) {
        if (!ota_offer_is_armed() && !ota_binary_stream_is_active()) {
            ESP_LOGW(tag_s, "UART1 忽略 OTA 二进制：尚未收到手机 message_type=0");
            return;
        }
        ESP_LOGI(tag_s, "UART1 legacy OTA packet (%d bytes)", len);
        process_ota_packet(data, len);
        return;
    }

    /* 未识别为 OT 帧的杂字节在 OTA 期间丢弃，禁止走裸字节写入 flash */
    if (ota_binary_stream_is_active() || ota_offer_is_armed()) {
        ESP_LOGW(tag_s, "UART1 丢弃 OTA 期间非 OT 帧数据 (%d bytes)", len);
    }
}

static void uart_skip_json_delimiters_before_ota(const uint8_t **data, int *len)
{
    while (*len > 0 && ((*data)[0] == '\r' || (*data)[0] == '\n')) {
        (*data)++;
        (*len)--;
    }
}

static bool uart_link_ota_rx_busy(void)
{
    return uart_ota_framed_mode_s || ota_frame_rx_is_active() ||
           ota_offer_is_armed() || ota_binary_stream_is_active();
}

static void link_uart_feed_rx_bytes(const uint8_t *data, int len)
{
    if (!data || len <= 0) {
        return;
    }

    uart_link_note_peer_rx();
    log_uart1_rx_raw(data, len);

    /*
     * OTA 期间 UART1 只走 OT 二进制解析。
     * 固件载荷里常有 0x7B('{'）：若走 JSON 逐字节路径会误解析并破坏 OT 帧同步。
     */
    if (uart_link_ota_rx_busy()) {
        remote_control_note_rx_activity();
        if (rx_buf_pos_s > 0) {
            rx_buf_pos_s = 0;
        }
        if (ota_offer_is_armed() && !ota_binary_stream_is_active()) {
            uart_skip_json_delimiters_before_ota(&data, &len);
            if (len <= 0) {
                return;
            }
        }
        link_uart_feed_rx_binary_chunk(data, len);
        return;
    }

    if (rx_buf_pos_s > 0 || data[0] == '{') {
        remote_control_note_rx_activity();
    }

    /* 整包即为 OT 帧或裸 0x01/0x02/0x03（不以 { 开头） */
    if (data[0] != '{' &&
        (ota_frame_rx_looks_framed(data, len) || is_ota_command(data[0]))) {
        link_uart_feed_rx_binary_chunk(data, len);
        return;
    }

    for (int i = 0; i < len; i++) {
        uint8_t ch = data[i];

        if (is_ota_command(ch) && i == 0 && rx_buf_pos_s == 0) {
            link_uart_feed_rx_binary_chunk(data + i, len - i);
            break;
        }

        if (ch == UART_FRAME_DELIMITER || ch == '\r') {
            uart_rx_try_finish_json_line();
            /* 同一 read 内：{"...":0}\nOT... 须在 JSON 行后立刻吃二进制尾 */
            int tail = i + 1;
            if (tail < len) {
                const uint8_t *tail_data = data + tail;
                int tail_len = len - tail;
                uart_skip_json_delimiters_before_ota(&tail_data, &tail_len);
                link_uart_feed_rx_binary_chunk(tail_data, tail_len);
                return;
            }
        } else if (rx_buf_pos_s < UART_JSON_MAX_BYTES) {
            rx_json_buf_s[rx_buf_pos_s++] = ch;
        } else {
            ESP_LOGW(tag_s, "UART1 RX JSON buffer overflow");
            rx_buf_pos_s = 0;
        }
    }
}

/* 环形缓冲区实例（静态分配，避免运行时 malloc） */
static uart_rx_ring_t uart_rx_ring_s;
static SemaphoreHandle_t uart_rx_data_sem_s = NULL;  /* 数据可用信号量 */
static SemaphoreHandle_t uart_rx_ring_mutex_s = NULL;

static void uart_rx_ring_init(void)
{
    memset(&uart_rx_ring_s, 0, sizeof(uart_rx_ring_s));
    uart_rx_ring_s.write_idx = 0;
    uart_rx_ring_s.read_idx = 0;
}

static inline bool uart_rx_ring_full(void)
{
    uint8_t next = (uart_rx_ring_s.write_idx + 1) % UART_RX_RING_SLOTS;
    return next == uart_rx_ring_s.read_idx;
}

static inline bool uart_rx_ring_empty(void)
{
    return uart_rx_ring_s.write_idx == uart_rx_ring_s.read_idx;
}

/**
 * @brief 向环形缓冲区写入数据（DMA 回调调用，须快速）
 * @return true=成功，false=满（丢包）
 */
static bool uart_rx_ring_write(const uint8_t *data, size_t len)
{
    if (len == 0) {
        return true;
    }

    if (uart_rx_ring_mutex_s != NULL) {
        xSemaphoreTake(uart_rx_ring_mutex_s, portMAX_DELAY);
    }

    size_t offset = 0;
    while (offset < len) {
        if (uart_rx_ring_full()) {
            if (uart_rx_ring_mutex_s != NULL) {
                xSemaphoreGive(uart_rx_ring_mutex_s);
            }
            return false; /* 满，丢包 */
        }

        uint8_t idx = uart_rx_ring_s.write_idx;
        size_t chunk = len - offset;
        if (chunk > UART_RX_SLOT_SIZE) {
            chunk = UART_RX_SLOT_SIZE;
        }

        memcpy(uart_rx_ring_s.data[idx], data + offset, chunk);
        uart_rx_ring_s.len[idx] = (uint16_t)chunk;
        uart_rx_ring_s.write_idx = (idx + 1) % UART_RX_RING_SLOTS;

        offset += chunk;
    }

    if (uart_rx_ring_mutex_s != NULL) {
        xSemaphoreGive(uart_rx_ring_mutex_s);
    }

    /* 通知 worker */
    if (uart_rx_data_sem_s) {
        xSemaphoreGive(uart_rx_data_sem_s);
    }
    return true;
}

static void uart_rx_ring_drain(void)
{
    if (uart_rx_ring_mutex_s != NULL) {
        xSemaphoreTake(uart_rx_ring_mutex_s, portMAX_DELAY);
    }
    uart_rx_ring_s.read_idx = uart_rx_ring_s.write_idx;
    if (uart_rx_ring_mutex_s != NULL) {
        xSemaphoreGive(uart_rx_ring_mutex_s);
    }
}

/** 按槽逐段读出并喂解析器，保持字节流连续、不截断（持锁仅拷贝，解析在锁外） */
static void uart_rx_ring_drain_to_parser(void)
{
    uint8_t local[UART_RX_SLOT_SIZE];

    for (;;) {
        uint16_t n = 0;

        if (uart_rx_ring_mutex_s != NULL) {
            xSemaphoreTake(uart_rx_ring_mutex_s, portMAX_DELAY);
        }
        if (uart_rx_ring_empty()) {
            if (uart_rx_ring_mutex_s != NULL) {
                xSemaphoreGive(uart_rx_ring_mutex_s);
            }
            break;
        }

        uint8_t idx = uart_rx_ring_s.read_idx;
        n = uart_rx_ring_s.len[idx];
        memcpy(local, uart_rx_ring_s.data[idx], n);
        uart_rx_ring_s.read_idx = (idx + 1) % UART_RX_RING_SLOTS;

        if (uart_rx_ring_mutex_s != NULL) {
            xSemaphoreGive(uart_rx_ring_mutex_s);
        }

        link_uart_feed_rx_bytes(local, (int)n);
    }
}

static void uart_rx_worker_task(void *param)
{
    (void)param;
    const uint32_t stack_sz = (uint32_t)(uintptr_t)param;

    ESP_LOGI(tag_s, "UART1 RX 工作任务已启动 (stack=%u, ring=%dx%dB=%dKB)",
             (unsigned)stack_sz, UART_RX_RING_SLOTS, UART_RX_SLOT_SIZE,
             (UART_RX_RING_SLOTS * UART_RX_SLOT_SIZE) / 1024);

    while (1) {
        /* 等待数据信号量，或 10ms 超时轮询 */
        if (uart_rx_data_sem_s) {
            xSemaphoreTake(uart_rx_data_sem_s, pdMS_TO_TICKS(10));
        } else {
            vTaskDelay(pdMS_TO_TICKS(10));
        }

        uart_rx_ring_drain_to_parser();
    }
}

/**
 * @brief 切换 RX worker 栈大小。OTA 期间用大栈(16KB)，平时用小栈(8KB)。
 * @param use_ota_stack true=切换到大栈，false=切换到小栈
 */
static void uart_rx_worker_switch_stack(bool use_ota_stack)
{
    if (uart_rx_worker_mutex_s == NULL) {
        return;
    }

    xSemaphoreTake(uart_rx_worker_mutex_s, portMAX_DELAY);

    if (use_ota_stack == uart_rx_worker_is_ota_stack_s) {
        xSemaphoreGive(uart_rx_worker_mutex_s);
        return; /* 已是目标栈大小 */
    }

    /* 删除旧 worker（保留环形缓冲区内数据，避免切换时丢失 BEGIN/DATA） */
    if (uart_rx_worker_handle_s) {
        vTaskDelete(uart_rx_worker_handle_s);
        uart_rx_worker_handle_s = NULL;
    }

    const uint32_t stack_sz = use_ota_stack ? UART_RX_WORKER_STACK_OTA : UART_RX_WORKER_STACK_NORMAL;
    BaseType_t ret = xTaskCreate(uart_rx_worker_task,
                                 use_ota_stack ? "uart_rx_ota" : "uart_rx_work",
                                 (uint32_t)stack_sz,
                                 (void *)(uintptr_t)stack_sz, /* 传递栈大小用于日志 */
                                 UART_RX_WORKER_PRIO,
                                 &uart_rx_worker_handle_s);
    if (ret != pdPASS) {
        ESP_LOGE(tag_s, "切换 RX worker 栈(%u)失败", (unsigned)stack_sz);
    } else {
        uart_rx_worker_is_ota_stack_s = use_ota_stack;
        ESP_LOGI(tag_s, "RX worker 已切换为 %s 栈(%u)",
                 use_ota_stack ? "OTA(大)" : "NORMAL(小)", (unsigned)stack_sz);
        /* 唤醒新 worker 处理切换前已入队的数据 */
        if (uart_rx_data_sem_s) {
            xSemaphoreGive(uart_rx_data_sem_s);
        }
    }

    xSemaphoreGive(uart_rx_worker_mutex_s);
}

static void uart_dma_rx_cb(const uint8_t *data, size_t len, void *ctx)
{
    (void)ctx;
    if (!data || len == 0) {
        return;
    }
    if (len > 65535U) {
        ESP_LOGW(tag_s, "UART1 RX 单次过长 (%u)，截断", (unsigned)len);
        len = 65535U;
    }

    if (!uart_rx_ring_write(data, len)) {
        ESP_LOGW(tag_s, "UART1 RX 环形缓冲区满，丢弃 %u 字节（OTA 将 NAK 触发重传）", (unsigned)len);
    }
}

static void uart_link_watchdog_task(void *param)
{
    (void)param;
    ESP_LOGI(tag_s, "UART1 DMA RX 监视任务 (port=%d, %d baud, TX=GPIO%d RX=GPIO%d)",
             (int)UART_LINK_PORT, CONFIG_APP_UART_LINK_BAUDRATE,
             CONFIG_APP_UART_LINK_TX_GPIO, CONFIG_APP_UART_LINK_RX_GPIO);

    bool was_ota_mode = false;

    while (1) {
        vTaskDelay(pdMS_TO_TICKS(200));
        uint32_t now = get_current_time_ms();
        uint32_t last_rx = last_peer_rx_ms;
        uint32_t idle_limit_ms = UART_PEER_UNPLUG_MS;
        bool ota_session_reset = false;

        bool in_ota = ota_binary_stream_is_active() || ota_offer_is_armed() || ota_frame_rx_is_active();

        /* 动态栈切换：进入/退出 OTA 时调整 RX worker 栈大小 */
        if (in_ota != was_ota_mode) {
            uart_rx_worker_switch_stack(in_ota);
            was_ota_mode = in_ota;
        }

        if (ota_binary_stream_is_active() || ota_frame_rx_is_active()) {
            idle_limit_ms = ota_uart_tune_transfer_idle_ms(CONFIG_APP_UART_LINK_BAUDRATE);
            ota_session_reset = true;
        } else if (ota_offer_is_armed()) {
            idle_limit_ms = UART_OTA_ARMED_IDLE_MS;
            ota_session_reset = true;
        }

        if (last_rx != 0 && (now - last_rx) > idle_limit_ms) {
            if (link_up_s) {
                link_up_s = false;
                remote_control_stop_notify_end();
                if (ota_session_reset || rx_buf_pos_s > 0) {
                    link_uart_session_reset_ex(ota_session_reset ? "timeout" : NULL);
                    ESP_LOGW(tag_s, "UART1 RX 超时（%lu ms），已清空未完成 OTA/JSON 会话",
                             (unsigned long)idle_limit_ms);
                }
                ESP_LOGI(tag_s, "UART1 对端近期无 RX（%lu ms），停止停车推送",
                         (unsigned long)idle_limit_ms);
            }
        }
    }
}

static bool uart_ota_tx_busy(void)
{
    /* UART 与 OT ACK 共用一线；OTA 期间不发心跳，改发 1002/active 识别 JSON */
    return ota_offer_session_busy();
}

static void uart_send_heartbeat_once(void)
{
    if (!link_uart_has_peer_seen()) {
        return;
    }
    if (uart_ota_tx_busy()) {
        return;
    }

    char devid[32] = {0};
    read_from_nvs(DEVICE_CFG_KEY_DEVICE_ID, devid, sizeof(devid));
    char *heartbeat = heart_payload_json_malloc(devid, NULL, false);
    if (!heartbeat) {
        return;
    }
    (void)link_uart_send_heartbeat(heartbeat);
    free(heartbeat);
}

static void uart_stop_notify_cb(const char *json)
{
    if (json == NULL || !uart_peer_rx_recent()) {
        return;
    }
    (void)uart_link_send_json_line(json);
}

static void uart_heartbeat_task(void *param)
{
    (void)param;
    ESP_LOGI(tag_s, "UART1 心跳任务已启动 (周期 %d ms)", UART_HEART_PERIOD_MS);
    for (uint32_t beat_count = 1;; beat_count++) {
        uart_send_heartbeat_once();
        ESP_LOGD(tag_s, "UART1 心跳 #%lu", (unsigned long)beat_count);
        vTaskDelay(pdMS_TO_TICKS(UART_HEART_PERIOD_MS));
    }
}

static esp_err_t uart_link_init_hardware(void)
{
    int tx_gpio = CONFIG_APP_UART_LINK_TX_GPIO;
    int rx_gpio = CONFIG_APP_UART_LINK_RX_GPIO;

    if (tx_gpio < 0 || rx_gpio < 0) {
        ESP_LOGE(tag_s, "Invalid UART GPIO config: TX=%d, RX=%d", tx_gpio, rx_gpio);
        return ESP_ERR_INVALID_ARG;
    }

    rx_buf_pos_s = 0;

    esp_err_t err = link_dma_uart_start(UART_LINK_PORT, CONFIG_APP_UART_LINK_BAUDRATE,
                                        tx_gpio, rx_gpio, uart_dma_rx_cb, NULL);
    if (err != ESP_OK) {
        ESP_LOGE(tag_s, "UART DMA init failed: %s", esp_err_to_name(err));
        return err;
    }

    ESP_LOGI(tag_s, "UART1 DMA 就绪: UART_NUM_%d TX=GPIO%d RX=GPIO%d %d baud",
             (int)UART_LINK_PORT, tx_gpio, rx_gpio, CONFIG_APP_UART_LINK_BAUDRATE);
    return ESP_OK;
}

esp_err_t link_uart_start(void)
{
    ESP_LOGI(tag_s, "启动 UART 链路 (GPIO%d TX / GPIO%d RX, %d baud)",
             CONFIG_APP_UART_LINK_TX_GPIO, CONFIG_APP_UART_LINK_RX_GPIO,
             CONFIG_APP_UART_LINK_BAUDRATE);

    ota_offer_reset_boot();
    uart_ota_framed_mode_s = false;
    ota_offer_set_done_callback(uart_ota_done_report);
    remote_control_set_stop_notify_cb(uart_stop_notify_cb);
    ota_frame_protocol_init(uart_ota_tx_frame, NULL);

    /* 初始化 UART OTA 模块 */
    uart_ota_init();

    /* 初始化环形缓冲区 */
    uart_rx_ring_init();

    uart_rx_ring_mutex_s = xSemaphoreCreateMutex();
    if (uart_rx_ring_mutex_s == NULL) {
        ESP_LOGE(tag_s, "UART RX ring mutex create failed");
        return ESP_ERR_NO_MEM;
    }

    /* 创建数据可用信号量（二值信号量，非计数） */
    uart_rx_data_sem_s = xSemaphoreCreateBinary();
    if (uart_rx_data_sem_s == NULL) {
        ESP_LOGE(tag_s, "UART RX data sem create failed");
        vSemaphoreDelete(uart_rx_ring_mutex_s);
        uart_rx_ring_mutex_s = NULL;
        return ESP_ERR_NO_MEM;
    }

    uart_rx_worker_mutex_s = xSemaphoreCreateMutex();
    if (uart_rx_worker_mutex_s == NULL) {
        ESP_LOGE(tag_s, "UART RX worker mutex create failed");
        vSemaphoreDelete(uart_rx_data_sem_s);
        uart_rx_data_sem_s = NULL;
        vSemaphoreDelete(uart_rx_ring_mutex_s);
        uart_rx_ring_mutex_s = NULL;
        return ESP_ERR_NO_MEM;
    }

    /* 初始创建小栈(8KB)worker，OTA期间自动切换大栈(16KB) */
    BaseType_t worker_ok = xTaskCreate(uart_rx_worker_task, "uart_rx_work",
                                       UART_RX_WORKER_STACK_NORMAL,
                                       (void *)(uintptr_t)UART_RX_WORKER_STACK_NORMAL,
                                       UART_RX_WORKER_PRIO, &uart_rx_worker_handle_s);
    if (worker_ok != pdPASS) {
        ESP_LOGE(tag_s, "UART RX worker task create failed");
        vSemaphoreDelete(uart_rx_worker_mutex_s);
        uart_rx_worker_mutex_s = NULL;
        vSemaphoreDelete(uart_rx_data_sem_s);
        uart_rx_data_sem_s = NULL;
        return ESP_ERR_NO_MEM;
    }
    uart_rx_worker_is_ota_stack_s = false;

    /* 初始化 UART 硬件 */
    esp_err_t err = uart_link_init_hardware();
    if (err != ESP_OK) {
        if (uart_rx_worker_handle_s) {
            vTaskDelete(uart_rx_worker_handle_s);
            uart_rx_worker_handle_s = NULL;
        }
        if (uart_rx_worker_mutex_s) {
            vSemaphoreDelete(uart_rx_worker_mutex_s);
            uart_rx_worker_mutex_s = NULL;
        }
        if (uart_rx_data_sem_s) {
            vSemaphoreDelete(uart_rx_data_sem_s);
            uart_rx_data_sem_s = NULL;
        }
        if (uart_rx_worker_mutex_s) {
            vSemaphoreDelete(uart_rx_worker_mutex_s);
            uart_rx_worker_mutex_s = NULL;
        }
        return err;
    }

    /* 创建发送互斥锁 */
    tx_mutex_s = xSemaphoreCreateMutex();
    if (!tx_mutex_s) {
        ESP_LOGE(tag_s, "TX mutex create failed");
        link_dma_uart_stop();
        if (uart_rx_worker_handle_s) {
            vTaskDelete(uart_rx_worker_handle_s);
            uart_rx_worker_handle_s = NULL;
        }
        if (uart_rx_worker_mutex_s) {
            vSemaphoreDelete(uart_rx_worker_mutex_s);
            uart_rx_worker_mutex_s = NULL;
        }
        if (uart_rx_data_sem_s) {
            vSemaphoreDelete(uart_rx_data_sem_s);
            uart_rx_data_sem_s = NULL;
        }
        return ESP_ERR_NO_MEM;
    }

    /* 启动遥控看门狗（与 BLE 模式相同） */
    remote_control_watchdog_start();

    /* DMA 接收由 link_dma_uart 驱动；独立任务仅做对端离线检测 */
    BaseType_t ret = xTaskCreate(uart_link_watchdog_task, "uart_wd",
                                 3072, NULL, 5, &rx_task_handle_s);
    if (ret != pdPASS) {
        ESP_LOGE(tag_s, "UART watchdog task create failed");
        vSemaphoreDelete(tx_mutex_s);
        tx_mutex_s = NULL;
        link_dma_uart_stop();
        if (uart_rx_worker_handle_s) {
            vTaskDelete(uart_rx_worker_handle_s);
            uart_rx_worker_handle_s = NULL;
        }
        if (uart_rx_worker_mutex_s) {
            vSemaphoreDelete(uart_rx_worker_mutex_s);
            uart_rx_worker_mutex_s = NULL;
        }
        if (uart_rx_data_sem_s) {
            vSemaphoreDelete(uart_rx_data_sem_s);
            uart_rx_data_sem_s = NULL;
        }
        return ESP_ERR_NO_MEM;
    }

    /* 启动心跳任务 */
    ret = xTaskCreate(uart_heartbeat_task, "uart_hb",
                      4096, NULL, 5, &hb_task_handle_s);
    if (ret != pdPASS) {
        ESP_LOGE(tag_s, "Heartbeat task create failed");
        vTaskDelete(rx_task_handle_s);
        rx_task_handle_s = NULL;
        vSemaphoreDelete(tx_mutex_s);
        tx_mutex_s = NULL;
        link_dma_uart_stop();
        if (uart_rx_worker_handle_s) {
            vTaskDelete(uart_rx_worker_handle_s);
            uart_rx_worker_handle_s = NULL;
        }
        if (uart_rx_worker_mutex_s) {
            vSemaphoreDelete(uart_rx_worker_mutex_s);
            uart_rx_worker_mutex_s = NULL;
        }
        if (uart_rx_data_sem_s) {
            vSemaphoreDelete(uart_rx_data_sem_s);
            uart_rx_data_sem_s = NULL;
        }
        return ESP_ERR_NO_MEM;
    }

    link_up_s = false;
    last_peer_rx_ms = 0;

    ESP_LOGI(tag_s, "UART 链路启动成功 (事件驱动收发；无新日志=无收发)");
    ESP_LOGI(tag_s, "握手: 设备不主动发 1002；须手机经 UART1 发 message_type=6 后才回 1002/query");
#if BUILD_IS_DEBUG
    ESP_LOGI(tag_s, "Debug: UART1 收发 JSON/二进制均有 I 级日志 (监视器 COM=UART0，数据口=GPIO17/18)");
#endif
    ESP_LOGI(tag_s, "串口工具应接 UART1: 手机_TX->ESP_GPIO%d(RX), 手机_RX<-ESP_GPIO%d(TX), %d baud",
             CONFIG_APP_UART_LINK_RX_GPIO, CONFIG_APP_UART_LINK_TX_GPIO,
             CONFIG_APP_UART_LINK_BAUDRATE);
    ESP_LOGI(tag_s, "手机发 link_ready(6) 后设备回 OTA 询问(1002)；手机回 0 后发 OT 帧固件");
#if BUILD_IS_RELEASE
    uart_log_hook_install_if_needed();
    ESP_LOGI(tag_s, "Release: ESP_LOGW/ESP_LOGE 经 UART1 推送 message_type=4/5 JSON");
#endif
    return ESP_OK;
}

void link_uart_stop(void)
{
    link_dma_uart_stop();

    if (uart_rx_worker_handle_s) {
        vTaskDelete(uart_rx_worker_handle_s);
        uart_rx_worker_handle_s = NULL;
    }
    uart_rx_ring_drain();
    if (uart_rx_data_sem_s) {
        vSemaphoreDelete(uart_rx_data_sem_s);
        uart_rx_data_sem_s = NULL;
    }
    if (uart_rx_ring_mutex_s) {
        vSemaphoreDelete(uart_rx_ring_mutex_s);
        uart_rx_ring_mutex_s = NULL;
    }
    if (uart_rx_worker_mutex_s) {
        vSemaphoreDelete(uart_rx_worker_mutex_s);
        uart_rx_worker_mutex_s = NULL;
    }

    /* 停止心跳任务 */
    if (hb_task_handle_s) {
        vTaskDelete(hb_task_handle_s);
        hb_task_handle_s = NULL;
    }

    /* 停止接收任务 */
    if (rx_task_handle_s) {
        vTaskDelete(rx_task_handle_s);
        rx_task_handle_s = NULL;
    }

    /* 停止遥控看门狗 */
    remote_control_watchdog_stop();

    /* 删除互斥锁 */
    if (tx_mutex_s) {
        vSemaphoreDelete(tx_mutex_s);
        tx_mutex_s = NULL;
    }

    link_up_s = false;

    ESP_LOGI(tag_s, "UART 链路已停止");
}
