#define _POSIX_C_SOURCE 200809L

#include "tools_internal.h"

#include <stdlib.h>
#include <string.h>

#include "cjson/cJSON.h"

static char* json_error(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;
}

int tools_init_legacy(tools_context_t* ctx, didactyl_config_t* cfg) {
    if (!ctx || !cfg) return -1;
    memset(ctx, 0, sizeof(*ctx));
    ctx->cfg = cfg;
    ctx->trigger_manager = NULL;
    ctx->template_sender_tier = 0;
    ctx->template_current_user_message = NULL;
    ctx->template_trigger_event_json = NULL;
    ctx->template_skill_lookup = NULL;
    ctx->template_skill_lookup_user_data = NULL;
    return 0;
}

void tools_cleanup_legacy(tools_context_t* ctx) {
    if (!ctx) return;
    memset(ctx, 0, sizeof(*ctx));
}

char* tools_execute_legacy(tools_context_t* ctx, const char* tool_name, const char* args_json) {
    if (!tool_name) return json_error("missing tool name");

    if (strcmp(tool_name, "nostr_post") == 0) {
        return execute_nostr_post(args_json);
    }
    if (strcmp(tool_name, "nostr_delete") == 0) {
        return execute_nostr_delete(args_json);
    }
    if (strcmp(tool_name, "nostr_react") == 0) {
        return execute_nostr_react(args_json);
    }
    if (strcmp(tool_name, "nostr_profile_get") == 0) {
        return execute_nostr_profile_get(args_json);
    }
    if (strcmp(tool_name, "nostr_relay_status") == 0) {
        return execute_nostr_relay_status(args_json);
    }
    if (strcmp(tool_name, "nostr_nip05_lookup") == 0) {
        return execute_nostr_nip05_lookup(args_json);
    }
    if (strcmp(tool_name, "nostr_encode") == 0) {
        return execute_nostr_encode(args_json);
    }
    if (strcmp(tool_name, "nostr_decode") == 0) {
        return execute_nostr_decode(args_json);
    }
    if (strcmp(tool_name, "nostr_dm_send") == 0) {
        return execute_nostr_dm_send(args_json);
    }
    if (strcmp(tool_name, "nostr_relay_info") == 0) {
        return execute_nostr_relay_info(args_json);
    }
    if (strcmp(tool_name, "nostr_subscription_status") == 0) {
        return execute_nostr_subscription_status(args_json);
    }
    if (strcmp(tool_name, "nostr_subscription_set") == 0) {
        return execute_nostr_subscription_set(args_json);
    }
    if (strcmp(tool_name, "nostr_encrypt") == 0) {
        return execute_nostr_encrypt(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_decrypt") == 0) {
        return execute_nostr_decrypt(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_dm_send_nip17") == 0) {
        return execute_nostr_dm_send_nip17(args_json);
    }
    if (strcmp(tool_name, "nostr_list_manage") == 0) {
        return execute_nostr_list_manage(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_block_list") == 0) {
        return execute_nostr_block_list(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_block_edit") == 0) {
        return execute_nostr_block_edit(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_query") == 0) {
        return execute_nostr_query(args_json);
    }
    if (strcmp(tool_name, "nostr_my_events") == 0) {
        return execute_nostr_my_events(ctx, args_json);
    }
    if (strcmp(tool_name, "agent_version") == 0) {
        return execute_agent_version(args_json);
    }
    if (strcmp(tool_name, "nostr_pubkey") == 0) {
        return execute_nostr_pubkey(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_npub") == 0) {
        return execute_nostr_npub(ctx, args_json);
    }
    if (strcmp(tool_name, "my_pubkey") == 0) {
        return execute_nostr_pubkey(ctx, args_json);
    }
    if (strcmp(tool_name, "my_npub") == 0) {
        return execute_nostr_npub(ctx, args_json);
    }
    if (strcmp(tool_name, "local_http_fetch") == 0) {
        return execute_local_http_fetch(ctx, args_json);
    }
    if (strcmp(tool_name, "local_shell_exec") == 0) {
        return execute_local_shell_exec(ctx, args_json);
    }
    if (strcmp(tool_name, "local_file_read") == 0) {
        return execute_local_file_read(ctx, args_json);
    }
    if (strcmp(tool_name, "local_file_write") == 0) {
        return execute_local_file_write(ctx, args_json);
    }
    if (strcmp(tool_name, "skill_create") == 0) {
        return execute_skill_create(ctx, args_json);
    }
    if (strcmp(tool_name, "skill_list") == 0) {
        return execute_skill_list(ctx, args_json);
    }
    if (strcmp(tool_name, "skill_get") == 0) {
        return execute_skill_get(ctx, args_json);
    }
    if (strcmp(tool_name, "skill_view") == 0) {
        return execute_skill_get(ctx, args_json);
    }
    if (strcmp(tool_name, "skill_set") == 0) {
        return execute_skill_set(ctx, args_json);
    }
    if (strcmp(tool_name, "skill_adopt") == 0) {
        return execute_skill_adopt(ctx, args_json);
    }
    if (strcmp(tool_name, "skill_remove") == 0) {
        return execute_skill_remove(ctx, args_json);
    }
    if (strcmp(tool_name, "skill_search") == 0) {
        return execute_skill_search(args_json);
    }
    if (strcmp(tool_name, "skill_edit") == 0) {
        return execute_skill_edit(ctx, args_json);
    }
    if (strcmp(tool_name, "trigger_list") == 0) {
        return execute_trigger_list(ctx, args_json);
    }
    if (strcmp(tool_name, "tool_list") == 0) {
        return execute_tool_list(ctx, args_json);
    }
    if (strcmp(tool_name, "model_get") == 0) {
        return execute_model_get(args_json);
    }
    if (strcmp(tool_name, "model_set") == 0) {
        return execute_model_set(ctx, args_json);
    }
    if (strcmp(tool_name, "model_list") == 0) {
        return execute_model_list(args_json);
    }

    if (strcmp(tool_name, "nostr_post_readme") == 0) {
        return execute_nostr_post_readme(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_file_md_to_longform_post") == 0) {
        return execute_nostr_file_md_to_longform_post(ctx, args_json);
    }
    if (strcmp(tool_name, "task_manage") == 0) {
        return execute_task_manage(ctx, args_json);
    }
    if (strcmp(tool_name, "admin_identity") == 0) {
        return execute_admin_identity(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_admin_profile") == 0) {
        return execute_nostr_admin_profile(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_admin_contacts") == 0) {
        return execute_nostr_admin_contacts(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_admin_relays") == 0) {
        return execute_nostr_admin_relays(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_admin_notes") == 0) {
        return execute_nostr_admin_notes(ctx, args_json);
    }
    if (strcmp(tool_name, "task_list") == 0) {
        return execute_task_list(ctx, args_json);
    }
    if (strcmp(tool_name, "message_current") == 0) {
        return execute_message_current(ctx, args_json);
    }
    if (strcmp(tool_name, "agent_identity") == 0) {
        return execute_agent_identity(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_agent_profile") == 0) {
        return execute_nostr_agent_profile(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_agent_contacts") == 0) {
        return execute_nostr_agent_contacts(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_agent_relays") == 0) {
        return execute_nostr_agent_relays(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_agent_notes") == 0) {
        return execute_nostr_agent_notes(ctx, args_json);
    }
    if (strcmp(tool_name, "my_kind0_profile") == 0) {
        return execute_nostr_agent_profile(ctx, args_json);
    }
    if (strcmp(tool_name, "my_contacts") == 0) {
        return execute_nostr_agent_contacts(ctx, args_json);
    }
    if (strcmp(tool_name, "my_relays") == 0) {
        return execute_nostr_agent_relays(ctx, args_json);
    }
    if (strcmp(tool_name, "my_notes") == 0) {
        return execute_nostr_agent_notes(ctx, args_json);
    }
    if (strcmp(tool_name, "memory_save") == 0) {
        return execute_memory_save(ctx, args_json);
    }
    if (strcmp(tool_name, "memory_recall") == 0) {
        return execute_memory_recall(ctx, args_json);
    }
    if (strcmp(tool_name, "my_memory") == 0) {
        return execute_my_memory(ctx, args_json);
    }
    if (strcmp(tool_name, "memory_short_term_read") == 0) {
        return execute_memory_short_term_read(ctx, args_json);
    }
    if (strcmp(tool_name, "config_store") == 0) {
        return execute_config_store(ctx, args_json);
    }
    if (strcmp(tool_name, "config_recall") == 0) {
        return execute_config_recall(ctx, args_json);
    }
    if (strcmp(tool_name, "adopted_skills") == 0) {
        return execute_adopted_skills(ctx, args_json);
    }
    if (strcmp(tool_name, "trigger_event") == 0) {
        return execute_trigger_event(ctx, args_json);
    }
    if (strcmp(tool_name, "nostr_dm_history") == 0) {
        return execute_nostr_dm_history(ctx, args_json);
    }
    if (strcmp(tool_name, "cashu_wallet_balance") == 0) {
        return execute_cashu_wallet_balance(ctx, args_json);
    }
    if (strcmp(tool_name, "cashu_wallet_info") == 0) {
        return execute_cashu_wallet_info(ctx, args_json);
    }
    if (strcmp(tool_name, "cashu_wallet_mint_quote") == 0) {
        return execute_cashu_wallet_mint_quote(ctx, args_json);
    }
    if (strcmp(tool_name, "cashu_wallet_mint_check") == 0) {
        return execute_cashu_wallet_mint_check(ctx, args_json);
    }
    if (strcmp(tool_name, "cashu_wallet_mint_claim") == 0) {
        return execute_cashu_wallet_mint_claim(ctx, args_json);
    }
    if (strcmp(tool_name, "cashu_wallet_melt_quote") == 0) {
        return execute_cashu_wallet_melt_quote(ctx, args_json);
    }
    if (strcmp(tool_name, "cashu_wallet_melt_pay") == 0) {
        return execute_cashu_wallet_melt_pay(ctx, args_json);
    }
    if (strcmp(tool_name, "cashu_wallet_check_proofs") == 0) {
        return execute_cashu_wallet_check_proofs(ctx, args_json);
    }
    if (strcmp(tool_name, "cashu_wallet_receive_token") == 0) {
        return execute_cashu_wallet_receive_token(ctx, args_json);
    }
    if (strcmp(tool_name, "cashu_wallet_send_token") == 0) {
        return execute_cashu_wallet_send_token(ctx, args_json);
    }
    if (strcmp(tool_name, "cashu_wallet_mints_get") == 0) {
        return execute_cashu_wallet_mints_get(ctx, args_json);
    }
    if (strcmp(tool_name, "cashu_wallet_mints_set") == 0) {
        return execute_cashu_wallet_mints_set(ctx, args_json);
    }
    if (strcmp(tool_name, "blossom_upload") == 0) {
        return execute_blossom_upload(ctx, args_json);
    }
    if (strcmp(tool_name, "blossom_download") == 0) {
        return execute_blossom_download(ctx, args_json);
    }
    if (strcmp(tool_name, "blossom_head") == 0) {
        return execute_blossom_head(ctx, args_json);
    }
    if (strcmp(tool_name, "blossom_delete") == 0) {
        return execute_blossom_delete(ctx, args_json);
    }
    if (strcmp(tool_name, "blossom_list") == 0) {
        return execute_blossom_list(ctx, args_json);
    }

    return json_error("unknown tool");
}

int tools_init(tools_context_t* ctx, didactyl_config_t* cfg) {
    int rc = tools_init_legacy(ctx, cfg);
    if (rc != 0) return rc;
    if (memory_init(ctx) != 0) {
        /* Keep agent startup resilient: memory may be empty or temporarily unavailable. */
        return 0;
    }
    return 0;
}

void tools_cleanup(tools_context_t* ctx) {
    memory_cleanup();
    tools_cleanup_legacy(ctx);
}

char* tools_execute(tools_context_t* ctx, const char* tool_name, const char* args_json) {
    return tools_execute_legacy(ctx, tool_name, args_json);
}
