// evse_core.c - Função principal de controle do EVSE

#include "evse_fsm.h"
#include "evse_error.h"
#include "evse_limits.h"
#include "evse_config.h"
#include "evse_api.h"
#include "pilot.h"
#include "energy_meter.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "esp_log.h"

static const char *TAG = "evse_core";

static SemaphoreHandle_t mutex;

static evse_state_t last_state = EVSE_STATE_A;
static bool authorized = false;
static TickType_t auth_grant_to = 0;

static void evse_core_task(void *arg);

void evse_init(void) {
    ESP_LOGI(TAG, "EVSE Init");

    mutex = xSemaphoreCreateMutex();

    evse_check_defaults();
    evse_fsm_reset();
    pilot_set_level(true);  // Estado inicial do piloto

    xTaskCreate(evse_core_task, "evse_core_task", 4096, NULL, 5, NULL);
}

void evse_process(void) {
    xSemaphoreTake(mutex, portMAX_DELAY);

    pilot_voltage_t pilot_voltage;
    bool is_n12v = false;

    pilot_measure(&pilot_voltage, &is_n12v);
    ESP_LOGD(TAG, "Pilot: %d, -12V: %s", pilot_voltage, is_n12v ? "yes" : "no");

    evse_error_check(pilot_voltage, is_n12v);

    if (evse_get_error() == 0 && !evse_is_error_cleared()) {

        bool authorized = evse_state_get_authorized();

        evse_fsm_process(
            pilot_voltage,
            authorized,
            evse_config_is_available(),
            evse_config_is_enabled()
        );

        evse_limits_check(evse_get_state());

        evse_state_t current = evse_get_state();
        if (current != last_state) {
            ESP_LOGI(TAG, "State changed: %s → %s", evse_state_to_str(last_state), evse_state_to_str(current));
            last_state = current;
        }
    }

    if (evse_get_error() == 0) {
        evse_mark_error_cleared();
    }

    xSemaphoreGive(mutex);

    energy_meter_process(
        evse_state_is_charging(evse_get_state()),
        evse_get_charging_current()
    );
}

// ================================
// Interface pública
// ================================

bool evse_is_enabled(void) {
    return evse_config_is_enabled();
}

void evse_set_enabled(bool value) {
    ESP_LOGI(TAG, "Set enabled %d", value);
    evse_config_set_enabled(value);
}

bool evse_is_available(void) {
    return evse_config_is_available();
}

void evse_set_available(bool value) {
    ESP_LOGI(TAG, "Set available %d", value);
    evse_config_set_available(value);
}

bool evse_is_pending_auth(void) {
    return evse_state_is_session(evse_get_state()) && !authorized;
}

void evse_authorize(void) {
    ESP_LOGI(TAG, "Authorize");
    evse_state_set_authorized(true);
}

void evse_set_authorized(bool value) {
    ESP_LOGI(TAG, "Set authorized %d", value);
    xSemaphoreTake(mutex, portMAX_DELAY);
    authorized = value;
    xSemaphoreGive(mutex);
}

// ================================
// Tarefa principal
// ================================

static void evse_core_task(void *arg) {
    while (true) {
        evse_process();
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}
