/*
 * Example application demonstrating how to integrate nostr_core into other projects
 * This shows a complete workflow from key generation to event publishing
 */

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

// Example application configuration
typedef struct {
    char* app_name;
    char* version;
    int debug_mode;
} app_config_t;

static app_config_t g_config = {
    .app_name = "My NOSTR App",
    .version = "1.0.0",
    .debug_mode = 1
};

// Helper function to print hex data
static void print_hex(const char* label, const unsigned char* data, size_t len) {
    if (g_config.debug_mode) {
        printf("%s: ", label);
        for (size_t i = 0; i < len; i++) {
            printf("%02x", data[i]);
        }
        printf("\n");
    }
}

// Helper function to print JSON nicely
static void print_event(const char* label, cJSON* event) {
    if (!event) {
        printf("%s: NULL\n", label);
        return;
    }
    
    char* json_string = cJSON_Print(event);
    if (json_string) {
        printf("%s:\n%s\n", label, json_string);
        free(json_string);
    }
}

// Example: Generate and manage identity
static int demo_identity_management(void) {
    printf("\n=== Identity Management Demo ===\n");
    
    unsigned char private_key[32], public_key[32];
    char nsec[100], npub[100];
    
    // Generate a new keypair
    printf("Generating new keypair...\n");
    int ret = nostr_generate_keypair(private_key, public_key);
    if (ret != NOSTR_SUCCESS) {
        printf("Error generating keypair: %s\n", nostr_strerror(ret));
        return ret;
    }
    
    print_hex("Private Key", private_key, 32);
    print_hex("Public Key", public_key, 32);
    
    // Convert to bech32 format
    ret = nostr_key_to_bech32(private_key, "nsec", nsec);
    if (ret != NOSTR_SUCCESS) {
        printf("Error encoding nsec: %s\n", nostr_strerror(ret));
        return ret;
    }
    
    ret = nostr_key_to_bech32(public_key, "npub", npub);
    if (ret != NOSTR_SUCCESS) {
        printf("Error encoding npub: %s\n", nostr_strerror(ret));
        return ret;
    }
    
    printf("nsec: %s\n", nsec);
    printf("npub: %s\n", npub);
    
    return NOSTR_SUCCESS;
}

// Example: Create different types of events
static int demo_event_creation(const unsigned char* private_key) {
    printf("\n=== Event Creation Demo ===\n");
    
    // Create a text note
    printf("Creating text note...\n");
    cJSON* text_event = nostr_create_text_event("Hello from my NOSTR app!", private_key);
    if (!text_event) {
        printf("Error creating text event\n");
        return NOSTR_ERROR_JSON_PARSE;
    }
    print_event("Text Event", text_event);
    
    // Create a profile event
    printf("\nCreating profile event...\n");
    cJSON* profile_event = nostr_create_profile_event(
        g_config.app_name, 
        "A sample application demonstrating NOSTR integration",
        private_key
    );
    if (!profile_event) {
        printf("Error creating profile event\n");
        cJSON_Delete(text_event);
        return NOSTR_ERROR_JSON_PARSE;
    }
    print_event("Profile Event", profile_event);
    
    // Cleanup
    cJSON_Delete(text_event);
    cJSON_Delete(profile_event);
    
    return NOSTR_SUCCESS;
}

// Example: Handle different input formats
static int demo_input_handling(const char* user_input) {
    printf("\n=== Input Handling Demo ===\n");
    printf("Processing input: %s\n", user_input);
    
    // Detect input type
    int input_type = nostr_detect_input_type(user_input);
    switch (input_type) {
        case NOSTR_INPUT_MNEMONIC:
            printf("Detected: BIP39 Mnemonic\n");
            {
                unsigned char priv[32], pub[32];
                int ret = nostr_derive_keys_from_mnemonic(user_input, 0, priv, pub);
                if (ret == NOSTR_SUCCESS) {
                    print_hex("Derived Private Key", priv, 32);
                    print_hex("Derived Public Key", pub, 32);
                }
            }
            break;
            
        case NOSTR_INPUT_NSEC_HEX:
            printf("Detected: Hex-encoded private key\n");
            {
                unsigned char decoded[32];
                int ret = nostr_decode_nsec(user_input, decoded);
                if (ret == NOSTR_SUCCESS) {
                    print_hex("Decoded Private Key", decoded, 32);
                }
            }
            break;
            
        case NOSTR_INPUT_NSEC_BECH32:
            printf("Detected: Bech32-encoded private key (nsec)\n");
            {
                unsigned char decoded[32];
                int ret = nostr_decode_nsec(user_input, decoded);
                if (ret == NOSTR_SUCCESS) {
                    print_hex("Decoded Private Key", decoded, 32);
                }
            }
            break;
            
        default:
            printf("Unknown input format\n");
            return NOSTR_ERROR_INVALID_INPUT;
    }
    
    return NOSTR_SUCCESS;
}

// Example: Demonstrate utility functions
static int demo_utilities(void) {
    printf("\n=== Utility Functions Demo ===\n");
    
    // Hex conversion
    const char* test_hex = "deadbeef";
    unsigned char bytes[4];
    char hex_result[9];
    
    printf("Testing hex conversion with: %s\n", test_hex);
    
    int ret = nostr_hex_to_bytes(test_hex, bytes, 4);
    if (ret != NOSTR_SUCCESS) {
        printf("Error in hex_to_bytes: %s\n", nostr_strerror(ret));
        return ret;
    }
    
    nostr_bytes_to_hex(bytes, 4, hex_result);
    printf("Round-trip result: %s\n", hex_result);
    
    // Error message testing
    printf("\nTesting error messages:\n");
    for (int i = 0; i >= -10; i--) {
        const char* msg = nostr_strerror(i);
        if (msg && strlen(msg) > 0) {
            printf("  %d: %s\n", i, msg);
        }
    }
    
    return NOSTR_SUCCESS;
}

int main(int argc, char* argv[]) {
    printf("%s v%s\n", g_config.app_name, g_config.version);
    printf("NOSTR Core Integration Example\n");
    printf("=====================================\n");
    
    // Initialize the NOSTR library
    printf("Initializing NOSTR core library...\n");
    int ret = nostr_init();
    if (ret != NOSTR_SUCCESS) {
        printf("Failed to initialize NOSTR library: %s\n", nostr_strerror(ret));
        return 1;
    }
    
    // Run demonstrations
    unsigned char demo_private_key[32];
    
    // 1. Identity management
    ret = demo_identity_management();
    if (ret != NOSTR_SUCCESS) {
        goto cleanup;
    }
    
    // Generate a key for other demos
    nostr_generate_keypair(demo_private_key, NULL);
    
    // 2. Event creation
    ret = demo_event_creation(demo_private_key);
    if (ret != NOSTR_SUCCESS) {
        goto cleanup;
    }
    
    // 3. Input handling (use command line argument if provided)
    const char* test_input = (argc > 1) ? argv[1] : 
        "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
    ret = demo_input_handling(test_input);
    if (ret != NOSTR_SUCCESS && ret != NOSTR_ERROR_INVALID_INPUT) {
        goto cleanup;
    }
    
    // 4. Utility functions
    ret = demo_utilities();
    if (ret != NOSTR_SUCCESS) {
        goto cleanup;
    }
    
    printf("\n=====================================\n");
    printf("All demonstrations completed successfully!\n");
    printf("\nThis example shows how to:\n");
    printf("  • Initialize the NOSTR library\n");
    printf("  • Generate and manage keypairs\n");
    printf("  • Create and sign different event types\n");
    printf("  • Handle various input formats\n");
    printf("  • Use utility functions\n");
    printf("  • Clean up resources properly\n");
    
    ret = NOSTR_SUCCESS;

cleanup:
    // Clean up the NOSTR library
    printf("\nCleaning up NOSTR library...\n");
    nostr_cleanup();
    
    if (ret == NOSTR_SUCCESS) {
        printf("Example completed successfully.\n");
        return 0;
    } else {
        printf("Example failed with error: %s\n", nostr_strerror(ret));
        return 1;
    }
}
