#include "WebServer.hpp"
#include "../KnxWorker.hpp"
#include "../Gui.hpp"
#include <cstring>

esp_err_t WebServer::getKnxAddressesHandler(httpd_req_t* req) {
    KnxWorker& knxWorker = Gui::knxWorker;
    size_t count = knxWorker.getGroupObjectCount();

    cJSON* arr = cJSON_CreateArray();

    for (size_t i = 1; i <= count; i++) {
        KnxGroupObjectInfo info;
        if (knxWorker.getGroupObjectInfo(i, info)) {
            if (info.groupAddress == 0) {
                continue;
            }
            char addrStr[16];
            KnxWorker::formatGroupAddress(info.groupAddress, addrStr, sizeof(addrStr));

            cJSON* obj = cJSON_CreateObject();
            cJSON_AddNumberToObject(obj, "index", info.goIndex);
            cJSON_AddNumberToObject(obj, "addr", info.groupAddress);
            cJSON_AddStringToObject(obj, "addrStr", addrStr);
            cJSON_AddBoolToObject(obj, "comm", info.commFlag);
            cJSON_AddBoolToObject(obj, "read", info.readFlag);
            cJSON_AddBoolToObject(obj, "write", info.transmitFlag);  // transmit = kann auf Bus schreiben
            cJSON_AddItemToArray(arr, obj);
        }
    }

    char* str = cJSON_PrintUnformatted(arr);
    httpd_resp_set_type(req, "application/json");
    httpd_resp_send(req, str, strlen(str));
    free(str);
    cJSON_Delete(arr);
    return ESP_OK;
}

esp_err_t WebServer::getKnxProgHandler(httpd_req_t* req) {
    KnxWorker& knxWorker = Gui::knxWorker;
    cJSON* json = cJSON_CreateObject();
    cJSON_AddBoolToObject(json, "progMode", knxWorker.getProgMode());
    return sendJsonObject(req, json);
}

esp_err_t WebServer::postKnxProgHandler(httpd_req_t* req) {
    KnxWorker& knxWorker = Gui::knxWorker;
    bool current = knxWorker.getProgMode();
    bool target = current;
    bool hasTarget = false;

    int total_len = req->content_len;
    if (total_len > 0) {
        if (total_len > 256) {
            return sendJsonError(req, "Content too large");
        }

        char* buf = new char[total_len + 1];
        if (!buf) {
            return sendJsonError(req, "Out of memory");
        }

        int received = 0;
        while (received < total_len) {
            int ret = httpd_req_recv(req, buf + received, total_len - received);
            if (ret <= 0) {
                delete[] buf;
                return sendJsonError(req, "Receive failed");
            }
            received += ret;
        }
        buf[received] = '\0';

        cJSON* json = cJSON_Parse(buf);
        delete[] buf;

        if (!json) {
            return sendJsonError(req, "Invalid JSON");
        }

        cJSON* enabled = cJSON_GetObjectItemCaseSensitive(json, "enabled");
        if (!enabled) {
            enabled = cJSON_GetObjectItemCaseSensitive(json, "progMode");
        }

        if (cJSON_IsBool(enabled)) {
            target = cJSON_IsTrue(enabled);
            hasTarget = true;
        }

        cJSON_Delete(json);

        if (!hasTarget) {
            return sendJsonError(req, "Missing 'enabled'");
        }
    }

    if (!hasTarget) {
        target = !current;
    }
    knxWorker.setProgMode(target);

    cJSON* json = cJSON_CreateObject();
    cJSON_AddStringToObject(json, "status", "ok");
    cJSON_AddBoolToObject(json, "progMode", target);
    return sendJsonObject(req, json);
}

esp_err_t WebServer::postKnxResetHandler(httpd_req_t* req) {
    KnxWorker& knxWorker = Gui::knxWorker;
    knxWorker.clearSettings();

    cJSON* json = cJSON_CreateObject();
    cJSON_AddStringToObject(json, "status", "ok");
    cJSON_AddStringToObject(json, "message", "KNX settings cleared, rebooting");
    return sendJsonObject(req, json);
}
