/*
 * cmd_exec.c — PLIP voice CMD executor (D5 contract, adapted from box3_voice).
 *
 * The PLIP has no display; screen/evt/led ops are logged and ignored.
 * play → audio_play_async(path).
 */

#include "cmd_exec.h"
#include "audio.h"

#include <string.h>

#include "cJSON.h"
#include "esp_log.h"

#define TAG "cmd_exec"

static esp_err_t exec_play(const cJSON *a)
{
    const cJSON *path_j = a ? cJSON_GetObjectItemCaseSensitive(a, "p") : NULL;
    const char *path = cJSON_IsString(path_j) ? path_j->valuestring : "embedded://";

    ESP_LOGI(TAG, "CMD op=play path=\"%s\"", path);
    return audio_play_async(path);
}

static esp_err_t exec_screen(const cJSON *a)
{
    const cJSON *t_j = a ? cJSON_GetObjectItemCaseSensitive(a, "t") : NULL;
    ESP_LOGI(TAG, "CMD op=screen t=\"%s\" (no display on PLIP — ignored)",
             cJSON_IsString(t_j) ? t_j->valuestring : "");
    return ESP_OK;
}

static esp_err_t exec_evt(const cJSON *a)
{
    const cJSON *n_j = a ? cJSON_GetObjectItemCaseSensitive(a, "n") : NULL;
    ESP_LOGI(TAG, "CMD op=evt n=\"%s\"",
             cJSON_IsString(n_j) ? n_j->valuestring : "<none>");
    return ESP_OK;
}

static esp_err_t exec_led(const cJSON *a)
{
    const cJSON *p_j = a ? cJSON_GetObjectItemCaseSensitive(a, "p") : NULL;
    ESP_LOGI(TAG, "CMD op=led pattern=\"%s\" (no LED — ignored)",
             cJSON_IsString(p_j) ? p_j->valuestring : "<none>");
    return ESP_OK;
}

esp_err_t cmd_exec_handle(const char *data, size_t len)
{
    if (!data || len == 0) return ESP_ERR_INVALID_ARG;

    cJSON *root = cJSON_ParseWithLength(data, len);
    if (!root) {
        ESP_LOGW(TAG, "CMD parse error: not valid JSON (%.40s)", data);
        return ESP_ERR_INVALID_ARG;
    }

    const cJSON *op_j = cJSON_GetObjectItemCaseSensitive(root, "op");
    if (!cJSON_IsString(op_j) || !op_j->valuestring || !op_j->valuestring[0]) {
        ESP_LOGW(TAG, "CMD missing/invalid 'op' field");
        cJSON_Delete(root);
        return ESP_ERR_INVALID_ARG;
    }

    const char  *op = op_j->valuestring;
    const cJSON *a  = cJSON_GetObjectItemCaseSensitive(root, "a");

    esp_err_t err;
    if (strcmp(op, "play") == 0) {
        err = exec_play(a);
    } else if (strcmp(op, "screen") == 0) {
        err = exec_screen(a);
    } else if (strcmp(op, "evt") == 0) {
        err = exec_evt(a);
    } else if (strcmp(op, "led") == 0) {
        err = exec_led(a);
    } else {
        ESP_LOGW(TAG, "CMD op=\"%s\" unknown — ignored", op);
        err = ESP_ERR_NOT_SUPPORTED;
    }

    cJSON_Delete(root);
    return err;
}
