#include "led_driver.h"
#include "driver/rmt_tx.h"
#include "led_strip_encoder.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_random.h"
#include <string.h>
#include "esp_rom_sys.h"

static const char *TAG = "LED";
static bool led_ready = false;                     // 🚦 flag de inicialização
static rmt_channel_handle_t led_chan = NULL;
static rmt_encoder_handle_t led_enc = NULL;
static uint8_t led_pixels[LED_COUNT * 3];

// --- Conversão HSV → RGB ---
static void hsv2rgb(uint32_t h, uint32_t s, uint32_t v,
                    uint8_t *r, uint8_t *g, uint8_t *b)
{
    h %= 360;
    uint32_t rgb_max = v * 255 / 100;
    uint32_t rgb_min = rgb_max * (100 - s) / 100;
    uint32_t i = h / 60, diff = h % 60;
    uint32_t adj = (rgb_max - rgb_min) * diff / 60;

    switch (i) {
        case 0: *r = rgb_max; *g = rgb_min + adj; *b = rgb_min; break;
        case 1: *r = rgb_max - adj; *g = rgb_max; *b = rgb_min; break;
        case 2: *r = rgb_min; *g = rgb_max; *b = rgb_min + adj; break;
        case 3: *r = rgb_min; *g = rgb_max - adj; *b = rgb_max; break;
        case 4: *r = rgb_min + adj; *g = rgb_min; *b = rgb_max; break;
        default:*r = rgb_max; *g = rgb_min; *b = rgb_max - adj; break;
    }
}

// --- Inicialização ---
esp_err_t led_init(void)
{
    ESP_LOGI(TAG, "Inicializando LEDs no GPIO%d (%d LEDs)", LED_PIN, LED_COUNT);

    rmt_tx_channel_config_t tx_cfg = {
        .gpio_num = LED_PIN,
        .clk_src = RMT_CLK_SRC_DEFAULT,
        .mem_block_symbols = 64,
        .resolution_hz = LED_RES_HZ,
        .trans_queue_depth = 4,
    };
    ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_cfg, &led_chan));

    led_strip_encoder_config_t enc_cfg = {.resolution = LED_RES_HZ};
    ESP_ERROR_CHECK(rmt_new_led_strip_encoder(&enc_cfg, &led_enc));
    ESP_ERROR_CHECK(rmt_enable(led_chan));

    memset(led_pixels, 0, sizeof(led_pixels));

    led_ready = true;              // ✅ marca como pronto
    led_show();                    // apaga tudo ao iniciar
    return ESP_OK;
}

// --- Apagar todos os LEDs ---
esp_err_t led_clear(void)
{
    if (!led_ready) return ESP_ERR_INVALID_STATE;
    memset(led_pixels, 0, sizeof(led_pixels));
    return led_show();
}

// --- Definir cor individual ---
esp_err_t led_set(uint16_t index, uint8_t r, uint8_t g, uint8_t b)
{
    if (index >= LED_COUNT) return ESP_ERR_INVALID_ARG;
    led_pixels[index * 3 + 0] = g;  // WS2812 usa ordem GRB
    led_pixels[index * 3 + 1] = r;
    led_pixels[index * 3 + 2] = b;
    return ESP_OK;
}

// --- Enviar buffer para o anel ---
esp_err_t led_show(void)
{
    if (!led_ready || !led_chan || !led_enc) {
        ESP_LOGW(TAG, "⚠️ led_show() chamado antes da inicialização — ignorado");
        return ESP_ERR_INVALID_STATE;
    }

    rmt_transmit_config_t tx_cfg = {.loop_count = 0};
    esp_err_t err = rmt_transmit(led_chan, led_enc,
                                 led_pixels, sizeof(led_pixels), &tx_cfg);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "❌ rmt_transmit falhou (%s)", esp_err_to_name(err));
        return err;
    }

    err = rmt_tx_wait_all_done(led_chan, portMAX_DELAY);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "❌ rmt_tx_wait_all_done falhou (%s)", esp_err_to_name(err));
        return err;
    }
    return ESP_OK;
}
// --- Animação de rotação até posição alvo ---
void led_spin_to(uint16_t target, uint16_t rounds, uint16_t delay_start, uint16_t delay_end)
{
    if (!led_ready) return;

    uint32_t total_steps = rounds * LED_COUNT + target;
    for (uint32_t i = 0; i < total_steps; i++) {
        uint16_t pos = i % LED_COUNT;

        // Limpa e acende o LED atual
        led_clear();
        led_set(pos, 255, 150, 0);
        led_show();

        // Calcula delay progressivo (aceleração -> desaceleração)
        uint32_t delay = delay_start + ((delay_end - delay_start) * i) / total_steps;
        vTaskDelay(pdMS_TO_TICKS(delay));
    }

    // Flash final
    for (int j = 0; j < 3; j++) {
        led_clear();
        led_show();
        vTaskDelay(pdMS_TO_TICKS(80));
        for (int k = 0; k < LED_COUNT; k++)
            led_set(k, 255, 200, 50);
        led_show();
        vTaskDelay(pdMS_TO_TICKS(80));
    }
}

// --- Animação idle (arco-íris lento) ---
void led_idle_animation(void)
{
    if (!led_ready) return;

    static uint16_t hue = 0;
    for (int i = 0; i < LED_COUNT; i++) {
        uint8_t r, g, b;
        hsv2rgb((hue + i * 6) % 360, 100, 10, &r, &g, &b);
        led_set(i, r, g, b);
    }
    led_show();
    hue = (hue + 2) % 360;
}
