#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <cjson/cJSON.h>
#include "../nostr_core_lib/nostr_core/nostr_core.h"

// External database connection (from main.c)
extern sqlite3* g_db;

// Global configuration manager instance
config_manager_t g_config_manager = {0};

// Logging functions (defined in main.c)
extern void log_info(const char* message);
extern void log_success(const char* message);
extern void log_warning(const char* message);
extern void log_error(const char* message);

// ================================
// CORE CONFIGURATION FUNCTIONS
// ================================

int init_configuration_system(void) {
    log_info("Initializing configuration system...");
    
    // Clear configuration manager state
    memset(&g_config_manager, 0, sizeof(config_manager_t));
    g_config_manager.db = g_db;
    
    // Get XDG configuration directory
    if (get_xdg_config_dir(g_config_manager.config_dir_path, sizeof(g_config_manager.config_dir_path)) != 0) {
        log_error("Failed to determine XDG configuration directory");
        return -1;
    }
    
    // Build configuration file path
    snprintf(g_config_manager.config_file_path, sizeof(g_config_manager.config_file_path),
             "%s/%s", g_config_manager.config_dir_path, CONFIG_FILE_NAME);
    
    log_info("Configuration directory: %s");
    printf("  %s\n", g_config_manager.config_dir_path);
    log_info("Configuration file: %s");
    printf("  %s\n", g_config_manager.config_file_path);
    
    // Initialize database prepared statements
    if (init_config_database_statements() != 0) {
        log_error("Failed to initialize configuration database statements");
        return -1;
    }
    
    // Generate configuration file if missing
    if (generate_config_file_if_missing() != 0) {
        log_warning("Failed to generate configuration file, continuing with database configuration");
    }
    
    // Load configuration from all sources
    if (load_configuration() != 0) {
        log_error("Failed to load configuration");
        return -1;
    }
    
    // Apply configuration to global variables
    if (apply_configuration_to_globals() != 0) {
        log_error("Failed to apply configuration to global variables");
        return -1;
    }
    
    log_success("Configuration system initialized successfully");
    return 0;
}

void cleanup_configuration_system(void) {
    log_info("Cleaning up configuration system...");
    
    // Finalize prepared statements
    if (g_config_manager.get_config_stmt) {
        sqlite3_finalize(g_config_manager.get_config_stmt);
        g_config_manager.get_config_stmt = NULL;
    }
    if (g_config_manager.set_config_stmt) {
        sqlite3_finalize(g_config_manager.set_config_stmt);
        g_config_manager.set_config_stmt = NULL;
    }
    if (g_config_manager.log_change_stmt) {
        sqlite3_finalize(g_config_manager.log_change_stmt);
        g_config_manager.log_change_stmt = NULL;
    }
    
    // Clear manager state
    memset(&g_config_manager, 0, sizeof(config_manager_t));
    
    log_success("Configuration system cleaned up");
}

int load_configuration(void) {
    log_info("Loading configuration from all sources...");
    
    // Try to load configuration from file first
    if (config_file_exists()) {
        log_info("Configuration file found, attempting to load...");
        if (load_config_from_file() == 0) {
            g_config_manager.file_config_loaded = 1;
            log_success("File configuration loaded successfully");
        } else {
            log_warning("Failed to load file configuration, falling back to database");
        }
    } else {
        log_info("No configuration file found, checking database");
    }
    
    // Load configuration from database (either as primary or fallback)
    if (load_config_from_database() == 0) {
        g_config_manager.database_config_loaded = 1;
        log_success("Database configuration loaded");
    } else {
        log_error("Failed to load database configuration");
        return -1;
    }
    
    g_config_manager.last_reload = time(NULL);
    return 0;
}

int apply_configuration_to_globals(void) {
    log_info("Applying configuration to global variables...");
    
    // Apply configuration values to existing global variables
    // This would update the existing hardcoded values with database values
    
    // For now, this is a placeholder - in Phase 4 we'll implement
    // the actual mapping to existing global variables
    
    log_success("Configuration applied to global variables");
    return 0;
}

// ================================
// DATABASE CONFIGURATION FUNCTIONS
// ================================

int init_config_database_statements(void) {
    if (!g_db) {
        log_error("Database connection not available for configuration");
        return -1;
    }
    
    log_info("Initializing configuration database statements...");
    
    // Prepare statement for getting configuration values
    const char* get_sql = "SELECT value FROM server_config WHERE key = ?";
    int rc = sqlite3_prepare_v2(g_db, get_sql, -1, &g_config_manager.get_config_stmt, NULL);
    if (rc != SQLITE_OK) {
        log_error("Failed to prepare get_config statement");
        return -1;
    }
    
    // Prepare statement for setting configuration values
    const char* set_sql = "INSERT OR REPLACE INTO server_config (key, value, updated_at) VALUES (?, ?, strftime('%s', 'now'))";
    rc = sqlite3_prepare_v2(g_db, set_sql, -1, &g_config_manager.set_config_stmt, NULL);
    if (rc != SQLITE_OK) {
        log_error("Failed to prepare set_config statement");
        return -1;
    }
    
    // Prepare statement for logging configuration changes
    const char* log_sql = "INSERT INTO config_history (config_key, old_value, new_value, changed_by) VALUES (?, ?, ?, ?)";
    rc = sqlite3_prepare_v2(g_db, log_sql, -1, &g_config_manager.log_change_stmt, NULL);
    if (rc != SQLITE_OK) {
        log_error("Failed to prepare log_change statement");
        return -1;
    }
    
    log_success("Configuration database statements initialized");
    return 0;
}

int get_database_config(const char* key, char* value, size_t value_size) {
    if (!key || !value || !g_config_manager.get_config_stmt) {
        return -1;
    }
    
    // Reset and bind parameters
    sqlite3_reset(g_config_manager.get_config_stmt);
    sqlite3_bind_text(g_config_manager.get_config_stmt, 1, key, -1, SQLITE_STATIC);
    
    int result = -1;
    if (sqlite3_step(g_config_manager.get_config_stmt) == SQLITE_ROW) {
        const char* db_value = (const char*)sqlite3_column_text(g_config_manager.get_config_stmt, 0);
        if (db_value) {
            strncpy(value, db_value, value_size - 1);
            value[value_size - 1] = '\0';
            result = 0;
        }
    }
    
    return result;
}

int set_database_config(const char* key, const char* new_value, const char* changed_by) {
    if (!key || !new_value || !g_config_manager.set_config_stmt) {
        return -1;
    }
    
    // Get old value for logging
    char old_value[CONFIG_VALUE_MAX_LENGTH] = {0};
    get_database_config(key, old_value, sizeof(old_value));
    
    // Set new value
    sqlite3_reset(g_config_manager.set_config_stmt);
    sqlite3_bind_text(g_config_manager.set_config_stmt, 1, key, -1, SQLITE_STATIC);
    sqlite3_bind_text(g_config_manager.set_config_stmt, 2, new_value, -1, SQLITE_STATIC);
    
    int result = 0;
    if (sqlite3_step(g_config_manager.set_config_stmt) != SQLITE_DONE) {
        log_error("Failed to set configuration value");
        result = -1;
    } else {
        // Log the change
        if (g_config_manager.log_change_stmt) {
            sqlite3_reset(g_config_manager.log_change_stmt);
            sqlite3_bind_text(g_config_manager.log_change_stmt, 1, key, -1, SQLITE_STATIC);
            sqlite3_bind_text(g_config_manager.log_change_stmt, 2, strlen(old_value) > 0 ? old_value : NULL, -1, SQLITE_STATIC);
            sqlite3_bind_text(g_config_manager.log_change_stmt, 3, new_value, -1, SQLITE_STATIC);
            sqlite3_bind_text(g_config_manager.log_change_stmt, 4, changed_by ? changed_by : "system", -1, SQLITE_STATIC);
            sqlite3_step(g_config_manager.log_change_stmt);
        }
    }
    
    return result;
}

int load_config_from_database(void) {
    log_info("Loading configuration from database...");
    
    // Database configuration is already populated by schema defaults
    // This function validates that the configuration tables exist and are accessible
    
    const char* test_sql = "SELECT COUNT(*) FROM server_config WHERE config_type IN ('system', 'user')";
    sqlite3_stmt* test_stmt;
    
    int rc = sqlite3_prepare_v2(g_db, test_sql, -1, &test_stmt, NULL);
    if (rc != SQLITE_OK) {
        log_error("Failed to prepare database configuration test query");
        return -1;
    }
    
    int config_count = 0;
    if (sqlite3_step(test_stmt) == SQLITE_ROW) {
        config_count = sqlite3_column_int(test_stmt, 0);
    }
    
    sqlite3_finalize(test_stmt);
    
    if (config_count > 0) {
        log_success("Database configuration validated (%d entries)");
        printf("  Found %d configuration entries\n", config_count);
        return 0;
    } else {
        log_error("No configuration entries found in database");
        return -1;
    }
}

// ================================
// FILE CONFIGURATION FUNCTIONS
// ================================

int get_xdg_config_dir(char* path, size_t path_size) {
    const char* xdg_config_home = getenv("XDG_CONFIG_HOME");
    
    if (xdg_config_home && strlen(xdg_config_home) > 0) {
        // Use XDG_CONFIG_HOME if set
        snprintf(path, path_size, "%s/%s", xdg_config_home, CONFIG_XDG_DIR_NAME);
    } else {
        // Fall back to ~/.config
        const char* home = getenv("HOME");
        if (!home) {
            log_error("Neither XDG_CONFIG_HOME nor HOME environment variable is set");
            return -1;
        }
        snprintf(path, path_size, "%s/.config/%s", home, CONFIG_XDG_DIR_NAME);
    }
    
    return 0;
}

int config_file_exists(void) {
    struct stat st;
    return (stat(g_config_manager.config_file_path, &st) == 0);
}

int load_config_from_file(void) {
    log_info("Loading configuration from file...");
    
    FILE* file = fopen(g_config_manager.config_file_path, "r");
    if (!file) {
        log_error("Failed to open configuration file");
        return -1;
    }
    
    // Read file contents
    fseek(file, 0, SEEK_END);
    long file_size = ftell(file);
    fseek(file, 0, SEEK_SET);
    
    char* file_content = malloc(file_size + 1);
    if (!file_content) {
        log_error("Failed to allocate memory for configuration file");
        fclose(file);
        return -1;
    }
    
    size_t read_size = fread(file_content, 1, file_size, file);
    file_content[read_size] = '\0';
    fclose(file);
    
    // Parse JSON
    cJSON* json = cJSON_Parse(file_content);
    free(file_content);
    
    if (!json) {
        log_error("Failed to parse configuration file as JSON");
        return -1;
    }
    
    // Validate Nostr event structure
    int result = validate_and_apply_config_event(json);
    cJSON_Delete(json);
    
    if (result == 0) {
        log_success("Configuration loaded from file successfully");
    } else {
        log_error("Configuration file validation failed");
    }
    
    return result;
}

// ================================
// NOSTR EVENT VALIDATION FUNCTIONS
// ================================

int validate_nostr_event_structure(const cJSON* event) {
    if (!event || !cJSON_IsObject(event)) {
        log_error("Configuration event is not a valid JSON object");
        return -1;
    }
    
    // Check required fields
    cJSON* kind = cJSON_GetObjectItem(event, "kind");
    cJSON* created_at = cJSON_GetObjectItem(event, "created_at");
    cJSON* tags = cJSON_GetObjectItem(event, "tags");
    cJSON* content = cJSON_GetObjectItem(event, "content");
    cJSON* pubkey = cJSON_GetObjectItem(event, "pubkey");
    cJSON* id = cJSON_GetObjectItem(event, "id");
    cJSON* sig = cJSON_GetObjectItem(event, "sig");
    
    if (!kind || !cJSON_IsNumber(kind)) {
        log_error("Configuration event missing or invalid 'kind' field");
        return -1;
    }
    
    if (cJSON_GetNumberValue(kind) != 33334) {
        log_error("Configuration event has wrong kind (expected 33334)");
        return -1;
    }
    
    if (!created_at || !cJSON_IsNumber(created_at)) {
        log_error("Configuration event missing or invalid 'created_at' field");
        return -1;
    }
    
    if (!tags || !cJSON_IsArray(tags)) {
        log_error("Configuration event missing or invalid 'tags' field");
        return -1;
    }
    
    if (!content || !cJSON_IsString(content)) {
        log_error("Configuration event missing or invalid 'content' field");
        return -1;
    }
    
    if (!pubkey || !cJSON_IsString(pubkey)) {
        log_error("Configuration event missing or invalid 'pubkey' field");
        return -1;
    }
    
    if (!id || !cJSON_IsString(id)) {
        log_error("Configuration event missing or invalid 'id' field");
        return -1;
    }
    
    if (!sig || !cJSON_IsString(sig)) {
        log_error("Configuration event missing or invalid 'sig' field");
        return -1;
    }
    
    // Validate pubkey format (64 hex characters)
    const char* pubkey_str = cJSON_GetStringValue(pubkey);
    if (strlen(pubkey_str) != 64) {
        log_error("Configuration event pubkey has invalid length");
        return -1;
    }
    
    // Validate id format (64 hex characters)
    const char* id_str = cJSON_GetStringValue(id);
    if (strlen(id_str) != 64) {
        log_error("Configuration event id has invalid length");
        return -1;
    }
    
    // Validate signature format (128 hex characters)
    const char* sig_str = cJSON_GetStringValue(sig);
    if (strlen(sig_str) != 128) {
        log_error("Configuration event signature has invalid length");
        return -1;
    }
    
    log_info("Configuration event structure validation passed");
    return 0;
}

int validate_config_tags(const cJSON* tags) {
    if (!tags || !cJSON_IsArray(tags)) {
        return -1;
    }
    
    int tag_count = 0;
    const cJSON* tag = NULL;
    
    cJSON_ArrayForEach(tag, tags) {
        if (!cJSON_IsArray(tag)) {
            log_error("Configuration tag is not an array");
            return -1;
        }
        
        int tag_size = cJSON_GetArraySize(tag);
        if (tag_size < 2) {
            log_error("Configuration tag has insufficient elements");
            return -1;
        }
        
        cJSON* key = cJSON_GetArrayItem(tag, 0);
        cJSON* value = cJSON_GetArrayItem(tag, 1);
        
        if (!key || !cJSON_IsString(key) || !value || !cJSON_IsString(value)) {
            log_error("Configuration tag key or value is not a string");
            return -1;
        }
        
        tag_count++;
    }
    
    log_info("Configuration tags validation passed (%d tags)");
    printf("  Found %d configuration tags\n", tag_count);
    return 0;
}

int extract_and_apply_config_tags(const cJSON* tags) {
    if (!tags || !cJSON_IsArray(tags)) {
        return -1;
    }
    
    int applied_count = 0;
    const cJSON* tag = NULL;
    
    cJSON_ArrayForEach(tag, tags) {
        cJSON* key = cJSON_GetArrayItem(tag, 0);
        cJSON* value = cJSON_GetArrayItem(tag, 1);
        
        if (!key || !value) continue;
        
        const char* key_str = cJSON_GetStringValue(key);
        const char* value_str = cJSON_GetStringValue(value);
        
        if (!key_str || !value_str) continue;
        
        // Validate configuration value
        config_validation_result_t validation = validate_config_value(key_str, value_str);
        if (validation != CONFIG_VALID) {
            log_config_validation_error(key_str, value_str, "Value failed validation");
            continue;
        }
        
        // Apply configuration to database
        if (set_database_config(key_str, value_str, "file") == 0) {
            applied_count++;
        } else {
            log_error("Failed to apply configuration");
            printf("  Key: %s, Value: %s\n", key_str, value_str);
        }
    }
    
    if (applied_count > 0) {
        log_success("Applied configuration from file");
        printf("  Applied %d configuration values\n", applied_count);
        return 0;
    } else {
        log_warning("No valid configuration values found in file");
        return -1;
    }
}

int validate_and_apply_config_event(const cJSON* event) {
    log_info("Validating configuration event...");
    
    // Step 1: Validate event structure
    if (validate_nostr_event_structure(event) != 0) {
        return -1;
    }
    
    // Step 2: Extract and validate tags
    cJSON* tags = cJSON_GetObjectItem(event, "tags");
    if (validate_config_tags(tags) != 0) {
        return -1;
    }
    
    // Step 3: For now, skip signature verification (would require Nostr crypto library)
    // In production, this would verify the event signature against admin pubkeys
    log_warning("Signature verification not yet implemented - accepting event");
    
    // Step 4: Extract and apply configuration
    if (extract_and_apply_config_tags(tags) != 0) {
        return -1;
    }
    
    log_success("Configuration event validation and application completed");
    return 0;
}

// ================================
// CONFIGURATION ACCESS FUNCTIONS
// ================================

const char* get_config_value(const char* key) {
    static char buffer[CONFIG_VALUE_MAX_LENGTH];
    
    if (!key) {
        return NULL;
    }
    
    // Priority 1: Database configuration (updated from file)
    if (get_database_config(key, buffer, sizeof(buffer)) == 0) {
        return buffer;
    }
    
    // Priority 2: Environment variables (fallback)
    const char* env_value = getenv(key);
    if (env_value) {
        return env_value;
    }
    
    // No value found
    return NULL;
}

int get_config_int(const char* key, int default_value) {
    const char* str_value = get_config_value(key);
    if (!str_value) {
        return default_value;
    }
    
    char* endptr;
    long val = strtol(str_value, &endptr, 10);
    
    if (endptr == str_value || *endptr != '\0') {
        // Invalid integer format
        return default_value;
    }
    
    return (int)val;
}

int get_config_bool(const char* key, int default_value) {
    const char* str_value = get_config_value(key);
    if (!str_value) {
        return default_value;
    }
    
    // Check for boolean values
    if (strcasecmp(str_value, "true") == 0 || 
        strcasecmp(str_value, "yes") == 0 || 
        strcasecmp(str_value, "1") == 0) {
        return 1;
    } else if (strcasecmp(str_value, "false") == 0 || 
               strcasecmp(str_value, "no") == 0 || 
               strcasecmp(str_value, "0") == 0) {
        return 0;
    }
    
    return default_value;
}

int set_config_value(const char* key, const char* value) {
    if (!key || !value) {
        return -1;
    }
    
    return set_database_config(key, value, "api");
}

// ================================
// CONFIGURATION VALIDATION
// ================================

config_validation_result_t validate_config_value(const char* key, const char* value) {
    // Placeholder for validation logic
    // Will implement full validation in Phase 3
    
    if (!key || !value) {
        return CONFIG_MISSING_REQUIRED;
    }
    
    // Basic validation - all values are valid for now
    return CONFIG_VALID;
}

void log_config_validation_error(const char* key, const char* value, const char* error) {
    log_error("Configuration validation error");
    printf("  Key: %s\n", key ? key : "NULL");
    printf("  Value: %s\n", value ? value : "NULL");
    printf("  Error: %s\n", error ? error : "Unknown error");
}

// ================================
// UTILITY FUNCTIONS
// ================================

const char* config_type_to_string(config_type_t type) {
    switch (type) {
        case CONFIG_TYPE_SYSTEM: return "system";
        case CONFIG_TYPE_USER: return "user";
        case CONFIG_TYPE_RUNTIME: return "runtime";
        default: return "unknown";
    }
}

const char* config_data_type_to_string(config_data_type_t type) {
    switch (type) {
        case CONFIG_DATA_STRING: return "string";
        case CONFIG_DATA_INTEGER: return "integer";
        case CONFIG_DATA_BOOLEAN: return "boolean";
        case CONFIG_DATA_JSON: return "json";
        default: return "unknown";
    }
}

config_type_t string_to_config_type(const char* str) {
    if (!str) return CONFIG_TYPE_USER;
    
    if (strcmp(str, "system") == 0) return CONFIG_TYPE_SYSTEM;
    if (strcmp(str, "user") == 0) return CONFIG_TYPE_USER;
    if (strcmp(str, "runtime") == 0) return CONFIG_TYPE_RUNTIME;
    
    return CONFIG_TYPE_USER;
}

config_data_type_t string_to_config_data_type(const char* str) {
    if (!str) return CONFIG_DATA_STRING;
    
    if (strcmp(str, "string") == 0) return CONFIG_DATA_STRING;
    if (strcmp(str, "integer") == 0) return CONFIG_DATA_INTEGER;
    if (strcmp(str, "boolean") == 0) return CONFIG_DATA_BOOLEAN;
    if (strcmp(str, "json") == 0) return CONFIG_DATA_JSON;
    
    return CONFIG_DATA_STRING;
}

int config_requires_restart(const char* key) {
    if (!key) return 0;
    
    // Check database for requires_restart flag
    const char* sql = "SELECT requires_restart FROM server_config WHERE key = ?";
    sqlite3_stmt* stmt;
    
    int rc = sqlite3_prepare_v2(g_db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        return 0;
    }
    
    sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
    
    int requires_restart = 0;
    if (sqlite3_step(stmt) == SQLITE_ROW) {
        requires_restart = sqlite3_column_int(stmt, 0);
    }
    
    sqlite3_finalize(stmt);
    return requires_restart;
}

// ================================
// NOSTR EVENT GENERATION FUNCTIONS
// ================================

#include <sys/stat.h>

cJSON* create_config_nostr_event(const char* privkey_hex) {
    log_info("Creating configuration Nostr event...");
    
    // Convert hex private key to bytes
    unsigned char privkey_bytes[32];
    if (nostr_hex_to_bytes(privkey_hex, privkey_bytes, 32) != 0) {
        log_error("Failed to convert private key from hex");
        return NULL;
    }
    
    // Create tags array with default configuration values
    cJSON* tags = cJSON_CreateArray();
    
    // Default configuration values (moved from schema.sql)
    typedef struct {
        const char* key;
        const char* value;
    } default_config_t;
    
    static const default_config_t defaults[] = {
        // Administrative settings
        {"admin_enabled", "false"},
        
        // Server core settings
        {"relay_port", "8888"},
        {"database_path", "db/c_nostr_relay.db"},
        {"max_connections", "100"},
        
        // NIP-11 Relay Information
        {"relay_name", "C Nostr Relay"},
        {"relay_description", "High-performance C Nostr relay with SQLite storage"},
        {"relay_contact", ""},
        {"relay_pubkey", ""},
        {"relay_software", "https://git.laantungir.net/laantungir/c-relay.git"},
        {"relay_version", "0.2.0"},
        
        // NIP-13 Proof of Work
        {"pow_enabled", "true"},
        {"pow_min_difficulty", "0"},
        {"pow_mode", "basic"},
        
        // NIP-40 Expiration Timestamp
        {"expiration_enabled", "true"},
        {"expiration_strict", "true"},
        {"expiration_filter", "true"},
        {"expiration_grace_period", "300"},
        
        // Subscription limits
        {"max_subscriptions_per_client", "25"},
        {"max_total_subscriptions", "5000"},
        {"max_filters_per_subscription", "10"},
        
        // Event processing limits
        {"max_event_tags", "100"},
        {"max_content_length", "8196"},
        {"max_message_length", "16384"},
        
        // Performance settings
        {"default_limit", "500"},
        {"max_limit", "5000"}
    };
    
    int defaults_count = sizeof(defaults) / sizeof(defaults[0]);
    
    // First try to load from database, fall back to defaults
    const char* sql = "SELECT key, value FROM server_config WHERE config_type IN ('system', 'user') ORDER BY key";
    sqlite3_stmt* stmt;
    
    int rc = sqlite3_prepare_v2(g_db, sql, -1, &stmt, NULL);
    if (rc == SQLITE_OK) {
        // Load existing values from database
        while (sqlite3_step(stmt) == SQLITE_ROW) {
            const char* key = (const char*)sqlite3_column_text(stmt, 0);
            const char* value = (const char*)sqlite3_column_text(stmt, 1);
            
            // Skip admin_pubkey since it's redundant (already in event.pubkey)
            if (key && value && strcmp(key, "admin_pubkey") != 0) {
                cJSON* tag = cJSON_CreateArray();
                cJSON_AddItemToArray(tag, cJSON_CreateString(key));
                cJSON_AddItemToArray(tag, cJSON_CreateString(value));
                cJSON_AddItemToArray(tags, tag);
            }
        }
        sqlite3_finalize(stmt);
    }
    
    // If database is empty, use defaults
    if (cJSON_GetArraySize(tags) == 0) {
        log_info("Database empty, using default configuration values");
        for (int i = 0; i < defaults_count; i++) {
            cJSON* tag = cJSON_CreateArray();
            cJSON_AddItemToArray(tag, cJSON_CreateString(defaults[i].key));
            cJSON_AddItemToArray(tag, cJSON_CreateString(defaults[i].value));
            cJSON_AddItemToArray(tags, tag);
        }
    }
    
    // Create and sign event using nostr_core_lib
    cJSON* event = nostr_create_and_sign_event(
        33334,                                          // kind
        "C Nostr Relay configuration event",           // content
        tags,                                           // tags
        privkey_bytes,                                  // private key bytes for signing
        time(NULL)                                      // created_at timestamp
    );
    
    cJSON_Delete(tags); // Clean up tags as they were duplicated in nostr_create_and_sign_event
    
    if (!event) {
        log_error("Failed to create and sign configuration event");
        return NULL;
    }
    
    // Log success information
    cJSON* id_obj = cJSON_GetObjectItem(event, "id");
    cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
    
    if (id_obj && pubkey_obj) {
        log_success("Configuration Nostr event created successfully");
        printf("  Event ID: %s\n", cJSON_GetStringValue(id_obj));
        printf("  Public Key: %s\n", cJSON_GetStringValue(pubkey_obj));
    }
    
    return event;
}

int write_config_event_to_file(const cJSON* event) {
    if (!event) {
        return -1;
    }
    
    // Ensure config directory exists
    struct stat st = {0};
    if (stat(g_config_manager.config_dir_path, &st) == -1) {
        if (mkdir(g_config_manager.config_dir_path, 0700) != 0) {
            log_error("Failed to create configuration directory");
            return -1;
        }
        log_info("Created configuration directory: %s");
        printf("  %s\n", g_config_manager.config_dir_path);
    }
    
    // Write to file with custom formatting for better readability
    FILE* file = fopen(g_config_manager.config_file_path, "w");
    if (!file) {
        log_error("Failed to open configuration file for writing");
        return -1;
    }
    
    // Custom formatting: tags first, then other fields
    fprintf(file, "{\n");
    
    // First, write tags array with each tag on its own line
    cJSON* tags = cJSON_GetObjectItem(event, "tags");
    if (tags && cJSON_IsArray(tags)) {
        fprintf(file, "  \"tags\": [\n");
        int tag_count = cJSON_GetArraySize(tags);
        for (int i = 0; i < tag_count; i++) {
            cJSON* tag = cJSON_GetArrayItem(tags, i);
            if (tag && cJSON_IsArray(tag)) {
                char* tag_str = cJSON_Print(tag);
                if (tag_str) {
                    fprintf(file, "    %s%s\n", tag_str, (i < tag_count - 1) ? "," : "");
                    free(tag_str);
                }
            }
        }
        fprintf(file, "  ],\n");
    }
    
    // Then write other fields in order
    const char* field_order[] = {"id", "pubkey", "created_at", "kind", "content", "sig"};
    int field_count = sizeof(field_order) / sizeof(field_order[0]);
    
    for (int i = 0; i < field_count; i++) {
        cJSON* field = cJSON_GetObjectItem(event, field_order[i]);
        if (field) {
            fprintf(file, "  \"%s\": ", field_order[i]);
            if (cJSON_IsString(field)) {
                fprintf(file, "\"%s\"", cJSON_GetStringValue(field));
            } else if (cJSON_IsNumber(field)) {
                fprintf(file, "%ld", (long)cJSON_GetNumberValue(field));
            }
            if (i < field_count - 1) {
                fprintf(file, ",");
            }
            fprintf(file, "\n");
        }
    }
    
    fprintf(file, "}\n");
    fclose(file);
    
    log_success("Configuration file written successfully");
    printf("  File: %s\n", g_config_manager.config_file_path);
    
    return 0;
}

int generate_config_file_if_missing(void) {
    // Check if config file already exists
    if (config_file_exists()) {
        log_info("Configuration file already exists, skipping generation");
        return 0;
    }
    
    log_info("Generating missing configuration file...");
    
    // Get private key from environment variable or generate random one
    char privkey_hex[65];
    const char* env_privkey = getenv(CONFIG_PRIVKEY_ENV);
    
    if (env_privkey && strlen(env_privkey) == 64) {
        // Use provided private key
        strncpy(privkey_hex, env_privkey, sizeof(privkey_hex) - 1);
        privkey_hex[sizeof(privkey_hex) - 1] = '\0';
        log_info("Using private key from environment variable");
    } else {
        // Generate random private key manually (nostr_core_lib doesn't have a key generation function)
        FILE* urandom = fopen("/dev/urandom", "rb");
        if (!urandom) {
            log_error("Failed to open /dev/urandom for key generation");
            return -1;
        }
        
        unsigned char privkey_bytes[32];
        if (fread(privkey_bytes, 1, 32, urandom) != 32) {
            log_error("Failed to read random bytes for private key");
            fclose(urandom);
            return -1;
        }
        fclose(urandom);
        
        // Convert to hex
        nostr_bytes_to_hex(privkey_bytes, 32, privkey_hex);
        
        // Generate corresponding public key
        char pubkey_hex[65];
        unsigned char pubkey_bytes[32];
        if (nostr_ec_public_key_from_private_key(privkey_bytes, pubkey_bytes) == 0) {
            nostr_bytes_to_hex(pubkey_bytes, 32, pubkey_hex);
        } else {
            log_error("Failed to derive public key from private key");
            return -1;
        }
        
        log_info("Generated random private key for configuration signing");
        
        // Print the generated private key prominently for the administrator
        printf("\n");
        printf("=================================================================\n");
        printf("IMPORTANT: GENERATED RELAY ADMIN PRIVATE KEY\n");
        printf("=================================================================\n");
        printf("Private Key: %s\n", privkey_hex);
        printf("Public Key:  %s\n", pubkey_hex);
        printf("\nSAVE THIS PRIVATE KEY SECURELY - IT CONTROLS YOUR RELAY!\n");
        printf("\nTo use this key in future sessions:\n");
        printf("  export %s=%s\n", CONFIG_PRIVKEY_ENV, privkey_hex);
        printf("=================================================================\n");
        printf("\n");
        
        char warning_msg[256];
        snprintf(warning_msg, sizeof(warning_msg),
                "To use a specific private key, set the %s environment variable", CONFIG_PRIVKEY_ENV);
        log_warning(warning_msg);
    }
    
    // Create Nostr event
    cJSON* event = create_config_nostr_event(privkey_hex);
    if (!event) {
        log_error("Failed to create configuration event");
        return -1;
    }
    
    // Extract and store the admin public key in database configuration
    cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
    if (pubkey_obj && cJSON_IsString(pubkey_obj)) {
        const char* admin_pubkey = cJSON_GetStringValue(pubkey_obj);
        if (set_database_config("admin_pubkey", admin_pubkey, "system") == 0) {
            log_info("Stored admin public key in configuration database");
            printf("  Admin Public Key: %s\n", admin_pubkey);
        } else {
            log_warning("Failed to store admin public key in database");
        }
    }
    
    // Write to file
    int result = write_config_event_to_file(event);
    cJSON_Delete(event);
    
    if (result == 0) {
        log_success("Configuration file generated successfully");
    } else {
        log_error("Failed to write configuration file");
    }
    
    return result;
}