/*
 * Ginxsom Admin Commands Implementation
 */

#include "admin_commands.h"
#include "../nostr_core_lib/nostr_core/nostr_core.h"
#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

// Forward declare app_log
typedef enum {
    LOG_DEBUG = 0,
    LOG_INFO = 1,
    LOG_WARN = 2,
    LOG_ERROR = 3
} log_level_t;

void app_log(log_level_t level, const char* format, ...);

// Global state
static struct {
    int initialized;
    char db_path[512];
} g_admin_state = {0};

// Initialize admin command system
int admin_commands_init(const char *db_path) {
    if (g_admin_state.initialized) {
        return 0;
    }
    
    strncpy(g_admin_state.db_path, db_path, sizeof(g_admin_state.db_path) - 1);
    g_admin_state.initialized = 1;
    
    app_log(LOG_INFO, "Admin command system initialized");
    return 0;
}

// NIP-44 encryption helper
int admin_encrypt_response(
    const unsigned char* server_privkey,
    const unsigned char* admin_pubkey,
    const char* plaintext_json,
    char* output,
    size_t output_size
) {
    int result = nostr_nip44_encrypt(
        server_privkey,
        admin_pubkey,
        plaintext_json,
        output,
        output_size
    );
    
    if (result != 0) {
        app_log(LOG_ERROR, "Failed to encrypt admin response: %d", result);
        return -1;
    }
    
    return 0;
}

// NIP-44 decryption helper
int admin_decrypt_command(
    const unsigned char* server_privkey,
    const unsigned char* admin_pubkey,
    const char* encrypted_data,
    char* output,
    size_t output_size
) {
    int result = nostr_nip44_decrypt(
        server_privkey,
        admin_pubkey,
        encrypted_data,
        output,
        output_size
    );
    
    if (result != 0) {
        app_log(LOG_ERROR, "Failed to decrypt admin command: %d", result);
        return -1;
    }
    
    return 0;
}

// Create error response
static cJSON* create_error_response(const char* query_type, const char* error_msg) {
    cJSON* response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "query_type", query_type);
    cJSON_AddStringToObject(response, "status", "error");
    cJSON_AddStringToObject(response, "error", error_msg);
    cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
    return response;
}

// Process admin command array and generate response
cJSON* admin_commands_process(cJSON* command_array, const char* request_event_id) {
    (void)request_event_id;  // Reserved for future use (e.g., logging, tracking)
    
    if (!cJSON_IsArray(command_array) || cJSON_GetArraySize(command_array) < 1) {
        return create_error_response("unknown", "Invalid command format");
    }
    
    cJSON* cmd_type = cJSON_GetArrayItem(command_array, 0);
    if (!cJSON_IsString(cmd_type)) {
        return create_error_response("unknown", "Command type must be string");
    }
    
    const char* command = cmd_type->valuestring;
    app_log(LOG_INFO, "Processing admin command: %s", command);
    
    // Route to appropriate handler
    if (strcmp(command, "config_query") == 0) {
        return admin_cmd_config_query(command_array);
    }
    else if (strcmp(command, "config_update") == 0) {
        return admin_cmd_config_update(command_array);
    }
    else if (strcmp(command, "stats_query") == 0) {
        return admin_cmd_stats_query(command_array);
    }
    else if (strcmp(command, "system_command") == 0) {
        // Check second parameter for system_status
        if (cJSON_GetArraySize(command_array) >= 2) {
            cJSON* subcmd = cJSON_GetArrayItem(command_array, 1);
            if (cJSON_IsString(subcmd) && strcmp(subcmd->valuestring, "system_status") == 0) {
                return admin_cmd_system_status(command_array);
            }
        }
        return create_error_response("system_command", "Unknown system command");
    }
    else if (strcmp(command, "blob_list") == 0) {
        return admin_cmd_blob_list(command_array);
    }
    else if (strcmp(command, "storage_stats") == 0) {
        return admin_cmd_storage_stats(command_array);
    }
    else if (strcmp(command, "sql_query") == 0) {
        return admin_cmd_sql_query(command_array);
    }
    else if (strcmp(command, "query_view") == 0) {
        return admin_cmd_query_view(command_array);
    }
    // Auth rules management commands (c-relay compatible)
    else if (strcmp(command, "blacklist") == 0 || strcmp(command, "whitelist") == 0) {
        return admin_cmd_auth_add_rule(command_array);
    }
    else if (strcmp(command, "delete_auth_rule") == 0) {
        return admin_cmd_auth_delete_rule(command_array);
    }
    else if (strcmp(command, "auth_query") == 0) {
        return admin_cmd_auth_query(command_array);
    }
    else {
        char error_msg[256];
        snprintf(error_msg, sizeof(error_msg), "Unknown command: %s", command);
        return create_error_response("unknown", error_msg);
    }
}

// ============================================================================
// COMMAND HANDLERS (Stub implementations - to be completed)
// ============================================================================

cJSON* admin_cmd_config_query(cJSON* args) {
    cJSON* response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "query_type", "config_query");
    
    // Open database
    sqlite3* db;
    int rc = sqlite3_open_v2(g_admin_state.db_path, &db, SQLITE_OPEN_READONLY, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to open database");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    // Check if specific keys were requested (args[1] should be array of keys, null, or "all" for all)
    cJSON* keys_array = NULL;
    if (cJSON_GetArraySize(args) >= 2) {
        keys_array = cJSON_GetArrayItem(args, 1);
        // Accept array, null, or string "all" for querying all configs
        if (!cJSON_IsArray(keys_array) && !cJSON_IsNull(keys_array)) {
            // Check if it's the string "all"
            if (cJSON_IsString(keys_array) && strcmp(keys_array->valuestring, "all") == 0) {
                // Treat "all" as null (query all configs)
                keys_array = NULL;
            } else {
                cJSON_AddStringToObject(response, "status", "error");
                cJSON_AddStringToObject(response, "error", "Keys parameter must be array, null, or \"all\"");
                cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
                sqlite3_close(db);
                return response;
            }
        }
    }
    
    sqlite3_stmt* stmt;
    const char* sql;
    
    if (keys_array && cJSON_IsArray(keys_array) && cJSON_GetArraySize(keys_array) > 0) {
        // Query specific keys
        int key_count = cJSON_GetArraySize(keys_array);
        
        // Build SQL with placeholders
        char sql_buffer[1024] = "SELECT key, value, description FROM config WHERE key IN (?";
        for (int i = 1; i < key_count && i < 50; i++) {  // Limit to 50 keys
            strncat(sql_buffer, ",?", sizeof(sql_buffer) - strlen(sql_buffer) - 1);
        }
        strncat(sql_buffer, ")", sizeof(sql_buffer) - strlen(sql_buffer) - 1);
        
        rc = sqlite3_prepare_v2(db, sql_buffer, -1, &stmt, NULL);
        if (rc != SQLITE_OK) {
            cJSON_AddStringToObject(response, "status", "error");
            cJSON_AddStringToObject(response, "error", "Failed to prepare query");
            cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
            sqlite3_close(db);
            return response;
        }
        
        // Bind keys
        for (int i = 0; i < key_count && i < 50; i++) {
            cJSON* key_item = cJSON_GetArrayItem(keys_array, i);
            if (cJSON_IsString(key_item)) {
                sqlite3_bind_text(stmt, i + 1, key_item->valuestring, -1, SQLITE_STATIC);
            }
        }
    } else {
        // Query all config values
        sql = "SELECT key, value, description FROM config ORDER BY key";
        rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
        if (rc != SQLITE_OK) {
            cJSON_AddStringToObject(response, "status", "error");
            cJSON_AddStringToObject(response, "error", "Failed to prepare query");
            cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
            sqlite3_close(db);
            return response;
        }
    }
    
    // Execute query and build result
    cJSON* config_obj = cJSON_CreateObject();
    int count = 0;
    
    while ((rc = 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);
        const char* description = (const char*)sqlite3_column_text(stmt, 2);
        
        cJSON* entry = cJSON_CreateObject();
        cJSON_AddStringToObject(entry, "value", value ? value : "");
        if (description && strlen(description) > 0) {
            cJSON_AddStringToObject(entry, "description", description);
        }
        
        cJSON_AddItemToObject(config_obj, key, entry);
        count++;
    }
    
    sqlite3_finalize(stmt);
    sqlite3_close(db);
    
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddNumberToObject(response, "count", count);
    cJSON_AddItemToObject(response, "config", config_obj);
    cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
    
    app_log(LOG_INFO, "Config query returned %d entries", count);
    
    return response;
}

cJSON* admin_cmd_config_update(cJSON* args) {
    cJSON* response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "query_type", "config_update");
    
    // Expected format: ["config_update", [{key: "x", value: "y", data_type: "z", category: "w"}]]
    if (cJSON_GetArraySize(args) < 2) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Missing config updates array");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    cJSON* updates = cJSON_GetArrayItem(args, 1);
    if (!cJSON_IsArray(updates)) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Updates must be an array of config objects");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    // Open database for writing
    sqlite3* db;
    int rc = sqlite3_open_v2(g_admin_state.db_path, &db, SQLITE_OPEN_READWRITE, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to open database");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    // Prepare update statement
    const char* sql = "UPDATE config SET value = ?, updated_at = strftime('%s', 'now') WHERE key = ?";
    sqlite3_stmt* stmt;
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to prepare update statement");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        sqlite3_close(db);
        return response;
    }
    
    // Process each update - expecting array of config objects
    cJSON* data_array = cJSON_CreateArray();
    int success_count = 0;
    int fail_count = 0;
    
    cJSON* config_obj = NULL;
    cJSON_ArrayForEach(config_obj, updates) {
        if (!cJSON_IsObject(config_obj)) {
            fail_count++;
            continue;
        }
        
        cJSON* key_item = cJSON_GetObjectItem(config_obj, "key");
        cJSON* value_item = cJSON_GetObjectItem(config_obj, "value");
        
        if (!cJSON_IsString(key_item) || !cJSON_IsString(value_item)) {
            fail_count++;
            continue;
        }
        
        const char* key = key_item->valuestring;
        const char* value = value_item->valuestring;
        
        sqlite3_reset(stmt);
        sqlite3_bind_text(stmt, 1, value, -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(stmt, 2, key, -1, SQLITE_TRANSIENT);
        
        rc = sqlite3_step(stmt);
        
        // Create result object for this config update
        cJSON* result_obj = cJSON_CreateObject();
        cJSON_AddStringToObject(result_obj, "key", key);
        
        if (rc == SQLITE_DONE && sqlite3_changes(db) > 0) {
            cJSON_AddStringToObject(result_obj, "status", "success");
            cJSON_AddStringToObject(result_obj, "value", value);
            
            // Add optional fields if present
            cJSON* data_type_item = cJSON_GetObjectItem(config_obj, "data_type");
            if (cJSON_IsString(data_type_item)) {
                cJSON_AddStringToObject(result_obj, "data_type", data_type_item->valuestring);
            }
            
            success_count++;
            app_log(LOG_INFO, "Updated config key: %s = %s", key, value);
        } else {
            cJSON_AddStringToObject(result_obj, "status", "error");
            cJSON_AddStringToObject(result_obj, "error", "Failed to update");
            fail_count++;
        }
        
        cJSON_AddItemToArray(data_array, result_obj);
    }
    
    sqlite3_finalize(stmt);
    sqlite3_close(db);
    
    cJSON_AddStringToObject(response, "status", success_count > 0 ? "success" : "error");
    cJSON_AddNumberToObject(response, "updates_applied", success_count);
    cJSON_AddItemToObject(response, "data", data_array);
    cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
    
    return response;
}

cJSON* admin_cmd_stats_query(cJSON* args) {
    (void)args;
    
    cJSON* response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "query_type", "stats_query");
    
    // Open database
    sqlite3* db;
    int rc = sqlite3_open_v2(g_admin_state.db_path, &db, SQLITE_OPEN_READONLY, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to open database");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    // Query storage stats view
    const char* sql = "SELECT * FROM storage_stats";
    sqlite3_stmt* stmt;
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to query stats");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        sqlite3_close(db);
        return response;
    }
    
    cJSON* stats = cJSON_CreateObject();
    if (sqlite3_step(stmt) == SQLITE_ROW) {
        cJSON_AddNumberToObject(stats, "total_blobs", sqlite3_column_int64(stmt, 0));
        cJSON_AddNumberToObject(stats, "total_bytes", sqlite3_column_int64(stmt, 1));
        cJSON_AddNumberToObject(stats, "avg_blob_size", sqlite3_column_double(stmt, 2));
        cJSON_AddNumberToObject(stats, "first_upload", sqlite3_column_int64(stmt, 3));
        cJSON_AddNumberToObject(stats, "last_upload", sqlite3_column_int64(stmt, 4));
        cJSON_AddNumberToObject(stats, "unique_uploaders", sqlite3_column_int64(stmt, 5));
    }
    
    sqlite3_finalize(stmt);
    
    // Get auth rules count
    sql = "SELECT COUNT(*) FROM auth_rules WHERE active = 1";
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc == SQLITE_OK && sqlite3_step(stmt) == SQLITE_ROW) {
        cJSON_AddNumberToObject(stats, "active_auth_rules", sqlite3_column_int(stmt, 0));
    }
    sqlite3_finalize(stmt);
    
    sqlite3_close(db);
    
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddItemToObject(response, "stats", stats);
    cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
    
    return response;
}

cJSON* admin_cmd_system_status(cJSON* args) {
    (void)args;
    
    cJSON* response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "query_type", "system_status");
    
    cJSON* status = cJSON_CreateObject();
    
    // Server uptime (would need to track start time - placeholder for now)
    cJSON_AddStringToObject(status, "server_status", "running");
    cJSON_AddNumberToObject(status, "current_time", (double)time(NULL));
    
    // Database status
    sqlite3* db;
    int rc = sqlite3_open_v2(g_admin_state.db_path, &db, SQLITE_OPEN_READONLY, NULL);
    if (rc == SQLITE_OK) {
        cJSON_AddStringToObject(status, "database_status", "connected");
        
        // Get database size
        sqlite3_stmt* stmt;
        const char* sql = "SELECT page_count * page_size as size FROM pragma_page_count(), pragma_page_size()";
        if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) == SQLITE_OK) {
            if (sqlite3_step(stmt) == SQLITE_ROW) {
                cJSON_AddNumberToObject(status, "database_size_bytes", sqlite3_column_int64(stmt, 0));
            }
            sqlite3_finalize(stmt);
        }
        
        sqlite3_close(db);
    } else {
        cJSON_AddStringToObject(status, "database_status", "error");
    }
    
    // Memory info (basic - would need more system calls for detailed info)
    cJSON_AddStringToObject(status, "memory_status", "ok");
    
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddItemToObject(response, "system", status);
    cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
    
    return response;
}

cJSON* admin_cmd_blob_list(cJSON* args) {
    cJSON* response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "query_type", "blob_list");
    
    // Parse optional parameters: limit, offset, uploader_pubkey
    int limit = 100;  // Default limit
    int offset = 0;
    const char* uploader_filter = NULL;
    
    if (cJSON_GetArraySize(args) >= 2) {
        cJSON* params = cJSON_GetArrayItem(args, 1);
        if (cJSON_IsObject(params)) {
            cJSON* limit_item = cJSON_GetObjectItem(params, "limit");
            if (cJSON_IsNumber(limit_item)) {
                limit = limit_item->valueint;
                if (limit > 1000) limit = 1000;  // Max 1000
                if (limit < 1) limit = 1;
            }
            
            cJSON* offset_item = cJSON_GetObjectItem(params, "offset");
            if (cJSON_IsNumber(offset_item)) {
                offset = offset_item->valueint;
                if (offset < 0) offset = 0;
            }
            
            cJSON* uploader_item = cJSON_GetObjectItem(params, "uploader");
            if (cJSON_IsString(uploader_item)) {
                uploader_filter = uploader_item->valuestring;
            }
        }
    }
    
    // Open database
    sqlite3* db;
    int rc = sqlite3_open_v2(g_admin_state.db_path, &db, SQLITE_OPEN_READONLY, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to open database");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    // Build query
    char sql[512];
    if (uploader_filter) {
        snprintf(sql, sizeof(sql),
            "SELECT sha256, size, type, uploaded_at, uploader_pubkey, filename "
            "FROM blobs WHERE uploader_pubkey = ? "
            "ORDER BY uploaded_at DESC LIMIT ? OFFSET ?");
    } else {
        snprintf(sql, sizeof(sql),
            "SELECT sha256, size, type, uploaded_at, uploader_pubkey, filename "
            "FROM blobs ORDER BY uploaded_at DESC LIMIT ? OFFSET ?");
    }
    
    sqlite3_stmt* stmt;
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to prepare query");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        sqlite3_close(db);
        return response;
    }
    
    // Bind parameters
    int param_idx = 1;
    if (uploader_filter) {
        sqlite3_bind_text(stmt, param_idx++, uploader_filter, -1, SQLITE_STATIC);
    }
    sqlite3_bind_int(stmt, param_idx++, limit);
    sqlite3_bind_int(stmt, param_idx++, offset);
    
    // Execute and build results
    cJSON* blobs = cJSON_CreateArray();
    int count = 0;
    
    while (sqlite3_step(stmt) == SQLITE_ROW) {
        cJSON* blob = cJSON_CreateObject();
        cJSON_AddStringToObject(blob, "sha256", (const char*)sqlite3_column_text(stmt, 0));
        cJSON_AddNumberToObject(blob, "size", sqlite3_column_int64(stmt, 1));
        cJSON_AddStringToObject(blob, "type", (const char*)sqlite3_column_text(stmt, 2));
        cJSON_AddNumberToObject(blob, "uploaded_at", sqlite3_column_int64(stmt, 3));
        
        const char* uploader = (const char*)sqlite3_column_text(stmt, 4);
        if (uploader) {
            cJSON_AddStringToObject(blob, "uploader_pubkey", uploader);
        }
        
        const char* filename = (const char*)sqlite3_column_text(stmt, 5);
        if (filename) {
            cJSON_AddStringToObject(blob, "filename", filename);
        }
        
        cJSON_AddItemToArray(blobs, blob);
        count++;
    }
    
    sqlite3_finalize(stmt);
    sqlite3_close(db);
    
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddNumberToObject(response, "count", count);
    cJSON_AddNumberToObject(response, "limit", limit);
    cJSON_AddNumberToObject(response, "offset", offset);
    cJSON_AddItemToObject(response, "blobs", blobs);
    cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
    
    return response;
}

cJSON* admin_cmd_storage_stats(cJSON* args) {
    (void)args;
    
    cJSON* response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "query_type", "storage_stats");
    
    // Open database
    sqlite3* db;
    int rc = sqlite3_open_v2(g_admin_state.db_path, &db, SQLITE_OPEN_READONLY, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to open database");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    cJSON* storage = cJSON_CreateObject();
    
    // Get overall stats from view
    const char* sql = "SELECT * FROM storage_stats";
    sqlite3_stmt* stmt;
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc == SQLITE_OK && sqlite3_step(stmt) == SQLITE_ROW) {
        cJSON_AddNumberToObject(storage, "total_blobs", sqlite3_column_int64(stmt, 0));
        cJSON_AddNumberToObject(storage, "total_bytes", sqlite3_column_int64(stmt, 1));
        cJSON_AddNumberToObject(storage, "avg_blob_size", sqlite3_column_double(stmt, 2));
        cJSON_AddNumberToObject(storage, "first_upload", sqlite3_column_int64(stmt, 3));
        cJSON_AddNumberToObject(storage, "last_upload", sqlite3_column_int64(stmt, 4));
        cJSON_AddNumberToObject(storage, "unique_uploaders", sqlite3_column_int64(stmt, 5));
    }
    sqlite3_finalize(stmt);
    
    // Get stats by MIME type
    sql = "SELECT type, COUNT(*) as count, SUM(size) as total_size "
          "FROM blobs GROUP BY type ORDER BY count DESC LIMIT 10";
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc == SQLITE_OK) {
        cJSON* by_type = cJSON_CreateArray();
        while (sqlite3_step(stmt) == SQLITE_ROW) {
            cJSON* type_stat = cJSON_CreateObject();
            cJSON_AddStringToObject(type_stat, "mime_type", (const char*)sqlite3_column_text(stmt, 0));
            cJSON_AddNumberToObject(type_stat, "count", sqlite3_column_int64(stmt, 1));
            cJSON_AddNumberToObject(type_stat, "total_bytes", sqlite3_column_int64(stmt, 2));
            cJSON_AddItemToArray(by_type, type_stat);
        }
        cJSON_AddItemToObject(storage, "by_mime_type", by_type);
        sqlite3_finalize(stmt);
    }
    
    // Get top uploaders
    sql = "SELECT uploader_pubkey, COUNT(*) as count, SUM(size) as total_size "
          "FROM blobs WHERE uploader_pubkey IS NOT NULL "
          "GROUP BY uploader_pubkey ORDER BY count DESC LIMIT 10";
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc == SQLITE_OK) {
        cJSON* top_uploaders = cJSON_CreateArray();
        while (sqlite3_step(stmt) == SQLITE_ROW) {
            cJSON* uploader_stat = cJSON_CreateObject();
            cJSON_AddStringToObject(uploader_stat, "pubkey", (const char*)sqlite3_column_text(stmt, 0));
            cJSON_AddNumberToObject(uploader_stat, "blob_count", sqlite3_column_int64(stmt, 1));
            cJSON_AddNumberToObject(uploader_stat, "total_bytes", sqlite3_column_int64(stmt, 2));
            cJSON_AddItemToArray(top_uploaders, uploader_stat);
        }
        cJSON_AddItemToObject(storage, "top_uploaders", top_uploaders);
        sqlite3_finalize(stmt);
    }
    
    sqlite3_close(db);
    
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddItemToObject(response, "storage", storage);
    cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
    
    return response;
}

cJSON* admin_cmd_sql_query(cJSON* args) {
    cJSON* response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "query_type", "sql_query");
    
    // Expected format: ["sql_query", "SQL STATEMENT"]
    if (cJSON_GetArraySize(args) < 2) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Missing SQL query");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    cJSON* query_item = cJSON_GetArrayItem(args, 1);
    if (!cJSON_IsString(query_item)) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Query must be a string");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    const char* sql = query_item->valuestring;
    const char* trimmed_sql = sql;
    while (*trimmed_sql && isspace((unsigned char)*trimmed_sql)) {
        trimmed_sql++;
    }
    
    int is_select = strncasecmp(trimmed_sql, "SELECT", 6) == 0;
    int is_delete = strncasecmp(trimmed_sql, "DELETE", 6) == 0;
    int is_update = strncasecmp(trimmed_sql, "UPDATE", 6) == 0;
    int is_insert = strncasecmp(trimmed_sql, "INSERT", 6) == 0;
    
    if (!is_select && !is_delete && !is_update && !is_insert) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Only SELECT, INSERT, UPDATE, or DELETE queries are allowed");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    int open_flags = is_select ? SQLITE_OPEN_READONLY : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
    sqlite3* db;
    int rc = sqlite3_open_v2(g_admin_state.db_path, &db, open_flags, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to open database");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    if (is_select) {
        sqlite3_stmt* stmt;
        rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
        if (rc != SQLITE_OK) {
            cJSON_AddStringToObject(response, "status", "error");
            char error_msg[256];
            snprintf(error_msg, sizeof(error_msg), "SQL error: %s", sqlite3_errmsg(db));
            cJSON_AddStringToObject(response, "error", error_msg);
            cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
            sqlite3_close(db);
            return response;
        }
        
        int col_count = sqlite3_column_count(stmt);
        cJSON* columns = cJSON_CreateArray();
        for (int i = 0; i < col_count; i++) {
            cJSON_AddItemToArray(columns, cJSON_CreateString(sqlite3_column_name(stmt, i)));
        }
        
        cJSON* rows = cJSON_CreateArray();
        int row_count = 0;
        const int MAX_ROWS = 1000;
        while (row_count < MAX_ROWS && (rc = sqlite3_step(stmt)) == SQLITE_ROW) {
            cJSON* row = cJSON_CreateArray();
            for (int i = 0; i < col_count; i++) {
                int col_type = sqlite3_column_type(stmt, i);
                switch (col_type) {
                    case SQLITE_INTEGER:
                        cJSON_AddItemToArray(row, cJSON_CreateNumber(sqlite3_column_int64(stmt, i)));
                        break;
                    case SQLITE_FLOAT:
                        cJSON_AddItemToArray(row, cJSON_CreateNumber(sqlite3_column_double(stmt, i)));
                        break;
                    case SQLITE_TEXT:
                        cJSON_AddItemToArray(row, cJSON_CreateString((const char*)sqlite3_column_text(stmt, i)));
                        break;
                    case SQLITE_NULL:
                        cJSON_AddItemToArray(row, cJSON_CreateNull());
                        break;
                    default:
                        cJSON_AddItemToArray(row, cJSON_CreateString(""));
                }
            }
            cJSON_AddItemToArray(rows, row);
            row_count++;
        }
        
        sqlite3_finalize(stmt);
        sqlite3_close(db);
        
        cJSON_AddStringToObject(response, "status", "success");
        cJSON_AddItemToObject(response, "columns", columns);
        cJSON_AddItemToObject(response, "rows", rows);
        cJSON_AddNumberToObject(response, "row_count", row_count);
        if (row_count >= MAX_ROWS) {
            cJSON_AddBoolToObject(response, "truncated", 1);
        }
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        
        app_log(LOG_INFO, "SQL query executed: %d rows returned", row_count);
        return response;
    }
    
    // Handle DELETE/UPDATE/INSERT
    sqlite3_stmt* stmt;
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        char error_msg[256];
        snprintf(error_msg, sizeof(error_msg), "SQL error: %s", sqlite3_errmsg(db));
        cJSON_AddStringToObject(response, "error", error_msg);
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        sqlite3_close(db);
        return response;
    }
    
    rc = sqlite3_step(stmt);
    if (rc != SQLITE_DONE) {
        cJSON_AddStringToObject(response, "status", "error");
        char error_msg[256];
        snprintf(error_msg, sizeof(error_msg), "SQL execution error: %s", sqlite3_errmsg(db));
        cJSON_AddStringToObject(response, "error", error_msg);
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        sqlite3_finalize(stmt);
        sqlite3_close(db);
        return response;
    }
    
    int affected_rows = sqlite3_changes(db);
    sqlite3_finalize(stmt);
    sqlite3_close(db);
    
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddNumberToObject(response, "affected_rows", affected_rows);
    cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
    
    app_log(LOG_INFO, "SQL modification executed: %d rows affected", affected_rows);
    return response;
}

cJSON* admin_cmd_query_view(cJSON* args) {
    cJSON* response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "query_type", "query_view");
    
    // Expected format: ["query_view", "view_name"]
    if (cJSON_GetArraySize(args) < 2) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Missing view name");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    cJSON* view_name_item = cJSON_GetArrayItem(args, 1);
    if (!cJSON_IsString(view_name_item)) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "View name must be a string");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    const char* view_name = view_name_item->valuestring;
    
    // Open database
    sqlite3* db;
    int rc = sqlite3_open_v2(g_admin_state.db_path, &db, SQLITE_OPEN_READONLY, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to open database");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    // Build SQL query based on view name
    char sql[512];
    
    if (strcmp(view_name, "blob_overview") == 0) {
        // Query blob_overview view
        snprintf(sql, sizeof(sql), "SELECT * FROM blob_overview");
    } else if (strcmp(view_name, "storage_stats") == 0) {
        // Query storage_stats view
        snprintf(sql, sizeof(sql), "SELECT * FROM storage_stats");
    } else if (strcmp(view_name, "blob_type_distribution") == 0) {
        // Query blob_type_distribution view
        snprintf(sql, sizeof(sql), "SELECT * FROM blob_type_distribution");
    } else if (strcmp(view_name, "blob_time_stats") == 0) {
        // Query blob_time_stats view
        snprintf(sql, sizeof(sql), "SELECT * FROM blob_time_stats");
    } else if (strcmp(view_name, "top_uploaders") == 0) {
        // Query top_uploaders view
        snprintf(sql, sizeof(sql), "SELECT * FROM top_uploaders");
    } else {
        cJSON_AddStringToObject(response, "status", "error");
        char error_msg[256];
        snprintf(error_msg, sizeof(error_msg), "Unknown view: %s", view_name);
        cJSON_AddStringToObject(response, "error", error_msg);
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        sqlite3_close(db);
        return response;
    }
    
    sqlite3_stmt* stmt;
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        char error_msg[256];
        snprintf(error_msg, sizeof(error_msg), "Failed to prepare query: %s", sqlite3_errmsg(db));
        cJSON_AddStringToObject(response, "error", error_msg);
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        sqlite3_close(db);
        return response;
    }
    
    // Execute query and build results
    int col_count = sqlite3_column_count(stmt);
    cJSON* columns = cJSON_CreateArray();
    for (int i = 0; i < col_count; i++) {
        cJSON_AddItemToArray(columns, cJSON_CreateString(sqlite3_column_name(stmt, i)));
    }
    
    cJSON* rows = cJSON_CreateArray();
    int row_count = 0;
    
    while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
        cJSON* row = cJSON_CreateArray();
        for (int i = 0; i < col_count; i++) {
            int col_type = sqlite3_column_type(stmt, i);
            switch (col_type) {
                case SQLITE_INTEGER:
                    cJSON_AddItemToArray(row, cJSON_CreateNumber(sqlite3_column_int64(stmt, i)));
                    break;
                case SQLITE_FLOAT:
                    cJSON_AddItemToArray(row, cJSON_CreateNumber(sqlite3_column_double(stmt, i)));
                    break;
                case SQLITE_TEXT:
                    cJSON_AddItemToArray(row, cJSON_CreateString((const char*)sqlite3_column_text(stmt, i)));
                    break;
                case SQLITE_NULL:
                    cJSON_AddItemToArray(row, cJSON_CreateNull());
                    break;
                default:
                    cJSON_AddItemToArray(row, cJSON_CreateString(""));
            }
        }
        cJSON_AddItemToArray(rows, row);
        row_count++;
    }
    
    sqlite3_finalize(stmt);
    sqlite3_close(db);
    
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddStringToObject(response, "view_name", view_name);
    cJSON_AddItemToObject(response, "columns", columns);
    cJSON_AddItemToObject(response, "rows", rows);
    cJSON_AddNumberToObject(response, "row_count", row_count);
    cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
    
    app_log(LOG_INFO, "View query executed: %s (%d rows)", view_name, row_count);
    
    return response;
}

// ============================================================================
// AUTH RULES MANAGEMENT COMMANDS (c-relay compatible)
// ============================================================================

// Add blacklist or whitelist rule
// Format: ["blacklist", "pubkey", "abc123..."] or ["whitelist", "pubkey", "def456..."]
cJSON* admin_cmd_auth_add_rule(cJSON* args) {
    cJSON* response = cJSON_CreateObject();
    
    // Get command type (blacklist or whitelist)
    cJSON* cmd_type = cJSON_GetArrayItem(args, 0);
    if (!cJSON_IsString(cmd_type)) {
        cJSON_AddStringToObject(response, "query_type", "auth_add_rule");
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Invalid command type");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    const char* command = cmd_type->valuestring;
    const char* rule_type_prefix = command; // "blacklist" or "whitelist"
    
    // Expected format: ["blacklist/whitelist", "pattern_type", "pattern_value"]
    if (cJSON_GetArraySize(args) < 3) {
        cJSON_AddStringToObject(response, "query_type", "auth_add_rule");
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Missing parameters. Format: [\"blacklist/whitelist\", \"pattern_type\", \"pattern_value\"]");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    cJSON* pattern_type_item = cJSON_GetArrayItem(args, 1);
    cJSON* pattern_value_item = cJSON_GetArrayItem(args, 2);
    
    if (!cJSON_IsString(pattern_type_item) || !cJSON_IsString(pattern_value_item)) {
        cJSON_AddStringToObject(response, "query_type", "auth_add_rule");
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Pattern type and value must be strings");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    const char* pattern_type = pattern_type_item->valuestring;
    const char* pattern_value = pattern_value_item->valuestring;
    
    char rule_type[64];
    snprintf(rule_type, sizeof(rule_type), "%s_%s", rule_type_prefix, pattern_type);
    
    // Validate pattern_type
    if (strcmp(pattern_type, "pubkey") != 0 && strcmp(pattern_type, "hash") != 0 && strcmp(pattern_type, "mime") != 0) {
        cJSON_AddStringToObject(response, "query_type", "auth_add_rule");
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Invalid pattern_type. Must be 'pubkey', 'hash', or 'mime'");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    // Open database
    sqlite3* db;
    int rc = sqlite3_open_v2(g_admin_state.db_path, &db, SQLITE_OPEN_READWRITE, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "query_type", "auth_add_rule");
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to open database");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    // Insert rule
    const char* sql = "INSERT INTO auth_rules (rule_type, pattern_type, pattern_value) VALUES (?, ?, ?)";
    sqlite3_stmt* stmt;
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "query_type", "auth_add_rule");
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to prepare insert statement");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        sqlite3_close(db);
        return response;
    }
    
    sqlite3_bind_text(stmt, 1, rule_type, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, pattern_type, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 3, pattern_value, -1, SQLITE_STATIC);
    
    rc = sqlite3_step(stmt);
    int rule_id = 0;
    
    if (rc == SQLITE_DONE) {
        rule_id = sqlite3_last_insert_rowid(db);
        cJSON_AddStringToObject(response, "query_type", "auth_add_rule");
        cJSON_AddStringToObject(response, "status", "success");
        cJSON_AddNumberToObject(response, "rule_id", rule_id);
        cJSON_AddStringToObject(response, "rule_type", rule_type);
        cJSON_AddStringToObject(response, "pattern_type", pattern_type);
        cJSON_AddStringToObject(response, "pattern_value", pattern_value);
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        
        app_log(LOG_INFO, "Added %s rule: %s=%s (ID: %d)", rule_type, pattern_type, pattern_value, rule_id);
    } else {
        cJSON_AddStringToObject(response, "query_type", "auth_add_rule");
        cJSON_AddStringToObject(response, "status", "error");
        char error_msg[256];
        snprintf(error_msg, sizeof(error_msg), "Failed to insert rule: %s", sqlite3_errmsg(db));
        cJSON_AddStringToObject(response, "error", error_msg);
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
    }
    
    sqlite3_finalize(stmt);
    sqlite3_close(db);
    
    return response;
}

// Delete auth rule
// Format: ["delete_auth_rule", "blacklist", "pubkey", "abc123..."]
cJSON* admin_cmd_auth_delete_rule(cJSON* args) {
    cJSON* response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "query_type", "delete_auth_rule");
    
    // Expected format: ["delete_auth_rule", "rule_type", "pattern_type", "pattern_value"]
    if (cJSON_GetArraySize(args) < 4) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Missing parameters. Format: [\"delete_auth_rule\", \"blacklist/whitelist\", \"pattern_type\", \"pattern_value\"]");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    cJSON* rule_type_item = cJSON_GetArrayItem(args, 1);
    cJSON* pattern_type_item = cJSON_GetArrayItem(args, 2);
    cJSON* pattern_value_item = cJSON_GetArrayItem(args, 3);
    
    if (!cJSON_IsString(rule_type_item) || !cJSON_IsString(pattern_type_item) || !cJSON_IsString(pattern_value_item)) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "All parameters must be strings");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    const char* rule_type_str = cJSON_GetStringValue(rule_type_item);
    const char* pattern_type = cJSON_GetStringValue(pattern_type_item);
    const char* pattern_value = cJSON_GetStringValue(pattern_value_item);
    
    char full_rule_type[64];
    snprintf(full_rule_type, sizeof(full_rule_type), "%s_%s", rule_type_str, pattern_type);
    
    // Open database
    sqlite3* db;
    int rc = sqlite3_open_v2(g_admin_state.db_path, &db, SQLITE_OPEN_READWRITE, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to open database");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    // Delete rule
    const char* sql = "DELETE FROM auth_rules WHERE rule_type = ? AND pattern_type = ? AND pattern_value = ?";
    sqlite3_stmt* stmt;
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to prepare delete statement");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        sqlite3_close(db);
        return response;
    }
    
    sqlite3_bind_text(stmt, 1, full_rule_type, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, pattern_type, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 3, pattern_value, -1, SQLITE_STATIC);
    
    rc = sqlite3_step(stmt);
    int changes = sqlite3_changes(db);
    
    if (rc == SQLITE_DONE) {
        cJSON_AddStringToObject(response, "status", "success");
        cJSON_AddNumberToObject(response, "deleted_count", changes);
        cJSON_AddStringToObject(response, "rule_type", full_rule_type);
        cJSON_AddStringToObject(response, "pattern_type", pattern_type);
        cJSON_AddStringToObject(response, "pattern_value", pattern_value);
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        
        app_log(LOG_INFO, "Deleted %d %s rule(s): %s=%s", changes, full_rule_type, pattern_type, pattern_value);
    } else {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to delete rule");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
    }
    
    sqlite3_finalize(stmt);
    sqlite3_close(db);
    
    return response;
}

// Query auth rules
// Format: ["auth_query", "all"] or ["auth_query", "whitelist"] or ["auth_query", "pattern", "abc123..."]
cJSON* admin_cmd_auth_query(cJSON* args) {
    cJSON* response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "query_type", "auth_query");
    
    // Get query type
    const char* query_type = "all";
    const char* filter_value = NULL;
    
    if (cJSON_GetArraySize(args) >= 2) {
        cJSON* query_type_item = cJSON_GetArrayItem(args, 1);
        if (cJSON_IsString(query_type_item)) {
            query_type = query_type_item->valuestring;
        }
    }
    
    if (cJSON_GetArraySize(args) >= 3) {
        cJSON* filter_value_item = cJSON_GetArrayItem(args, 2);
        if (cJSON_IsString(filter_value_item)) {
            filter_value = filter_value_item->valuestring;
        }
    }
    
    // Open database
    sqlite3* db;
    int rc = sqlite3_open_v2(g_admin_state.db_path, &db, SQLITE_OPEN_READONLY, NULL);
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to open database");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        return response;
    }
    
    // Build SQL query based on query type
    char sql[512];
    sqlite3_stmt* stmt;
    
    if (strcmp(query_type, "all") == 0) {
        snprintf(sql, sizeof(sql), "SELECT id, rule_type, pattern_type, pattern_value, active, created_at, updated_at FROM auth_rules ORDER BY id");
        rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    }
    else if (strcmp(query_type, "blacklist") == 0 || strcmp(query_type, "whitelist") == 0) {
        snprintf(sql, sizeof(sql), "SELECT id, rule_type, pattern_type, pattern_value, active, created_at, updated_at FROM auth_rules WHERE rule_type LIKE ? || '_%%' ORDER BY id");
        rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
        if (rc == SQLITE_OK) {
            sqlite3_bind_text(stmt, 1, query_type, -1, SQLITE_STATIC);
        }
    }
    else if (strcmp(query_type, "pattern") == 0 && filter_value) {
        snprintf(sql, sizeof(sql), "SELECT id, rule_type, pattern_type, pattern_value, active, created_at, updated_at FROM auth_rules WHERE pattern_value = ? ORDER BY id");
        rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
        if (rc == SQLITE_OK) {
            sqlite3_bind_text(stmt, 1, filter_value, -1, SQLITE_STATIC);
        }
    }
    else {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Invalid query type. Use 'all', 'blacklist', 'whitelist', or 'pattern'");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        sqlite3_close(db);
        return response;
    }
    
    if (rc != SQLITE_OK) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "error", "Failed to prepare query");
        cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
        sqlite3_close(db);
        return response;
    }
    
    // Execute query and build results
    cJSON* rules = cJSON_CreateArray();
    int count = 0;
    
    while (sqlite3_step(stmt) == SQLITE_ROW) {
        cJSON* rule = cJSON_CreateObject();
        cJSON_AddNumberToObject(rule, "id", sqlite3_column_int(stmt, 0));
        cJSON_AddStringToObject(rule, "rule_type", (const char*)sqlite3_column_text(stmt, 1));
        cJSON_AddStringToObject(rule, "pattern_type", (const char*)sqlite3_column_text(stmt, 2));
        cJSON_AddStringToObject(rule, "pattern_value", (const char*)sqlite3_column_text(stmt, 3));
        cJSON_AddNumberToObject(rule, "active", sqlite3_column_int(stmt, 4));
        cJSON_AddNumberToObject(rule, "created_at", sqlite3_column_int64(stmt, 5));
        cJSON_AddNumberToObject(rule, "updated_at", sqlite3_column_int64(stmt, 6));
        
        cJSON_AddItemToArray(rules, rule);
        count++;
    }
    
    sqlite3_finalize(stmt);
    sqlite3_close(db);
    
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddNumberToObject(response, "count", count);
    cJSON_AddStringToObject(response, "filter", query_type);
    cJSON_AddItemToObject(response, "rules", rules);
    cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
    
    app_log(LOG_INFO, "Auth query executed: %d rules returned (filter: %s)", count, query_type);
    
    return response;
}