// NIP-13 Proof of Work validation module
#include <stdio.h>
#include "debug.h"
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "../nostr_core_lib/cjson/cJSON.h"
#include "../nostr_core_lib/nostr_core/nostr_core.h"
#include "../nostr_core_lib/nostr_core/nip013.h"
#include "config.h"


// Configuration functions from config.c
extern int get_config_bool(const char* key, int default_value);
extern int get_config_int(const char* key, int default_value);
extern const char* get_config_value(const char* key);

// Initialize PoW configuration using configuration system
void init_pow_config() {
    // Configuration is now handled directly through database queries
    // No cache initialization needed
}

// Validate event Proof of Work according to NIP-13
int validate_event_pow(cJSON* event, char* error_message, size_t error_size) {
    // Get PoW configuration directly from database
    int enabled = get_config_bool("pow_enabled", 1);
    int min_pow_difficulty = get_config_int("pow_min_difficulty", 0);
    const char* pow_mode = get_config_value("pow_mode");

    // Determine validation flags based on mode
    int validation_flags = NOSTR_POW_VALIDATE_BASIC; // Default
    if (pow_mode) {
        if (strcmp(pow_mode, "strict") == 0) {
            validation_flags = NOSTR_POW_VALIDATE_ANTI_SPAM | NOSTR_POW_STRICT_FORMAT;
        } else if (strcmp(pow_mode, "full") == 0) {
            validation_flags = NOSTR_POW_VALIDATE_FULL;
        } else if (strcmp(pow_mode, "basic") == 0) {
            validation_flags = NOSTR_POW_VALIDATE_BASIC;
        } else if (strcmp(pow_mode, "disabled") == 0) {
            enabled = 0;
        }
        free((char*)pow_mode);
    }

    if (!enabled) {
        return 0; // PoW validation disabled
    }

    if (!event) {
        snprintf(error_message, error_size, "pow: null event");
        return NOSTR_ERROR_INVALID_INPUT;
    }

    // If min_pow_difficulty is 0, only validate events that have nonce tags
    // This allows events without PoW when difficulty requirement is 0
    if (min_pow_difficulty == 0) {
        cJSON* tags = cJSON_GetObjectItem(event, "tags");
        int has_nonce_tag = 0;

        if (tags && cJSON_IsArray(tags)) {
            cJSON* tag = NULL;
            cJSON_ArrayForEach(tag, tags) {
                if (cJSON_IsArray(tag) && cJSON_GetArraySize(tag) >= 2) {
                    cJSON* tag_name = cJSON_GetArrayItem(tag, 0);
                    if (cJSON_IsString(tag_name)) {
                        const char* name = cJSON_GetStringValue(tag_name);
                        if (name && strcmp(name, "nonce") == 0) {
                            has_nonce_tag = 1;
                            break;
                        }
                    }
                }
            }
        }

        // If no minimum difficulty required and no nonce tag, skip PoW validation
        if (!has_nonce_tag) {
            return 0; // Accept event without PoW when min_difficulty=0
        }
    }

    // Perform PoW validation using nostr_core_lib
    nostr_pow_result_t pow_result;
    int validation_result = nostr_validate_pow(event, min_pow_difficulty,
                                             validation_flags, &pow_result);

    if (validation_result != NOSTR_SUCCESS) {
        // Handle specific error cases with appropriate messages
        switch (validation_result) {
            case NOSTR_ERROR_NIP13_INSUFFICIENT:
                snprintf(error_message, error_size,
                        "pow: insufficient difficulty: %d < %d",
                        pow_result.actual_difficulty, min_pow_difficulty);
                DEBUG_WARN("Event rejected: insufficient PoW difficulty");
                break;
            case NOSTR_ERROR_NIP13_NO_NONCE_TAG:
                // This should not happen with min_difficulty=0 after our check above
                if (min_pow_difficulty > 0) {
                    snprintf(error_message, error_size, "pow: missing required nonce tag");
                    DEBUG_WARN("Event rejected: missing nonce tag");
                } else {
                    return 0; // Allow when min_difficulty=0
                }
                break;
            case NOSTR_ERROR_NIP13_INVALID_NONCE_TAG:
                snprintf(error_message, error_size, "pow: invalid nonce tag format");
                DEBUG_WARN("Event rejected: invalid nonce tag format");
                break;
            case NOSTR_ERROR_NIP13_TARGET_MISMATCH:
                snprintf(error_message, error_size,
                        "pow: committed target (%d) lower than minimum (%d)",
                        pow_result.committed_target, min_pow_difficulty);
                DEBUG_WARN("Event rejected: committed target too low (anti-spam protection)");
                break;
            case NOSTR_ERROR_NIP13_CALCULATION:
                snprintf(error_message, error_size, "pow: difficulty calculation failed");
                DEBUG_ERROR("PoW difficulty calculation error");
                break;
            case NOSTR_ERROR_EVENT_INVALID_ID:
                snprintf(error_message, error_size, "pow: invalid event ID format");
                DEBUG_WARN("Event rejected: invalid event ID for PoW calculation");
                break;
            default:
                snprintf(error_message, error_size, "pow: validation failed - %s",
                        strlen(pow_result.error_detail) > 0 ? pow_result.error_detail : "unknown error");
                DEBUG_WARN("Event rejected: PoW validation failed");
        }
        return validation_result;
    }

    return 0;  // Success
}