#include "evse_manager.h"
#include "evse_state.h"
#include "evse_error.h"
#include "evse_hardware.h"
#include "evse_config.h"
#include "evse_api.h"
#include "evse_meter.h"
#include "evse_session.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include <string.h>

#include "auth_events.h"
#include "loadbalancer_events.h"
#include "esp_event.h"

static const char *TAG = "EVSE_Manager";

static SemaphoreHandle_t evse_mutex;
static bool auth_enabled = false;

#define EVSE_MANAGER_TICK_PERIOD_MS 1000  // 1 segundo

// ===== Task de ciclo principal =====
static void evse_manager_task(void *arg) {
    while (true) {
        evse_manager_tick();
        vTaskDelay(pdMS_TO_TICKS(EVSE_MANAGER_TICK_PERIOD_MS));
    }
}

// ===== Tratador de eventos de autenticação =====
static void on_auth_event(void* arg, esp_event_base_t base, int32_t id, void* data) {
    if (base != AUTH_EVENTS || data == NULL) return;

    switch (id) {
        case AUTH_EVENT_TAG_PROCESSED: {
            auth_tag_event_data_t *evt = (auth_tag_event_data_t*)data;
            ESP_LOGI("EVSE", "Tag: %s | Autorizada: %s", evt->tag, evt->authorized ? "SIM" : "NÃO");
            evse_state_set_authorized(evt->authorized);
            break;
        }

        case AUTH_EVENT_ENABLED_CHANGED:
        case AUTH_EVENT_INIT: {
            auth_enabled_event_data_t *evt = (auth_enabled_event_data_t*)data;
            auth_enabled = evt->enabled;

            ESP_LOGI("EVSE", "Auth %s (%s)", 
                id == AUTH_EVENT_ENABLED_CHANGED ? "ficou" : "init", 
                evt->enabled ? "ATIVO" : "INATIVO");

            if (!auth_enabled) {
                evse_state_set_authorized(true);
                ESP_LOGI("EVSE", "Autenticação desativada → autorização forçada.");
            } else {
                evse_state_set_authorized(false);
                ESP_LOGI("EVSE", "Autenticação ativada → aguardando autorização por tag.");
            }
            break;
        }
    }
}

// ===== Tratador de eventos de loadbalancer =====
static void on_loadbalancer_event(void* handler_arg, esp_event_base_t event_base,
                                  int32_t event_id, void* event_data) {
    if (event_id == LOADBALANCER_EVENT_INIT || event_id == LOADBALANCER_EVENT_STATE_CHANGED) {
        const loadbalancer_state_event_t* evt = (const loadbalancer_state_event_t*) event_data;
        ESP_LOGI(TAG, "Loadbalancer %s (ts: %lld)",
                 evt->enabled ? "ENABLED" : "DISABLED", evt->timestamp_us);
        // Ações adicionais podem ser adicionadas aqui conforme necessário
    } else if (event_id == LOADBALANCER_EVENT_CHARGING_LIMIT_CHANGED) {
        const loadbalancer_charging_limit_event_t* evt = (const loadbalancer_charging_limit_event_t*) event_data;
        ESP_LOGD(TAG, "Novo limite de corrente: %.1f A (ts: %lld)", evt->limit, evt->timestamp_us);
        evse_set_runtime_charging_current((uint16_t)(evt->limit));
    }
}

// ===== Inicialização =====
void evse_manager_init(void) {
    evse_mutex = xSemaphoreCreateMutex();

    evse_config_init();
    evse_error_init();
    evse_hardware_init();
    evse_state_init();
    evse_meter_init();
    evse_session_init();

    ESP_ERROR_CHECK(esp_event_handler_register(AUTH_EVENTS, ESP_EVENT_ANY_ID, &on_auth_event, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(LOADBALANCER_EVENTS, ESP_EVENT_ANY_ID, &on_loadbalancer_event, NULL));

    ESP_LOGI(TAG, "EVSE Manager inicializado.");
    xTaskCreate(evse_manager_task, "evse_manager_task", 4096, NULL, 5, NULL);
}

// ===== Main Tick =====
void evse_manager_tick(void) {
    xSemaphoreTake(evse_mutex, portMAX_DELAY);

    evse_hardware_tick();
    evse_error_tick();
    evse_state_tick();
    evse_temperature_check();
    evse_session_tick();

    if (auth_enabled) {
        // If the car is disconnected, revoke authorization
        if (evse_state_get_authorized() && evse_get_state() == EVSE_STATE_A) {
            ESP_LOGI(TAG, "Vehicle disconnected → revoking authorization.");
            evse_state_set_authorized(false);
        }
    } else {
        // If authentication is disabled, ensure authorization is always granted
        if (!evse_state_get_authorized()) {
            evse_state_set_authorized(true);
            ESP_LOGI(TAG, "Authentication disabled → forced authorization.");
        }
    }

    xSemaphoreGive(evse_mutex);
}
