#include "sdkconfig.h"
#include "remote_control.h"
#include "rc_pwm_control.h"
#include "task_manager.h"
#if CONFIG_APP_LINK_WIFI
#include "ota.h"
#endif
#include "cJSON.h"
#include "esp_log.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

static const char *tag_s = "REMOTE_CTRL";

/* 超时保护：500ms 未收到命令则自动停止 */
#define RC_CMD_TIMEOUT_MS    500
#define RC_WATCHDOG_PERIOD_MS 100  /* 检查周期 100ms */

static volatile uint32_t s_last_cmd_time_ms = 0;
static volatile bool s_watchdog_running = false;
static TaskHandle_t s_watchdog_handle = NULL;

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

static void rc_watchdog_task(void *param)
{
    (void)param;
    s_watchdog_running = true;
    
    while (s_watchdog_running) {
        vTaskDelay(pdMS_TO_TICKS(RC_WATCHDOG_PERIOD_MS));
        
        uint32_t now = get_current_time_ms();
        uint32_t last = s_last_cmd_time_ms;
        
        /* 如果已经初始化过且超过 500ms 未收到命令 */
        if (last != 0 && (now - last) > RC_CMD_TIMEOUT_MS) {
            rc_vehicle_stop();
            ESP_LOGW(tag_s, "RC timeout: no cmd for %d ms, vehicle stopped", (int)(now - last));
            /* 重置时间戳，避免重复停止 */
            s_last_cmd_time_ms = now;
        }
    }
    
    s_watchdog_handle = NULL;
    vTaskDelete(NULL);
}

esp_err_t remote_control_watchdog_start(void)
{
    if (s_watchdog_handle != NULL) {
        return ESP_OK;  /* 已经在运行 */
    }
    
    s_last_cmd_time_ms = get_current_time_ms();  /* 初始化时间戳 */
    
    return app_task_start(APP_TASK_RC_WATCHDOG, rc_watchdog_task, NULL, &s_watchdog_handle);
}

void remote_control_watchdog_stop(void)
{
    s_watchdog_running = false;
    /* task 会自行删除，句柄会在任务函数中设为 NULL */
}

static void update_last_cmd_time(void)
{
    s_last_cmd_time_ms = get_current_time_ms();
}

void remote_control_apply_json(const char *json)
{
    /* 更新上次接收命令的时间戳 */
    update_last_cmd_time();
    
    if (!json) {
        return;
    }

    cJSON *root = cJSON_Parse(json);
    if (!root) {
        return;
    }

    cJSON *head = cJSON_GetObjectItem(root, "head");
    if (!head || !cJSON_IsObject(head)) {
#if CONFIG_APP_LINK_WIFI
        /* 仅 WiFi+MQTT 构建：云端 JSON 触发 HTTPS OTA */
        ota_update_recmqtt(json);
#endif
        cJSON_Delete(root);
        return;
    }

    cJSON *m_type = cJSON_GetObjectItem(head, "message_type");
    if (m_type && cJSON_IsNumber(m_type) && m_type->valueint == 1) {
        ESP_LOGW(tag_s, "message_type=1: reboot (all devices)");
        cJSON_Delete(root);
        esp_restart();
        return;
    }

    cJSON *body = cJSON_GetObjectItem(root, "body");
    if (m_type && cJSON_IsNumber(m_type) && body) {
        if (m_type->valueint == 4) {
            cJSON *pin_ctrl = cJSON_GetObjectItem(body, "pin_setctrl");
            if (pin_ctrl && cJSON_IsObject(pin_ctrl)) {
                cJSON *jp = cJSON_GetObjectItem(pin_ctrl, "pin");
                cJSON *jv = cJSON_GetObjectItem(pin_ctrl, "val");
                if (jp && jv && cJSON_IsNumber(jp) && cJSON_IsNumber(jv)) {
                    int pin = jp->valueint;
                    int val = jv->valueint;
                    ESP_LOGI(tag_s, "GPIO: pin %d -> %d", pin, val);
                    rc_vehicle_shot(pin, val);
                }
            }
        } else if (m_type->valueint == 3) {
            cJSON *pwm_ctrl = cJSON_GetObjectItem(body, "pwm_ctrl");
            if (pwm_ctrl && cJSON_IsObject(pwm_ctrl)) {
                cJSON *jm = cJSON_GetObjectItem(pwm_ctrl, "mode");
                cJSON *jt = cJSON_GetObjectItem(pwm_ctrl, "type");
                cJSON *jv = cJSON_GetObjectItem(pwm_ctrl, "val");
                if (jm && jv && cJSON_IsNumber(jm) && cJSON_IsNumber(jv)) {
                    int mode = jm->valueint;
                    int type = jt && cJSON_IsNumber(jt) ? jt->valueint : 0;
                    int val = jv->valueint;
                    ESP_LOGI(tag_s, "PWM: mode %d type %d val %d", mode, type, val);
                    rc_vehicle_control(mode, val);
                }
            }
        }
    }

    cJSON_Delete(root);
}
