#include "loadbalancing_settings_api.h"
#include "loadbalancer.h"
#include "esp_log.h"
#include "cJSON.h"

static const char *TAG = "loadbalancing_settings_api";

// GET Handler: Retorna configurações atuais de load balancing
static esp_err_t loadbalancing_config_get_handler(httpd_req_t *req) {
    bool enabled = loadbalancer_is_enabled();
    uint8_t currentLimit = load_balancing_get_max_grid_current();

    ESP_LOGI(TAG, "Fetching load balancing settings: enabled = %d, currentLimit = %u", enabled, currentLimit);

    httpd_resp_set_type(req, "application/json");

    cJSON *config = cJSON_CreateObject();
    cJSON_AddBoolToObject(config, "loadBalancingEnabled", enabled);
    cJSON_AddNumberToObject(config, "loadBalancingCurrentLimit", currentLimit);

    const char *json_str = cJSON_Print(config);
    httpd_resp_sendstr(req, json_str);

    ESP_LOGI(TAG, "Returned config: %s", json_str);

    free((void *)json_str);
    cJSON_Delete(config);
    return ESP_OK;
}

// POST Handler: Atualiza configurações de load balancing
static esp_err_t loadbalancing_config_post_handler(httpd_req_t *req) {
    char buf[512];
    int len = httpd_req_recv(req, buf, sizeof(buf) - 1);

    if (len <= 0) {
        ESP_LOGE(TAG, "Received empty POST body");
        httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Empty body");
        return ESP_FAIL;
    }

    buf[len] = '\0';
    ESP_LOGI(TAG, "Received POST data: %s", buf);

    cJSON *json = cJSON_Parse(buf);
    if (!json) {
        ESP_LOGE(TAG, "Invalid JSON");
        httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid JSON");
        return ESP_FAIL;
    }

    // Atualizar estado habilitado
    cJSON *enabled_item = cJSON_GetObjectItem(json, "loadBalancingEnabled");
    if (enabled_item && cJSON_IsBool(enabled_item)) {
        bool isEnabled = cJSON_IsTrue(enabled_item);
        loadbalancer_set_enabled(isEnabled);
        ESP_LOGI(TAG, "Updated loadBalancingEnabled to: %d", isEnabled);
    }

    // Atualizar limite de corrente
    cJSON *limit_item = cJSON_GetObjectItem(json, "loadBalancingCurrentLimit");
    if (limit_item && cJSON_IsNumber(limit_item)) {
        uint8_t currentLimit = (uint8_t)limit_item->valuedouble;

        // Validar intervalo
        if (currentLimit < 6 || currentLimit > 100) {
            ESP_LOGW(TAG, "Rejected invalid currentLimit: %d", currentLimit);
            cJSON_Delete(json);
            httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid currentLimit (must be 6-100)");
            return ESP_FAIL;
        }

        esp_err_t err = load_balancing_set_max_grid_current(currentLimit);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "Failed to save currentLimit: %s", esp_err_to_name(err));
            cJSON_Delete(json);
            httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to save setting");
            return ESP_FAIL;
        }

        ESP_LOGI(TAG, "Updated loadBalancingCurrentLimit to: %d", currentLimit);
    }

    cJSON_Delete(json);
    httpd_resp_sendstr(req, "Load balancing settings updated successfully");
    return ESP_OK;
}

// Registro dos handlers na API HTTP
void register_loadbalancing_settings_handlers(httpd_handle_t server, void *ctx) {
    // GET
    httpd_uri_t get_uri = {
        .uri = "/api/v1/config/loadbalancing",
        .method = HTTP_GET,
        .handler = loadbalancing_config_get_handler,
        .user_ctx = ctx
    };
    httpd_register_uri_handler(server, &get_uri);

    // POST
    httpd_uri_t post_uri = {
        .uri = "/api/v1/config/loadbalancing",
        .method = HTTP_POST,
        .handler = loadbalancing_config_post_handler,
        .user_ctx = ctx
    };
    httpd_register_uri_handler(server, &post_uri);
}
