#include "loadbalancer.h"
#include "gridmeter.h"
#include "evsemeter.h"
#include "evse_api.h"
#include "esp_event.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "input_filter.h"
#include <string.h> // Para memcpy

static const char *TAG = "loadbalancer";

static float grid_current = 0.0f;
static float evse_current = 0.0f;
static float max_grid_current = 32.0f; // Amperes

#define MIN_EVSE_CURRENT 6.0f

// Filtros exponenciais para suavizar leituras
static input_filter_t grid_filter;
static input_filter_t evse_filter;

static void grid_event_handler(void *arg, esp_event_base_t base, int32_t id, void *data)
{
    if (id == GRIDMETER_EVENT_UPDATE && data)
    {
        float raw;
        memcpy(&raw, data, sizeof(float));
        grid_current = input_filter_update(&grid_filter, raw);
        ESP_LOGD(TAG, "Grid current (filtered): %.2f A", grid_current);
    }
}

static void evse_event_handler(void *arg, esp_event_base_t base, int32_t id, void *data)
{
    if (id == EVSEMETER_EVENT_UPDATE && data)
    {
        float raw;
        memcpy(&raw, data, sizeof(float));
        evse_current = input_filter_update(&evse_filter, raw);
        ESP_LOGD(TAG, "EVSE current (filtered): %.2f A", evse_current);
    }
}

void loadbalancer_init(void)
{
    ESP_LOGI(TAG, "Initializing load balancer");

    input_filter_init(&grid_filter, 0.3f);
    input_filter_init(&evse_filter, 0.3f);

    if (esp_event_handler_register(GRIDMETER_EVENT, GRIDMETER_EVENT_UPDATE,
                                   grid_event_handler, NULL) != ESP_OK) {
        ESP_LOGE(TAG, "Failed to register gridmeter event handler");
    }

    if (esp_event_handler_register(EVSEMETER_EVENT, EVSEMETER_EVENT_UPDATE,
                                   evse_event_handler, NULL) != ESP_OK) {
        ESP_LOGE(TAG, "Failed to register evsemeter event handler");
    }

    if (xTaskCreate(loadbalancer_task, "loadbalancer", 4096, NULL, 5, NULL) != pdPASS) {
        ESP_LOGE(TAG, "Failed to create loadbalancer task");
    }
}

void loadbalancer_task(void *param)
{
    while (true)
    {
        float available = max_grid_current - grid_current + evse_current;

        // Restrição de corrente mínima e máxima
        if (available < MIN_EVSE_CURRENT) {
            available = 0.0f;
        } else if (available > max_grid_current) {
            available = max_grid_current;
        }

        ESP_LOGI(TAG, "Setting EVSE current limit: %.1f A", available);
        evse_set_charging_current((uint16_t)available);

        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void setMaxGridCurrent(int value)
{
    max_grid_current = value / 10.0f;
}

void setLiveGridCurrent(int value)
{
    float raw = value / 10.0f;
    grid_current = input_filter_update(&grid_filter, raw);
}

void setLiveVolt(int value)
{
    (void)value; // reservado para uso futuro
}
