#define _POSIX_C_SOURCE 200809L

#include "tools_internal.h"

#include <stdlib.h>

#include "cjson/cJSON.h"
#include "../trigger_manager.h"

static char* json_error_local(const char* msg) {
    cJSON* root = cJSON_CreateObject();
    if (!root) return NULL;
    cJSON_AddBoolToObject(root, "success", 0);
    cJSON_AddStringToObject(root, "error", msg ? msg : "unknown error");
    char* out = cJSON_PrintUnformatted(root);
    cJSON_Delete(root);
    return out;
}

char* execute_tool_list(tools_context_t* ctx, const char* args_json) {
    (void)args_json;
    if (!ctx) {
        return json_error_local("tool context unavailable");
    }

    char* schema_json = tools_build_openai_schema_json(ctx);
    if (!schema_json) {
        return json_error_local("failed to build tool schemas");
    }

    cJSON* schema_arr = cJSON_Parse(schema_json);
    free(schema_json);
    if (!schema_arr || !cJSON_IsArray(schema_arr)) {
        cJSON_Delete(schema_arr);
        return json_error_local("failed to parse tool schemas");
    }

    cJSON* out = cJSON_CreateObject();
    cJSON* tools = cJSON_CreateArray();
    if (!out || !tools) {
        cJSON_Delete(schema_arr);
        cJSON_Delete(out);
        cJSON_Delete(tools);
        return json_error_local("out of memory");
    }

    cJSON* item = NULL;
    cJSON_ArrayForEach(item, schema_arr) {
        cJSON* fn = cJSON_GetObjectItemCaseSensitive(item, "function");
        if (!fn || !cJSON_IsObject(fn)) {
            continue;
        }

        cJSON* name = cJSON_GetObjectItemCaseSensitive(fn, "name");
        if (!name || !cJSON_IsString(name) || !name->valuestring) {
            continue;
        }

        cJSON* row = cJSON_CreateObject();
        if (!row) {
            continue;
        }

        cJSON_AddStringToObject(row, "name", name->valuestring);

        cJSON* description = cJSON_GetObjectItemCaseSensitive(fn, "description");
        if (description && cJSON_IsString(description) && description->valuestring) {
            cJSON_AddStringToObject(row, "description", description->valuestring);
        } else {
            cJSON_AddStringToObject(row, "description", "");
        }

        cJSON* parameters = cJSON_GetObjectItemCaseSensitive(fn, "parameters");
        if (parameters) {
            cJSON_AddItemToObject(row, "parameters", cJSON_Duplicate(parameters, 1));
        } else {
            cJSON_AddItemToObject(row, "parameters", cJSON_CreateObject());
        }

        cJSON_AddItemToArray(tools, row);
    }

    cJSON_AddBoolToObject(out, "success", 1);
    cJSON_AddNumberToObject(out, "count", (double)cJSON_GetArraySize(tools));
    cJSON_AddItemToObject(out, "tools", tools);

    char* result = cJSON_PrintUnformatted(out);
    cJSON_Delete(out);
    cJSON_Delete(schema_arr);
    return result;
}

char* execute_trigger_list(tools_context_t* ctx, const char* args_json) {
    (void)args_json;
    if (!ctx || !ctx->trigger_manager) {
        return json_error_local("trigger manager unavailable");
    }
    char* status = trigger_manager_status_json(ctx->trigger_manager);
    if (!status) {
        return json_error_local("failed to build trigger status");
    }
    return status;
}
