/*
 * Simple WebSocket Debug Tool for NIP-17 Testing
 *
 * Connects to a relay and sends a subscription request to see what responses we get.
 */

#define _GNU_SOURCE
#define _POSIX_C_SOURCE 200809L

#include "../nostr_core/nostr_core.h"
#include "../nostr_websocket/nostr_websocket_tls.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>

int main(int argc, char* argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <relay_url> [event_id]\n", argv[0]);
        fprintf(stderr, "Example: websocket_debug wss://relay.laantungir.net 06cdf2cdd095ddb1ebe15d5b3c736b27a34de2683e847b871fe37d86ac998772\n");
        return 1;
    }

    const char* relay_url = argv[1];
    const char* event_id = (argc >= 3) ? argv[2] : NULL;

    printf("🔍 WebSocket Debug Tool\n");
    printf("=======================\n");
    printf("Relay: %s\n", relay_url);
    if (event_id) {
        printf("Looking for event: %s\n", event_id);
    }
    printf("\n");

    // Initialize crypto
    if (nostr_init() != NOSTR_SUCCESS) {
        fprintf(stderr, "Failed to initialize crypto\n");
        return 1;
    }

    // Connect to relay
    printf("🔌 Connecting to relay...\n");
    nostr_ws_client_t* client = nostr_ws_connect(relay_url);
    if (!client) {
        fprintf(stderr, "Failed to connect to relay - nostr_ws_connect returned NULL\n");
        return 1;
    }

    // Check initial state
    nostr_ws_state_t initial_state = nostr_ws_get_state(client);
    printf("Initial connection state: %d\n", (int)initial_state);

    // Wait for connection
    time_t start_time = time(NULL);
    while (time(NULL) - start_time < 10) {  // 10 second timeout
        nostr_ws_state_t state = nostr_ws_get_state(client);
        if (state == NOSTR_WS_CONNECTED) {
            printf("✅ Connected!\n");
            break;
        } else if (state == NOSTR_WS_ERROR) {
            fprintf(stderr, "❌ Connection failed\n");
            nostr_ws_close(client);
            return 1;
        }
        usleep(100000); // 100ms
    }

    if (nostr_ws_get_state(client) != NOSTR_WS_CONNECTED) {
        fprintf(stderr, "❌ Connection timeout\n");
        nostr_ws_close(client);
        return 1;
    }

    // Send subscription request
    printf("📡 Sending subscription request...\n");

    // Create filter for kind 1059 events
    cJSON* filter = cJSON_CreateObject();
    cJSON* kinds = cJSON_CreateArray();
    cJSON_AddItemToArray(kinds, cJSON_CreateNumber(1059));
    cJSON_AddItemToObject(filter, "kinds", kinds);

    // If we have a specific event ID, add it to the filter
    if (event_id) {
        cJSON* ids = cJSON_CreateArray();
        cJSON_AddItemToArray(ids, cJSON_CreateString(event_id));
        cJSON_AddItemToObject(filter, "ids", ids);
    }

    char* filter_json = cJSON_PrintUnformatted(filter);
    printf("Filter: %s\n", filter_json);

    // Send REQ message
    char subscription_id[32];
    snprintf(subscription_id, sizeof(subscription_id), "debug_%ld", time(NULL));

    if (nostr_relay_send_req(client, subscription_id, filter) < 0) {
        fprintf(stderr, "Failed to send subscription request\n");
        cJSON_Delete(filter);
        free(filter_json);
        nostr_ws_close(client);
        return 1;
    }

    cJSON_Delete(filter);
    free(filter_json);

    printf("✅ Subscription sent (ID: %s)\n", subscription_id);
    printf("⏳ Listening for responses (30 seconds)...\n");
    printf("Press Ctrl+C to stop\n\n");

    // Listen for responses
    start_time = time(NULL);
    int message_count = 0;

    while (time(NULL) - start_time < 30) {  // 30 second timeout
        char buffer[16384];
        int len = nostr_ws_receive(client, buffer, sizeof(buffer) - 1, 1000); // 1 second timeout

        if (len > 0) {
            buffer[len] = '\0';
            message_count++;

            printf("📨 Message %d:\n", message_count);
            printf("%s\n", buffer);

            // Parse the message
            char* msg_type = NULL;
            cJSON* parsed = NULL;

            if (nostr_parse_relay_message(buffer, &msg_type, &parsed) == 0) {
                if (msg_type && strcmp(msg_type, "EVENT") == 0) {
                    printf("   → EVENT received\n");
                    if (cJSON_IsArray(parsed) && cJSON_GetArraySize(parsed) >= 3) {
                        cJSON* event = cJSON_GetArrayItem(parsed, 2);
                        if (event) {
                            cJSON* kind_item = cJSON_GetObjectItem(event, "kind");
                            cJSON* id_item = cJSON_GetObjectItem(event, "id");
                            if (kind_item && cJSON_IsNumber(kind_item)) {
                                printf("   → Kind: %d\n", (int)cJSON_GetNumberValue(kind_item));
                            }
                            if (id_item && cJSON_IsString(id_item)) {
                                printf("   → ID: %.12s...\n", cJSON_GetStringValue(id_item));
                            }
                        }
                    }
                } else if (msg_type && strcmp(msg_type, "EOSE") == 0) {
                    printf("   → EOSE (End of Stored Events)\n");
                } else if (msg_type && strcmp(msg_type, "NOTICE") == 0) {
                    printf("   → NOTICE from relay\n");
                    if (cJSON_IsArray(parsed) && cJSON_GetArraySize(parsed) >= 2) {
                        cJSON* notice_msg = cJSON_GetArrayItem(parsed, 1);
                        if (notice_msg && cJSON_IsString(notice_msg)) {
                            printf("   → Message: %s\n", cJSON_GetStringValue(notice_msg));
                        }
                    }
                } else if (msg_type) {
                    printf("   → %s\n", msg_type);
                }

                if (msg_type) free(msg_type);
                if (parsed) cJSON_Delete(parsed);
            }

            printf("\n");
        } else if (len < 0) {
            printf("❌ Receive error\n");
            break;
        }

        // Small delay to prevent busy waiting
        usleep(10000); // 10ms
    }

    printf("📊 Total messages received: %d\n", message_count);

    // Send CLOSE message
    printf("🔌 Closing subscription...\n");
    nostr_relay_send_close(client, subscription_id);

    // Close connection
    nostr_ws_close(client);
    nostr_cleanup();

    printf("✅ Done\n");
    return 0;
}