#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#ifdef __linux__
#include <sys/statvfs.h>
#else
#include <sys/mount.h>
#endif
#include <unistd.h>
#include "ginxsom.h"

// Use global database path from main.c
extern char g_db_path[];

// Function declarations (moved from admin_api.h)
void handle_admin_api_request(const char* method, const char* uri, const char* validated_pubkey, int is_authenticated);
void handle_stats_api(void);
void handle_config_get_api(void);
void handle_config_put_api(void);
void handle_config_key_put_api(const char* key);
void handle_files_api(void);
void handle_health_api(void);
int authenticate_admin_request(const char* auth_header);
int is_admin_enabled(void);
int verify_admin_pubkey(const char* event_pubkey);
void send_json_response(int status, const char* json_content);
void send_json_error(int status, const char* error, const char* message);
int parse_query_params(const char* query_string, char params[][256], int max_params);

// Forward declarations for local utility functions
static int admin_nip94_get_origin(char* out, size_t out_size);
static void admin_nip94_build_blob_url(const char* origin, const char* sha256, const char* mime_type, char* out, size_t out_size);
static const char* admin_mime_to_extension(const char* mime_type);

// Local utility functions (from main.c but implemented here for admin API)
static int admin_nip94_get_origin(char* out, size_t out_size) {
    if (!out || out_size == 0) {
        return 0;
    }

    sqlite3* db;
    sqlite3_stmt* stmt;
    int rc;

    rc = sqlite3_open_v2(g_db_path, &db, SQLITE_OPEN_READONLY, NULL);
    if (rc) {
        // Default on DB error
        strncpy(out, "http://localhost:9001", out_size - 1);
        out[out_size - 1] = '\0';
        return 1;
    }

    const char* sql = "SELECT value FROM config WHERE key = 'cdn_origin'";
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc == SQLITE_OK) {
        rc = sqlite3_step(stmt);
        if (rc == SQLITE_ROW) {
            const char* value = (const char*)sqlite3_column_text(stmt, 0);
            if (value) {
                strncpy(out, value, out_size - 1);
                out[out_size - 1] = '\0';
                sqlite3_finalize(stmt);
                sqlite3_close(db);
                return 1;
            }
        }
        sqlite3_finalize(stmt);
    }

    sqlite3_close(db);

    // Default fallback
    strncpy(out, "http://localhost:9001", out_size - 1);
    out[out_size - 1] = '\0';
    return 1;
}

static void admin_nip94_build_blob_url(const char* origin, const char* sha256,
                                       const char* mime_type, char* out, size_t out_size) {
    if (!origin || !sha256 || !out || out_size == 0) {
        return;
    }

    // Use local admin implementation for extension mapping
    const char* extension = admin_mime_to_extension(mime_type);
    snprintf(out, out_size, "%s/%s%s", origin, sha256, extension);
}

// Centralized MIME type to file extension mapping (from main.c)
static const char* admin_mime_to_extension(const char* mime_type) {
    if (!mime_type) {
        return ".bin";
    }

    if (strstr(mime_type, "image/jpeg")) {
        return ".jpg";
    } else if (strstr(mime_type, "image/webp")) {
        return ".webp";
    } else if (strstr(mime_type, "image/png")) {
        return ".png";
    } else if (strstr(mime_type, "image/gif")) {
        return ".gif";
    } else if (strstr(mime_type, "video/mp4")) {
        return ".mp4";
    } else if (strstr(mime_type, "video/webm")) {
        return ".webm";
    } else if (strstr(mime_type, "audio/mpeg")) {
        return ".mp3";
    } else if (strstr(mime_type, "audio/ogg")) {
        return ".ogg";
    } else if (strstr(mime_type, "text/plain")) {
        return ".txt";
    } else if (strstr(mime_type, "application/pdf")) {
        return ".pdf";
    } else {
        return ".bin";
    }
}

// Main API request handler
void handle_admin_api_request(const char* method, const char* uri, const char* validated_pubkey, int is_authenticated) {
    const char* path = uri + 4; // Skip "/api"

    // Check if admin interface is enabled
    if (!is_admin_enabled()) {
        send_json_error(503, "admin_disabled", "Admin interface is disabled");
        return;
    }

    // Authentication now handled by centralized validation system
    // Health endpoint and POST /admin (Kind 23456 events) are exempt from authentication requirement
    // Kind 23456 events authenticate themselves via signed event validation
    int skip_auth = (strcmp(path, "/health") == 0) ||
                    (strcmp(method, "POST") == 0 && strcmp(path, "/admin") == 0);
    
    if (!skip_auth) {
        if (!is_authenticated || !validated_pubkey) {
            send_json_error(401, "admin_auth_required", "Valid admin authentication required");
            return;
        }
        
        // Verify the authenticated pubkey has admin privileges
        if (!verify_admin_pubkey(validated_pubkey)) {
            send_json_error(403, "admin_forbidden", "Admin privileges required");
            return;
        }
    }

    // Route to appropriate handler
    if (strcmp(method, "GET") == 0) {
        if (strcmp(path, "/stats") == 0) {
            handle_stats_api();
        } else if (strcmp(path, "/config") == 0) {
            handle_config_get_api();
        } else if (strncmp(path, "/files", 6) == 0) {
            handle_files_api();
        } else if (strcmp(path, "/health") == 0) {
            handle_health_api();
        } else {
            send_json_error(404, "not_found", "API endpoint not found");
        }
    } else if (strcmp(method, "POST") == 0) {
        if (strcmp(path, "/admin") == 0) {
            // Handle Kind 23456/23457 admin event commands
            handle_admin_event_request();
        } else {
            send_json_error(404, "not_found", "API endpoint not found");
        }
    } else if (strcmp(method, "PUT") == 0) {
        if (strcmp(path, "/config") == 0) {
            handle_config_put_api();
        } else if (strncmp(path, "/config/", 8) == 0) {
            const char* key = path + 8; // Skip "/config/"
            if (strlen(key) > 0) {
                handle_config_key_put_api(key);
            } else {
                send_json_error(400, "invalid_key", "Configuration key cannot be empty");
            }
        } else {
            send_json_error(405, "method_not_allowed", "Method not allowed");
        }
    } else {
        send_json_error(405, "method_not_allowed", "Method not allowed");
    }
}

// Admin authentication functions
int authenticate_admin_request(const char* auth_header) {
    if (!auth_header) {
        return 0; // No auth header
    }

    // NOTE: Authentication now handled by centralized validation system in main.c
    // This function is kept for compatibility but should receive validation results
    // from the centralized system rather than performing duplicate validation
    
    // TODO: Modify to accept validation results from centralized system
    // For now, assume validation was successful if we reach here
    // and extract pubkey from global context or parameters
    
    return 0; // Temporarily disabled - needs integration with centralized system
}

int verify_admin_pubkey(const char* event_pubkey) {
    if (!event_pubkey) {
        return 0;
    }

    sqlite3* db;
    sqlite3_stmt* stmt;
    int rc, is_admin = 0;

    rc = sqlite3_open_v2(g_db_path, &db, SQLITE_OPEN_READONLY, NULL);
    if (rc) {
        return 0;
    }

    const char* sql = "SELECT value FROM config WHERE key = 'admin_pubkey'";
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc == SQLITE_OK) {
        rc = sqlite3_step(stmt);
        if (rc == SQLITE_ROW) {
            const char* admin_pubkey = (const char*)sqlite3_column_text(stmt, 0);
            if (admin_pubkey && strcmp(event_pubkey, admin_pubkey) == 0) {
                is_admin = 1;
            }
        }
        sqlite3_finalize(stmt);
    }
    sqlite3_close(db);

    return is_admin;
}

int is_admin_enabled(void) {
    sqlite3* db;
    sqlite3_stmt* stmt;
    int rc, enabled = 0;

    rc = sqlite3_open_v2(g_db_path, &db, SQLITE_OPEN_READONLY, NULL);
    if (rc) {
        return 0; // Default disabled if can't access DB
    }

    const char* sql = "SELECT value FROM config WHERE key = 'admin_enabled'";
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc == SQLITE_OK) {
        rc = sqlite3_step(stmt);
        if (rc == SQLITE_ROW) {
            const char* value = (const char*)sqlite3_column_text(stmt, 0);
            enabled = (value && strcmp(value, "true") == 0) ? 1 : 0;
        }
        sqlite3_finalize(stmt);
    }
    sqlite3_close(db);

    return enabled;
}

// Individual endpoint handlers
void handle_stats_api(void) {
    sqlite3* db;
    sqlite3_stmt* stmt;
    int rc;

    rc = sqlite3_open_v2(g_db_path, &db, SQLITE_OPEN_READONLY, NULL);
    if (rc) {
        send_json_error(500, "database_error", "Failed to open database");
        return;
    }

    // Create consolidated statistics view if it doesn't exist
    const char* create_view =
        "CREATE VIEW IF NOT EXISTS storage_stats AS "
        "SELECT "
        "    COUNT(*) as total_blobs, "
        "    SUM(size) as total_bytes, "
        "    AVG(size) as avg_blob_size, "
        "    COUNT(DISTINCT uploader_pubkey) as unique_uploaders, "
        "    MIN(uploaded_at) as first_upload, "
        "    MAX(uploaded_at) as last_upload "
        "FROM blobs";

    rc = sqlite3_exec(db, create_view, NULL, NULL, NULL);
    if (rc != SQLITE_OK) {
        sqlite3_close(db);
        send_json_error(500, "database_error", "Failed to create stats view");
        return;
    }

    // Query storage_stats view
    const char* sql = "SELECT total_blobs, total_bytes, avg_blob_size, "
                      "unique_uploaders, first_upload, last_upload FROM storage_stats";

    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        sqlite3_close(db);
        send_json_error(500, "database_error", "Failed to prepare query");
        return;
    }

    cJSON* response = cJSON_CreateObject();
    cJSON* data = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddItemToObject(response, "data", data);

    rc = sqlite3_step(stmt);
    if (rc == SQLITE_ROW) {
        int total_files = sqlite3_column_int(stmt, 0);
        long long total_bytes = sqlite3_column_int64(stmt, 1);
        double avg_size = sqlite3_column_double(stmt, 2);
        int unique_uploaders = sqlite3_column_int(stmt, 3);

        cJSON_AddNumberToObject(data, "total_files", total_files);
        cJSON_AddNumberToObject(data, "total_bytes", (double)total_bytes);
        cJSON_AddNumberToObject(data, "total_size_mb", (double)total_bytes / (1024 * 1024));
        cJSON_AddNumberToObject(data, "unique_uploaders", unique_uploaders);
        cJSON_AddNumberToObject(data, "first_upload", sqlite3_column_int64(stmt, 4));
        cJSON_AddNumberToObject(data, "last_upload", sqlite3_column_int64(stmt, 5));
        cJSON_AddNumberToObject(data, "avg_file_size", avg_size);

        // Get file type distribution
        sqlite3_stmt* type_stmt;
        const char* type_sql = "SELECT type, COUNT(*) FROM blobs GROUP BY type ORDER BY COUNT(*) DESC LIMIT 5";
        cJSON* file_types = cJSON_CreateObject();

        rc = sqlite3_prepare_v2(db, type_sql, -1, &type_stmt, NULL);
        if (rc == SQLITE_OK) {
            while (sqlite3_step(type_stmt) == SQLITE_ROW) {
                const char* type_name = (const char*)sqlite3_column_text(type_stmt, 0);
                int count = sqlite3_column_int(type_stmt, 1);
                cJSON_AddNumberToObject(file_types, type_name ? type_name : "unknown", count);
            }
            sqlite3_finalize(type_stmt);
        }
        cJSON_AddItemToObject(data, "file_types", file_types);
    } else {
        // No data - return zeros
        cJSON_AddNumberToObject(data, "total_files", 0);
        cJSON_AddNumberToObject(data, "total_bytes", 0);
        cJSON_AddNumberToObject(data, "total_size_mb", 0.0);
        cJSON_AddNumberToObject(data, "unique_uploaders", 0);
        cJSON_AddNumberToObject(data, "avg_file_size", 0);
        cJSON_AddItemToObject(data, "file_types", cJSON_CreateObject());
    }

    sqlite3_finalize(stmt);
    sqlite3_close(db);

    char* response_str = cJSON_PrintUnformatted(response);
    send_json_response(200, response_str);
    free(response_str);
    cJSON_Delete(response);
}

void handle_config_get_api(void) {
    sqlite3* db;
    sqlite3_stmt* stmt;
    int rc;

    rc = sqlite3_open_v2(g_db_path, &db, SQLITE_OPEN_READONLY, NULL);
    if (rc) {
        send_json_error(500, "database_error", "Failed to open database");
        return;
    }

    cJSON* response = cJSON_CreateObject();
    cJSON* data = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddItemToObject(response, "data", data);

    // Query all config settings
    const char* sql = "SELECT key, value FROM config ORDER BY key";
    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc == SQLITE_OK) {
        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);
            if (key && value) {
                cJSON_AddStringToObject(data, key, value);
            }
        }
        sqlite3_finalize(stmt);
    }

    sqlite3_close(db);

    char* response_str = cJSON_PrintUnformatted(response);
    send_json_response(200, response_str);
    free(response_str);
    cJSON_Delete(response);
}

void handle_config_put_api(void) {
    // Read request body
    const char* content_length_str = getenv("CONTENT_LENGTH");
    if (!content_length_str) {
        send_json_error(411, "length_required", "Content-Length header required");
        return;
    }

    long content_length = atol(content_length_str);
    if (content_length <= 0 || content_length > 4096) {
        send_json_error(400, "invalid_content_length", "Invalid content length");
        return;
    }

    char* json_body = malloc(content_length + 1);
    if (!json_body) {
        send_json_error(500, "memory_error", "Failed to allocate memory");
        return;
    }

    size_t bytes_read = fread(json_body, 1, content_length, stdin);
    if (bytes_read != (size_t)content_length) {
        free(json_body);
        send_json_error(400, "incomplete_body", "Failed to read complete request body");
        return;
    }
    json_body[content_length] = '\0';

    // Parse JSON
    cJSON* config_data = cJSON_Parse(json_body);
    if (!config_data) {
        free(json_body);
        send_json_error(400, "invalid_json", "Invalid JSON in request body");
        return;
    }

    // Update database
    sqlite3* db;
    sqlite3_stmt* stmt;
    int rc;

    rc = sqlite3_open_v2(g_db_path, &db, SQLITE_OPEN_READWRITE, NULL);
    if (rc) {
        free(json_body);
        cJSON_Delete(config_data);
        send_json_error(500, "database_error", "Failed to open database");
        return;
    }

    // Collect updated keys for response
    cJSON* updated_keys = cJSON_CreateArray();

    // Update each config value
    const char* update_sql = "INSERT OR REPLACE INTO config (key, value, updated_at) VALUES (?, ?, ?)";

    cJSON* item = NULL;
    cJSON_ArrayForEach(item, config_data) {
        if (cJSON_IsString(item) && item->string) {
            rc = sqlite3_prepare_v2(db, update_sql, -1, &stmt, NULL);
            if (rc == SQLITE_OK) {
                sqlite3_bind_text(stmt, 1, item->string, -1, SQLITE_STATIC);
                sqlite3_bind_text(stmt, 2, cJSON_GetStringValue(item), -1, SQLITE_STATIC);
                sqlite3_bind_int64(stmt, 3, time(NULL));

                rc = sqlite3_step(stmt);
                if (rc == SQLITE_DONE) {
                    cJSON_AddItemToArray(updated_keys, cJSON_CreateString(item->string));
                }
                sqlite3_finalize(stmt);
            }
        }
    }

    free(json_body);
    cJSON_Delete(config_data);
    sqlite3_close(db);

    // Send response
    cJSON* response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddStringToObject(response, "message", "Configuration updated successfully");
    cJSON_AddItemToObject(response, "updated_keys", updated_keys);

    char* response_str = cJSON_PrintUnformatted(response);
    send_json_response(200, response_str);
    free(response_str);
    cJSON_Delete(response);
    
    // Force cache refresh after configuration update
    nostr_request_validator_force_cache_refresh();
}

void handle_config_key_put_api(const char* key) {
    if (!key || strlen(key) == 0) {
        send_json_error(400, "invalid_key", "Configuration key cannot be empty");
        return;
    }

    // Read request body
    const char* content_length_str = getenv("CONTENT_LENGTH");
    if (!content_length_str) {
        send_json_error(411, "length_required", "Content-Length header required");
        return;
    }

    long content_length = atol(content_length_str);
    if (content_length <= 0 || content_length > 4096) {
        send_json_error(400, "invalid_content_length", "Invalid content length");
        return;
    }

    char* json_body = malloc(content_length + 1);
    if (!json_body) {
        send_json_error(500, "memory_error", "Failed to allocate memory");
        return;
    }

    size_t bytes_read = fread(json_body, 1, content_length, stdin);
    if (bytes_read != (size_t)content_length) {
        free(json_body);
        send_json_error(400, "incomplete_body", "Failed to read complete request body");
        return;
    }
    json_body[content_length] = '\0';

    // Parse JSON - expect {"value": "..."}
    cJSON* request_data = cJSON_Parse(json_body);
    if (!request_data) {
        free(json_body);
        send_json_error(400, "invalid_json", "Invalid JSON in request body");
        return;
    }

    cJSON* value_item = cJSON_GetObjectItem(request_data, "value");
    if (!cJSON_IsString(value_item)) {
        free(json_body);
        cJSON_Delete(request_data);
        send_json_error(400, "missing_value", "Request must contain 'value' field");
        return;
    }

    const char* value = cJSON_GetStringValue(value_item);
    if (!value) {
        free(json_body);
        cJSON_Delete(request_data);
        send_json_error(400, "invalid_value", "Value must be a string");
        return;
    }

    // Make a safe copy of the value string BEFORE deleting cJSON object
    char safe_value[256];
    strncpy(safe_value, value, sizeof(safe_value) - 1);
    safe_value[sizeof(safe_value) - 1] = '\0';

    // Update database
    sqlite3* db;
    sqlite3_stmt* stmt;
    int rc;

    rc = sqlite3_open_v2(g_db_path, &db, SQLITE_OPEN_READWRITE, NULL);
    if (rc) {
        free(json_body);
        cJSON_Delete(request_data);
        send_json_error(500, "database_error", "Failed to open database");
        return;
    }

    // Update or insert the config value
    const char* update_sql = "INSERT OR REPLACE INTO config (key, value, updated_at) VALUES (?, ?, ?)";
    rc = sqlite3_prepare_v2(db, update_sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        free(json_body);
        cJSON_Delete(request_data);
        sqlite3_close(db);
        send_json_error(500, "database_error", "Failed to prepare update statement");
        return;
    }

    sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, safe_value, -1, SQLITE_STATIC);
    sqlite3_bind_int64(stmt, 3, time(NULL));

    rc = sqlite3_step(stmt);
    sqlite3_finalize(stmt);
    sqlite3_close(db);

    free(json_body);
    cJSON_Delete(request_data);

    if (rc != SQLITE_DONE) {
        send_json_error(500, "database_error", "Failed to update configuration");
        return;
    }
    
    cJSON* response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddStringToObject(response, "message", "Configuration updated successfully");
    cJSON_AddStringToObject(response, "key", key);
    cJSON_AddStringToObject(response, "value", safe_value);

    char* response_str = cJSON_PrintUnformatted(response);
    send_json_response(200, response_str);
    free(response_str);
    cJSON_Delete(response);

    // Force cache refresh after configuration update
    nostr_request_validator_force_cache_refresh();
}

void handle_files_api(void) {
    // Parse query parameters for pagination
    const char* query_string = getenv("QUERY_STRING");
    int limit = 50;
    int offset = 0;

    if (query_string) {
        char params[10][256];
        int param_count = parse_query_params(query_string, params, 10);

        for (int i = 0; i < param_count; i++) {
            char* key = params[i];
            char* value = strchr(key, '=');
            if (value) {
                *value++ = '\0';
                if (strcmp(key, "limit") == 0) {
                    limit = atoi(value);
                    if (limit <= 0 || limit > 200) limit = 50;
                } else if (strcmp(key, "offset") == 0) {
                    offset = atoi(value);
                    if (offset < 0) offset = 0;
                }
            }
        }
    }

    sqlite3* db;
    sqlite3_stmt* stmt;
    int rc;

    rc = sqlite3_open_v2(g_db_path, &db, SQLITE_OPEN_READONLY, NULL);
    if (rc) {
        send_json_error(500, "database_error", "Failed to open database");
        return;
    }

    // Query recent files with pagination
    const char* sql = "SELECT sha256, size, type, uploaded_at, uploader_pubkey, filename "
                      "FROM blobs ORDER BY uploaded_at DESC LIMIT ? OFFSET ?";

    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        sqlite3_close(db);
        send_json_error(500, "database_error", "Failed to prepare query");
        return;
    }

    sqlite3_bind_int(stmt, 1, limit);
    sqlite3_bind_int(stmt, 2, offset);

    cJSON* response = cJSON_CreateObject();
    cJSON* data = cJSON_CreateObject();
    cJSON* files_array = cJSON_CreateArray();
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddItemToObject(response, "data", data);
    cJSON_AddItemToObject(data, "files", files_array);
    cJSON_AddNumberToObject(data, "limit", limit);
    cJSON_AddNumberToObject(data, "offset", offset);

    int total_count = 0;
    while (sqlite3_step(stmt) == SQLITE_ROW) {
        total_count++;

        cJSON* file_obj = cJSON_CreateObject();
        cJSON_AddItemToArray(files_array, file_obj);

        const char* sha256 = (const char*)sqlite3_column_text(stmt, 0);
        const char* type = (const char*)sqlite3_column_text(stmt, 2);
        const char* filename = (const char*)sqlite3_column_text(stmt, 5);

        cJSON_AddStringToObject(file_obj, "sha256", sha256 ? sha256 : "");
        cJSON_AddNumberToObject(file_obj, "size", sqlite3_column_int64(stmt, 1));
        cJSON_AddStringToObject(file_obj, "type", type ? type : "");
        cJSON_AddNumberToObject(file_obj, "uploaded_at", sqlite3_column_int64(stmt, 3));

        const char* uploader = (const char*)sqlite3_column_text(stmt, 4);
        cJSON_AddStringToObject(file_obj, "uploader_pubkey",
                               uploader ? uploader : "");

        cJSON_AddStringToObject(file_obj, "filename",
                               filename ? filename : "");

        // Build URL for file
        char url[1024];
        if (type && sha256) {
                    // Use local admin implementation for URL building
                    char origin_url[256];
                    admin_nip94_get_origin(origin_url, sizeof(origin_url));
                    admin_nip94_build_blob_url(origin_url, sha256, type, url, sizeof(url));
            cJSON_AddStringToObject(file_obj, "url", url);
        }
    }

    // Get total count for pagination info
    const char* count_sql = "SELECT COUNT(*) FROM blobs";
    sqlite3_stmt* count_stmt;

    rc = sqlite3_prepare_v2(db, count_sql, -1, &count_stmt, NULL);
    if (rc == SQLITE_OK) {
        rc = sqlite3_step(count_stmt);
        if (rc == SQLITE_ROW) {
            int total = sqlite3_column_int(count_stmt, 0);
            cJSON_AddNumberToObject(data, "total", total);
        }
        sqlite3_finalize(count_stmt);
    }

    sqlite3_finalize(stmt);
    sqlite3_close(db);

    char* response_str = cJSON_PrintUnformatted(response);
    send_json_response(200, response_str);
    free(response_str);
    cJSON_Delete(response);
}

void handle_health_api(void) {
    cJSON* response = cJSON_CreateObject();
    cJSON* data = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddItemToObject(response, "data", data);

    // Check database connection
    sqlite3* db;
    int rc = sqlite3_open_v2(g_db_path, &db, SQLITE_OPEN_READONLY, NULL);
    if (rc == SQLITE_OK) {
        cJSON_AddStringToObject(data, "database", "connected");
        sqlite3_close(db);
    } else {
        cJSON_AddStringToObject(data, "database", "disconnected");
    }

    // Check blob directory
    struct stat st;
    if (stat("blobs", &st) == 0 && S_ISDIR(st.st_mode)) {
        cJSON_AddStringToObject(data, "blob_directory", "accessible");
    } else {
        cJSON_AddStringToObject(data, "blob_directory", "inaccessible");
    }

    // Get disk usage
    cJSON* disk_usage = cJSON_CreateObject();
    struct statvfs vfs;
    if (statvfs(".", &vfs) == 0) {
        unsigned long long total_bytes = (unsigned long long)vfs.f_blocks * vfs.f_frsize;
        unsigned long long free_bytes = (unsigned long long)vfs.f_bavail * vfs.f_frsize;
        unsigned long long used_bytes = total_bytes - free_bytes;
        double usage_percent = (double)used_bytes / (double)total_bytes * 100.0;

        cJSON_AddNumberToObject(disk_usage, "total_bytes", (double)total_bytes);
        cJSON_AddNumberToObject(disk_usage, "used_bytes", (double)used_bytes);
        cJSON_AddNumberToObject(disk_usage, "available_bytes", (double)free_bytes);
        cJSON_AddNumberToObject(disk_usage, "usage_percent", usage_percent);
    }
    cJSON_AddItemToObject(data, "disk_usage", disk_usage);

    // Add server info
    cJSON_AddNumberToObject(data, "server_time", (double)time(NULL));
    cJSON_AddNumberToObject(data, "uptime", 0); // Would need to track process start time

    char* response_str = cJSON_PrintUnformatted(response);
    send_json_response(200, response_str);
    free(response_str);
    cJSON_Delete(response);
}

// Utility functions
void send_json_response(int status, const char* json_content) {
    printf("Status: %d OK\r\n", status);
    printf("Content-Type: application/json\r\n");
    printf("Cache-Control: no-cache\r\n");
    printf("\r\n");
    printf("%s\n", json_content);
}

void send_json_error(int status, const char* error, const char* message) {
    cJSON* response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "status", "error");
    cJSON_AddStringToObject(response, "error", error);
    cJSON_AddStringToObject(response, "message", message);

    char* response_str = cJSON_PrintUnformatted(response);
    printf("Status: %d %s\r\n",
           status,
           status == 400 ? "Bad Request" :
           status == 401 ? "Unauthorized" :
           status == 403 ? "Forbidden" :
           status == 404 ? "Not Found" :
           status == 500 ? "Internal Server Error" :
           status == 503 ? "Service Unavailable" :
           "Error");
    printf("Content-Type: application/json\r\n");
    printf("Cache-Control: no-cache\r\n");
    printf("\r\n");
    printf("%s\n", response_str);

    free(response_str);
    cJSON_Delete(response);
}

int parse_query_params(const char* query_string, char params[][256], int max_params) {
    if (!query_string || !params) return 0;

    size_t query_len = strlen(query_string);
    char* query_copy = malloc(query_len + 1);
    if (!query_copy) return 0;
    memcpy(query_copy, query_string, query_len + 1);

    int count = 0;
    char* token = strtok(query_copy, "&");

    while (token && count < max_params) {
        if (strlen(token) >= sizeof(params[0])) {
            token[sizeof(params[0]) - 1] = '\0';
        }
        strcpy(params[count], token);
        count++;
        token = strtok(NULL, "&");
    }

    free(query_copy);
    return count;
}