/*
 * turn_client.c — NPC gateway client for /v1/voice/turn.
 *
 * Uses esp_http_client open/write/fetch/read streaming so the binary WAV
 * body can be written directly to SPIFFS without a large heap buffer.
 *
 * Pattern mirrors hook_client.c but synchronous (called from conv_task).
 * Timeout is generous (30 s) because TTS synthesis adds latency.
 */

#include "turn_client.h"

#include "sdkconfig.h"

#include <stdio.h>
#include <string.h>

#include "esp_http_client.h"
#include "esp_log.h"

#define TAG "turn_client"

/* WAV header is 44 bytes; anything shorter is certainly not a valid response. */
#define MIN_WAV_BYTES 44

/* Read chunks when streaming the response body. */
#define CHUNK_SIZE    1024

/* Timeout for the full TTS round-trip (connect + synthesis + transfer). */
#define TIMEOUT_MS    30000

bool turn_client_greeting(const char *session_id,
                           const char *number,
                           const char *out_path)
{
    /* --- Build URL -------------------------------------------------------- */
    char url[256];
    snprintf(url, sizeof(url), "%s/v1/voice/turn",
             CONFIG_PLIP_GATEWAY_URL);

    /* --- Build JSON body -------------------------------------------------- */
    char body[256];
    int body_len = snprintf(body, sizeof(body),
        "{\"session_id\":\"%s\",\"number\":\"%s\",\"kind\":\"greeting\"}",
        session_id ? session_id : "",
        number     ? number     : "");

    /* --- Configure client ------------------------------------------------- */
    esp_http_client_config_t cfg = {
        .url        = url,
        .method     = HTTP_METHOD_POST,
        .timeout_ms = TIMEOUT_MS,
    };
    esp_http_client_handle_t client = esp_http_client_init(&cfg);
    if (!client) {
        ESP_LOGE(TAG, "esp_http_client_init failed");
        return false;
    }

    esp_http_client_set_header(client, "Content-Type", "application/json");

    /* Authorization header — skip if token is empty */
    const char *token = CONFIG_PLIP_GATEWAY_TOKEN;
    if (token && token[0] != '\0') {
        char auth[128];
        snprintf(auth, sizeof(auth), "Bearer %s", token);
        esp_http_client_set_header(client, "Authorization", auth);
    }

    /* --- Open connection and write body (streaming POST) ------------------ */
    esp_err_t err = esp_http_client_open(client, body_len);
    if (err != ESP_OK) {
        ESP_LOGW(TAG, "open %s failed: %s", url, esp_err_to_name(err));
        esp_http_client_cleanup(client);
        return false;
    }

    int written = esp_http_client_write(client, body, body_len);
    if (written < 0) {
        ESP_LOGW(TAG, "write body failed (written=%d)", written);
        esp_http_client_close(client);
        esp_http_client_cleanup(client);
        return false;
    }

    /* --- Fetch response headers ------------------------------------------ */
    int content_len = esp_http_client_fetch_headers(client);
    int status_code = esp_http_client_get_status_code(client);

    if (status_code != 200) {
        ESP_LOGW(TAG, "gateway returned HTTP %d (url=%s)", status_code, url);
        esp_http_client_close(client);
        esp_http_client_cleanup(client);
        return false;
    }

    ESP_LOGI(TAG, "HTTP 200 from %s (content_length=%d)", url, content_len);

    /* --- Stream binary body into SPIFFS file ------------------------------ */
    FILE *fp = fopen(out_path, "wb");
    if (!fp) {
        ESP_LOGE(TAG, "fopen(%s, wb) failed", out_path);
        esp_http_client_close(client);
        esp_http_client_cleanup(client);
        return false;
    }

    static uint8_t s_chunk[CHUNK_SIZE];   /* static: avoids stack pressure */
    int total = 0;
    int rd;
    while ((rd = esp_http_client_read(client, (char *)s_chunk, sizeof(s_chunk))) > 0) {
        size_t fw = fwrite(s_chunk, 1, (size_t)rd, fp);
        if ((int)fw != rd) {
            ESP_LOGW(TAG, "fwrite short: wrote %d of %d bytes", (int)fw, rd);
            break;
        }
        total += rd;
    }

    fclose(fp);
    esp_http_client_close(client);
    esp_http_client_cleanup(client);

    if (total <= MIN_WAV_BYTES) {
        ESP_LOGW(TAG, "greeting WAV too short (%d bytes) — ignoring", total);
        return false;
    }

    ESP_LOGI(TAG, "greeting WAV %d bytes written to %s", total, out_path);
    return true;
}
