/*
 * Example: Utility Functions
 * Demonstrates nostr_bytes_to_hex(), nostr_hex_to_bytes(), nostr_strerror()
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "nostr_core.h"

int main() {
    printf("=== NOSTR Utility Functions Example ===\n\n");
    
    // Initialize the library
    if (nostr_init() != NOSTR_SUCCESS) {
        fprintf(stderr, "Failed to initialize NOSTR library\n");
        return 1;
    }
    
    // Test 1: Bytes to Hex conversion
    printf("Test 1: Bytes to Hex Conversion\n");
    printf("-------------------------------\n");
    
    unsigned char test_bytes[] = {
        0x5d, 0xab, 0x08, 0x7e, 0x62, 0x4a, 0x8a, 0x4b,
        0x79, 0xe1, 0x7f, 0x8b, 0x83, 0x80, 0x0e, 0xe6,
        0x6f, 0x3b, 0xb1, 0x29, 0x26, 0x18, 0xb6, 0xfd,
        0x1c, 0x2f, 0x8b, 0x27, 0xff, 0x88, 0xe0, 0xeb
    };
    
    char hex_output[65]; // 32 bytes * 2 + null terminator
    nostr_bytes_to_hex(test_bytes, sizeof(test_bytes), hex_output);
    
    printf("Input bytes (%zu bytes):\n", sizeof(test_bytes));
    printf("  ");
    for (size_t i = 0; i < sizeof(test_bytes); i++) {
        printf("%02x ", test_bytes[i]);
        if ((i + 1) % 16 == 0) printf("\n  ");
    }
    printf("\n");
    printf("Hex output: %s\n\n", hex_output);
    
    // Test 2: Hex to Bytes conversion
    printf("Test 2: Hex to Bytes Conversion\n");
    printf("-------------------------------\n");
    
    const char* test_hex = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb";
    unsigned char bytes_output[32];
    
    printf("Input hex: %s\n", test_hex);
    
    int result = nostr_hex_to_bytes(test_hex, bytes_output, sizeof(bytes_output));
    if (result == NOSTR_SUCCESS) {
        printf("✓ Successfully converted hex to bytes\n");
        printf("Output bytes (%zu bytes):\n", sizeof(bytes_output));
        printf("  ");
        for (size_t i = 0; i < sizeof(bytes_output); i++) {
            printf("%02x ", bytes_output[i]);
            if ((i + 1) % 16 == 0) printf("\n  ");
        }
        printf("\n");
        
        // Verify round-trip conversion
        int match = memcmp(test_bytes, bytes_output, sizeof(test_bytes)) == 0;
        printf("Round-trip verification: %s\n\n", match ? "✓ PASSED" : "✗ FAILED");
    } else {
        printf("✗ Failed to convert hex to bytes: %s\n\n", nostr_strerror(result));
    }
    
    // Test 3: Error code to string conversion
    printf("Test 3: Error Code to String Conversion\n");
    printf("---------------------------------------\n");
    
    int error_codes[] = {
        NOSTR_SUCCESS,
        NOSTR_ERROR_INVALID_INPUT,
        NOSTR_ERROR_CRYPTO_FAILED,
        NOSTR_ERROR_MEMORY_FAILED,
        NOSTR_ERROR_IO_FAILED,
        NOSTR_ERROR_NETWORK_FAILED,
        -999 // Unknown error code
    };
    
    int num_errors = sizeof(error_codes) / sizeof(error_codes[0]);
    
    for (int i = 0; i < num_errors; i++) {
        int code = error_codes[i];
        const char* message = nostr_strerror(code);
        printf("Error code %d: %s\n", code, message);
    }
    printf("\n");
    
    // Test 4: Invalid hex string handling
    printf("Test 4: Invalid Hex String Handling\n");
    printf("------------------------------------\n");
    
    const char* invalid_hex_strings[] = {
        "invalid_hex_string",        // Non-hex characters
        "5dab087e624a8a4b79e17f8b",  // Too short (24 chars, need 64)
        "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0ebaa", // Too long (66 chars)
        "",                         // Empty string
        "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eZ" // Invalid hex char 'Z'
    };
    
    int num_invalid = sizeof(invalid_hex_strings) / sizeof(invalid_hex_strings[0]);
    
    for (int i = 0; i < num_invalid; i++) {
        printf("Testing invalid hex: \"%s\"\n", invalid_hex_strings[i]);
        
        unsigned char invalid_output[32];
        result = nostr_hex_to_bytes(invalid_hex_strings[i], invalid_output, sizeof(invalid_output));
        
        if (result == NOSTR_SUCCESS) {
            printf("  ✗ Unexpectedly succeeded (should have failed)\n");
        } else {
            printf("  ✓ Correctly failed: %s\n", nostr_strerror(result));
        }
    }
    printf("\n");
    
    // Test 5: Working with real NOSTR keys
    printf("Test 5: Real NOSTR Key Conversion\n");
    printf("---------------------------------\n");
    
    // Generate a real keypair
    unsigned char private_key[NOSTR_PRIVATE_KEY_SIZE];
    unsigned char public_key[NOSTR_PUBLIC_KEY_SIZE];
    
    result = nostr_generate_keypair(private_key, public_key);
    if (result == NOSTR_SUCCESS) {
        // Convert to hex
        char private_hex[NOSTR_HEX_KEY_SIZE];
        char public_hex[NOSTR_HEX_KEY_SIZE];
        
        nostr_bytes_to_hex(private_key, NOSTR_PRIVATE_KEY_SIZE, private_hex);
        nostr_bytes_to_hex(public_key, NOSTR_PUBLIC_KEY_SIZE, public_hex);
        
        printf("Generated NOSTR keys:\n");
        printf("Private key (hex): %s\n", private_hex);
        printf("Public key (hex):  %s\n", public_hex);
        
        // Convert back to bytes to verify
        unsigned char recovered_private[NOSTR_PRIVATE_KEY_SIZE];
        unsigned char recovered_public[NOSTR_PUBLIC_KEY_SIZE];
        
        int priv_result = nostr_hex_to_bytes(private_hex, recovered_private, NOSTR_PRIVATE_KEY_SIZE);
        int pub_result = nostr_hex_to_bytes(public_hex, recovered_public, NOSTR_PUBLIC_KEY_SIZE);
        
        if (priv_result == NOSTR_SUCCESS && pub_result == NOSTR_SUCCESS) {
            int priv_match = memcmp(private_key, recovered_private, NOSTR_PRIVATE_KEY_SIZE) == 0;
            int pub_match = memcmp(public_key, recovered_public, NOSTR_PUBLIC_KEY_SIZE) == 0;
            
            printf("Key recovery verification:\n");
            printf("  Private key: %s\n", priv_match ? "✓ PASSED" : "✗ FAILED");
            printf("  Public key:  %s\n", pub_match ? "✓ PASSED" : "✗ FAILED");
        }
    }
    
    // Cleanup
    nostr_cleanup();
    
    printf("\n✓ Example completed successfully!\n");
    printf("💡 Utility functions handle format conversions and error reporting\n");
    return 0;
}
