/*
 * Ginxsom Admin Command Handlers
 * Implements execution of admin commands received via Kind 23456 events
 */

#include "ginxsom.h"
#include <cjson/cJSON.h>
#include <sqlite3.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/statvfs.h>
#include <dirent.h>

// Forward declarations
static cJSON* handle_blob_list(char **args, int arg_count);
static cJSON* handle_blob_info(char **args, int arg_count);
static cJSON* handle_blob_delete(char **args, int arg_count);
static cJSON* handle_storage_stats(char **args, int arg_count);
static cJSON* handle_config_get(char **args, int arg_count);
static cJSON* handle_config_set(char **args, int arg_count);
static cJSON* handle_help(char **args, int arg_count);

// Command dispatch table
typedef struct {
    const char *command;
    cJSON* (*handler)(char **args, int arg_count);
    const char *description;
} admin_command_t;

static admin_command_t command_table[] = {
    {"blob_list", handle_blob_list, "List all blobs"},
    {"blob_info", handle_blob_info, "Get blob information"},
    {"blob_delete", handle_blob_delete, "Delete a blob"},
    {"storage_stats", handle_storage_stats, "Get storage statistics"},
    {"config_get", handle_config_get, "Get configuration value"},
    {"config_set", handle_config_set, "Set configuration value"},
    {"help", handle_help, "Show available commands"},
    {NULL, NULL, NULL}
};

// Execute admin command and return JSON response
int execute_admin_command(char **command_array, int command_count, char **response_json_out) {
    if (!command_array || command_count < 1 || !response_json_out) {
        return -1;
    }

    const char *command = command_array[0];
    
    // Find command handler
    admin_command_t *cmd = NULL;
    for (int i = 0; command_table[i].command != NULL; i++) {
        if (strcmp(command_table[i].command, command) == 0) {
            cmd = &command_table[i];
            break;
        }
    }

    cJSON *response;
    if (cmd) {
        // Execute command handler
        response = cmd->handler(command_array + 1, command_count - 1);
    } else {
        // Unknown command
        response = cJSON_CreateObject();
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "message", "Unknown command");
        cJSON_AddStringToObject(response, "command", command);
    }

    // Convert response to JSON string
    char *json_str = cJSON_PrintUnformatted(response);
    cJSON_Delete(response);

    if (!json_str) {
        return -1;
    }

    *response_json_out = json_str;
    return 0;
}

// Command handlers

static cJSON* handle_blob_list(char **args __attribute__((unused)), int arg_count __attribute__((unused))) {
    cJSON *response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddStringToObject(response, "command", "blob_list");
    
    // TODO: Implement actual blob listing from database
    cJSON *blobs = cJSON_CreateArray();
    cJSON_AddItemToObject(response, "blobs", blobs);
    cJSON_AddNumberToObject(response, "count", 0);
    
    return response;
}

static cJSON* handle_blob_info(char **args, int arg_count) {
    cJSON *response = cJSON_CreateObject();
    
    if (arg_count < 1) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "message", "Missing blob hash argument");
        return response;
    }
    
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddStringToObject(response, "command", "blob_info");
    cJSON_AddStringToObject(response, "hash", args[0]);
    
    // TODO: Implement actual blob info retrieval from database
    cJSON_AddStringToObject(response, "message", "Not yet implemented");
    
    return response;
}

static cJSON* handle_blob_delete(char **args, int arg_count) {
    cJSON *response = cJSON_CreateObject();
    
    if (arg_count < 1) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "message", "Missing blob hash argument");
        return response;
    }
    
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddStringToObject(response, "command", "blob_delete");
    cJSON_AddStringToObject(response, "hash", args[0]);
    
    // TODO: Implement actual blob deletion
    cJSON_AddStringToObject(response, "message", "Not yet implemented");
    
    return response;
}

static cJSON* handle_storage_stats(char **args __attribute__((unused)), int arg_count __attribute__((unused))) {
    cJSON *response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddStringToObject(response, "command", "storage_stats");
    
    // Get filesystem stats
    struct statvfs stat;
    if (statvfs(".", &stat) == 0) {
        unsigned long long total = stat.f_blocks * stat.f_frsize;
        unsigned long long available = stat.f_bavail * stat.f_frsize;
        unsigned long long used = total - available;
        
        cJSON_AddNumberToObject(response, "total_bytes", (double)total);
        cJSON_AddNumberToObject(response, "used_bytes", (double)used);
        cJSON_AddNumberToObject(response, "available_bytes", (double)available);
    }
    
    // TODO: Add blob count and total blob size from database
    cJSON_AddNumberToObject(response, "blob_count", 0);
    cJSON_AddNumberToObject(response, "blob_total_bytes", 0);
    
    return response;
}

static cJSON* handle_config_get(char **args, int arg_count) {
    cJSON *response = cJSON_CreateObject();
    
    if (arg_count < 1) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "message", "Missing config key argument");
        return response;
    }
    
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddStringToObject(response, "command", "config_get");
    cJSON_AddStringToObject(response, "key", args[0]);
    
    // TODO: Implement actual config retrieval from database
    cJSON_AddStringToObject(response, "value", "");
    cJSON_AddStringToObject(response, "message", "Not yet implemented");
    
    return response;
}

static cJSON* handle_config_set(char **args, int arg_count) {
    cJSON *response = cJSON_CreateObject();
    
    if (arg_count < 2) {
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "message", "Missing config key or value argument");
        return response;
    }
    
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddStringToObject(response, "command", "config_set");
    cJSON_AddStringToObject(response, "key", args[0]);
    cJSON_AddStringToObject(response, "value", args[1]);
    
    // TODO: Implement actual config update in database
    cJSON_AddStringToObject(response, "message", "Not yet implemented");
    
    return response;
}

static cJSON* handle_help(char **args __attribute__((unused)), int arg_count __attribute__((unused))) {
    cJSON *response = cJSON_CreateObject();
    cJSON_AddStringToObject(response, "status", "success");
    cJSON_AddStringToObject(response, "command", "help");
    
    cJSON *commands = cJSON_CreateArray();
    for (int i = 0; command_table[i].command != NULL; i++) {
        cJSON *cmd = cJSON_CreateObject();
        cJSON_AddStringToObject(cmd, "command", command_table[i].command);
        cJSON_AddStringToObject(cmd, "description", command_table[i].description);
        cJSON_AddItemToArray(commands, cmd);
    }
    
    cJSON_AddItemToObject(response, "commands", commands);
    
    return response;
}