/*
 * NIP-05 Test Program
 * 
 * Tests the NIP-05 identifier verification and lookup functionality
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "../nostr_core/nip005.h"
#include "../nostr_core/nostr_common.h"

// Test helper function
void print_test_result(const char* test_name, int result) {
    if (result == NOSTR_SUCCESS) {
        printf("✅ %s: PASSED\n", test_name);
    } else {
        printf("❌ %s: FAILED (%s)\n", test_name, nostr_strerror(result));
    }
}

void print_relays(char** relays, int relay_count) {
    if (relays && relay_count > 0) {
        printf("   📡 Found %d relay(s):\n", relay_count);
        for (int i = 0; i < relay_count; i++) {
            printf("      - %s\n", relays[i]);
        }
    } else {
        printf("   📡 No relays found\n");
    }
}

void cleanup_relays(char** relays, int relay_count) {
    if (relays) {
        for (int i = 0; i < relay_count; i++) {
            free(relays[i]);
        }
        free(relays);
    }
}

int main(void) {
    printf("NOSTR NIP-05 Test Suite\n");
    printf("======================\n\n");
    
    // Initialize library
    int init_result = nostr_init();
    print_test_result("Library initialization", init_result);
    if (init_result != NOSTR_SUCCESS) {
        return 1;
    }
    
    printf("\n=== NIP-05 Lookup Tests ===\n");
    
    // Test 1: Valid identifier lookup (provided by user)
    printf("\n[TEST] NIP-05 Lookup: lt@laantungir.net\n");
    char pubkey_out[65];
    char** relays = NULL;
    int relay_count = 0;
    
    int result = nostr_nip05_lookup("lt@laantungir.net", pubkey_out, &relays, &relay_count, 10);
    print_test_result("NIP-05 lookup for lt@laantungir.net", result);
    
    if (result == NOSTR_SUCCESS) {
        printf("   🔑 Public key: %s\n", pubkey_out);
        print_relays(relays, relay_count);
        cleanup_relays(relays, relay_count);
        relays = NULL;
        relay_count = 0;
        
        // Test 2: Verify the found public key
        printf("\n[TEST] NIP-05 Verification: lt@laantungir.net\n");
        char** verify_relays = NULL;
        int verify_relay_count = 0;
        
        int verify_result = nostr_nip05_verify("lt@laantungir.net", pubkey_out, 
                                              &verify_relays, &verify_relay_count, 10);
        print_test_result("NIP-05 verification for lt@laantungir.net", verify_result);
        
        if (verify_result == NOSTR_SUCCESS) {
            printf("   ✅ Verification successful!\n");
            print_relays(verify_relays, verify_relay_count);
        }
        
        cleanup_relays(verify_relays, verify_relay_count);
        
        // Test 3: Verify with wrong public key (should fail)
        printf("\n[TEST] NIP-05 Verification with wrong pubkey\n");
        char wrong_pubkey[65] = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
        
        int wrong_result = nostr_nip05_verify("lt@laantungir.net", wrong_pubkey, NULL, NULL, 10);
        if (wrong_result == NOSTR_ERROR_NIP05_PUBKEY_MISMATCH) {
            printf("✅ Wrong pubkey verification correctly failed: %s\n", nostr_strerror(wrong_result));
        } else {
            printf("❌ Wrong pubkey verification should have failed but got: %s\n", nostr_strerror(wrong_result));
        }
        
    } else {
        printf("   ❌ Cannot proceed with verification tests due to lookup failure\n");
    }
    
    printf("\n=== Error Handling Tests ===\n");
    
    // Test 4: Invalid identifier format
    printf("\n[TEST] Invalid identifier format\n");
    int invalid_result = nostr_nip05_lookup("invalid_identifier", pubkey_out, NULL, NULL, 10);
    if (invalid_result == NOSTR_ERROR_NIP05_INVALID_IDENTIFIER) {
        printf("✅ Invalid identifier correctly rejected: %s\n", nostr_strerror(invalid_result));
    } else {
        printf("❌ Invalid identifier should have been rejected but got: %s\n", nostr_strerror(invalid_result));
    }
    
    // Test 5: Non-existent domain (will likely fail with HTTP error)
    printf("\n[TEST] Non-existent domain\n");
    int nonexistent_result = nostr_nip05_lookup("test@nonexistentdomain12345.com", pubkey_out, NULL, NULL, 5);
    if (nonexistent_result == NOSTR_ERROR_NIP05_HTTP_FAILED) {
        printf("✅ Non-existent domain correctly failed: %s\n", nostr_strerror(nonexistent_result));
    } else {
        printf("⚠️  Non-existent domain result: %s\n", nostr_strerror(nonexistent_result));
    }
    
    // Test 6: Non-existent user on valid domain
    printf("\n[TEST] Non-existent user on valid domain\n");
    int nonexistent_user_result = nostr_nip05_lookup("nonexistentuser123@laantungir.net", pubkey_out, NULL, NULL, 10);
    if (nonexistent_user_result == NOSTR_ERROR_NIP05_NAME_NOT_FOUND) {
        printf("✅ Non-existent user correctly failed: %s\n", nostr_strerror(nonexistent_user_result));
    } else {
        printf("⚠️  Non-existent user result: %s\n", nostr_strerror(nonexistent_user_result));
    }
    
    printf("\n=== Test Popular NIP-05 Services ===\n");
    
    // Test some well-known NIP-05 identifiers (these may or may not work)
    const char* test_identifiers[] = {
        "_@damus.io",
        "_@nostrid.com",
        "_@nos.social"
    };
    
    for (size_t i = 0; i < sizeof(test_identifiers) / sizeof(test_identifiers[0]); i++) {
        printf("\n[TEST] Testing %s\n", test_identifiers[i]);
        char test_pubkey[65];
        char** test_relays = NULL;
        int test_relay_count = 0;
        
        int test_result = nostr_nip05_lookup(test_identifiers[i], test_pubkey, 
                                           &test_relays, &test_relay_count, 10);
        
        if (test_result == NOSTR_SUCCESS) {
            printf("✅ %s lookup successful\n", test_identifiers[i]);
            printf("   🔑 Public key: %s\n", test_pubkey);
            print_relays(test_relays, test_relay_count);
        } else {
            printf("⚠️  %s lookup failed: %s\n", test_identifiers[i], nostr_strerror(test_result));
        }
        
        cleanup_relays(test_relays, test_relay_count);
    }
    
    printf("\n=== JSON Parsing Tests ===\n");
    
    // Test 7: Direct JSON parsing
    printf("\n[TEST] Direct JSON parsing\n");
    const char* test_json = "{"
        "\"names\": {"
            "\"test\": \"b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9\""
        "},"
        "\"relays\": {"
            "\"b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9\": ["
                "\"wss://relay.example.com\","
                "\"wss://relay2.example.com\""
            "]"
        "}"
    "}";
    
    char parse_pubkey[65];
    char** parse_relays = NULL;
    int parse_relay_count = 0;
    
    int parse_result = nostr_nip05_parse_well_known(test_json, "test", parse_pubkey, 
                                                   &parse_relays, &parse_relay_count);
    print_test_result("JSON parsing", parse_result);
    
    if (parse_result == NOSTR_SUCCESS) {
        printf("   🔑 Parsed public key: %s\n", parse_pubkey);
        print_relays(parse_relays, parse_relay_count);
    }
    
    cleanup_relays(parse_relays, parse_relay_count);
    
    // Test 8: JSON parsing with missing name
    printf("\n[TEST] JSON parsing with missing name\n");
    int missing_name_result = nostr_nip05_parse_well_known(test_json, "missing", parse_pubkey, NULL, NULL);
    if (missing_name_result == NOSTR_ERROR_NIP05_NAME_NOT_FOUND) {
        printf("✅ Missing name correctly handled: %s\n", nostr_strerror(missing_name_result));
    } else {
        printf("❌ Missing name should have failed but got: %s\n", nostr_strerror(missing_name_result));
    }
    
    printf("\n=== Summary ===\n");
    printf("NIP-05 testing completed.\n");
    printf("The primary test identifier lt@laantungir.net should have worked if properly configured.\n");
    printf("Some popular services may be unavailable or have different configurations.\n");
    
    // Cleanup
    nostr_cleanup();
    
    return 0;
}
