#!/bin/bash

# NIP-13 Proof of Work Validation Test Suite for C Nostr Relay
# Tests PoW validation in the relay's event processing pipeline
# Based on nostr_core_lib/tests/nip13_test.c

set -e  # Exit on error

# Color constants
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
BLUE='\033[34m'
BOLD='\033[1m'
RESET='\033[0m'

# Test configuration
RELAY_URL="ws://127.0.0.1:8888"
HTTP_URL="http://127.0.0.1:8888"
TEST_COUNT=0
PASSED_COUNT=0
FAILED_COUNT=0

# Test results tracking
declare -a TEST_RESULTS=()

print_info() {
    echo -e "${BLUE}[INFO]${RESET} $1"
}

print_success() {
    echo -e "${GREEN}${BOLD}[SUCCESS]${RESET} $1"
}

print_warning() {
    echo -e "${YELLOW}[WARNING]${RESET} $1"
}

print_error() {
    echo -e "${RED}${BOLD}[ERROR]${RESET} $1"
}

print_test_header() {
    TEST_COUNT=$((TEST_COUNT + 1))
    echo ""
    echo -e "${BOLD}=== TEST $TEST_COUNT: $1 ===${RESET}"
}

record_test_result() {
    local test_name="$1"
    local result="$2"
    local details="$3"
    
    TEST_RESULTS+=("$test_name|$result|$details")
    
    if [ "$result" = "PASS" ]; then
        PASSED_COUNT=$((PASSED_COUNT + 1))
        print_success "PASS: $test_name"
    else
        FAILED_COUNT=$((FAILED_COUNT + 1))
        print_error "FAIL: $test_name"
        if [ -n "$details" ]; then
            echo "       Details: $details"
        fi
    fi
}

# Check if relay is running
check_relay_running() {
    print_info "Checking if relay is running..."
    
    if ! curl -s -H "Accept: application/nostr+json" "$HTTP_URL/" >/dev/null 2>&1; then
        print_error "Relay is not running or not accessible at $HTTP_URL"
        print_info "Please start the relay with: ./make_and_restart_relay.sh"
        exit 1
    fi
    
    print_success "Relay is running and accessible"
}

# Test NIP-11 relay information includes NIP-13
test_nip11_pow_support() {
    print_test_header "NIP-11 PoW Support Advertisement"
    
    print_info "Fetching relay information..."
    RELAY_INFO=$(curl -s -H "Accept: application/nostr+json" "$HTTP_URL/")
    
    echo "Relay Info Response:"
    echo "$RELAY_INFO" | jq '.'
    echo ""
    
    # Check if NIP-13 is in supported_nips
    if echo "$RELAY_INFO" | jq -e '.supported_nips | index(13)' >/dev/null 2>&1; then
        print_success "✓ NIP-13 found in supported_nips array"
        NIP13_SUPPORTED=true
    else
        print_error "✗ NIP-13 not found in supported_nips array"
        NIP13_SUPPORTED=false
    fi
    
    # Check if min_pow_difficulty is present
    MIN_POW_DIFF=$(echo "$RELAY_INFO" | jq -r '.limitation.min_pow_difficulty // "missing"')
    if [ "$MIN_POW_DIFF" != "missing" ]; then
        print_success "✓ min_pow_difficulty found: $MIN_POW_DIFF"
        MIN_POW_PRESENT=true
    else
        print_error "✗ min_pow_difficulty not found in limitations"
        MIN_POW_PRESENT=false
    fi
    
    if [ "$NIP13_SUPPORTED" = true ] && [ "$MIN_POW_PRESENT" = true ]; then
        record_test_result "NIP-11 PoW Support Advertisement" "PASS" "NIP-13 supported, min_pow_difficulty=$MIN_POW_DIFF"
        return 0
    else
        record_test_result "NIP-11 PoW Support Advertisement" "FAIL" "Missing NIP-13 support or min_pow_difficulty"
        return 1
    fi
}

# Test event submission without PoW (should be accepted when min_difficulty=0)
test_event_without_pow() {
    print_test_header "Event Submission Without PoW (min_difficulty=0)"
    
    # Create a simple event without PoW
    print_info "Generating test event without PoW..."
    
    # Use nak to generate a simple event
    if ! command -v nak &> /dev/null; then
        print_warning "nak command not found - skipping PoW generation tests"
        record_test_result "Event Submission Without PoW" "SKIP" "nak not available"
        return 0
    fi
    
    # Generate event without PoW using direct private key
    PRIVATE_KEY="91ba716fa9e7ea2fcbad360cf4f8e0d312f73984da63d90f524ad61a6a1e7dbe"
    EVENT_JSON=$(nak event --sec "$PRIVATE_KEY" -c "Test event without PoW" --ts $(date +%s))
    
    print_info "Generated event:"
    echo "$EVENT_JSON" | jq '.'
    echo ""
    
    # Send event to relay via WebSocket using websocat
    print_info "Sending event to relay..."
    
    # Create EVENT message in Nostr format
    EVENT_MESSAGE="[\"EVENT\",$EVENT_JSON]"
    
    # Send to relay and capture response
    if command -v websocat &> /dev/null; then
        RESPONSE=$(echo "$EVENT_MESSAGE" | timeout 5s websocat "$RELAY_URL" 2>&1 || echo "Connection failed")
        
        print_info "Relay response: $RESPONSE"
        
        if [[ "$RESPONSE" == *"Connection failed"* ]]; then
            print_error "✗ Failed to connect to relay"
            record_test_result "Event Submission Without PoW" "FAIL" "Connection failed"
            return 1
        elif [[ "$RESPONSE" == *"true"* ]]; then
            print_success "✓ Event without PoW accepted (expected when min_difficulty=0)"
            record_test_result "Event Submission Without PoW" "PASS" "Event accepted as expected"
            return 0
        else
            print_error "✗ Event without PoW rejected (unexpected when min_difficulty=0)"
            record_test_result "Event Submission Without PoW" "FAIL" "Event rejected: $RESPONSE"
            return 1
        fi
    else
        print_error "websocat not found - required for testing"
        record_test_result "Event Submission Without PoW" "SKIP" "websocat not available"
        return 0
    fi
}

# Test event with valid PoW
test_event_with_pow() {
    print_test_header "Event Submission With Valid PoW"
    
    if ! command -v nak &> /dev/null; then
        print_warning "nak command not found - skipping PoW validation tests"
        record_test_result "Event Submission With Valid PoW" "SKIP" "nak not available"
        return 0
    fi
    
    print_info "Generating event with PoW difficulty 8..."
    
    # Generate event with PoW (difficulty 8 for reasonable test time) using direct private key
    PRIVATE_KEY="91ba716fa9e7ea2fcbad360cf4f8e0d312f73984da63d90f524ad61a6a1e7dbe"
    POW_EVENT_JSON=$(nak event --sec "$PRIVATE_KEY" -c "Test event with PoW difficulty 8" --pow 8 --ts $(date +%s))
    
    if [ -z "$POW_EVENT_JSON" ]; then
        print_error "Failed to generate PoW event"
        record_test_result "Event Submission With Valid PoW" "FAIL" "PoW event generation failed"
        return 1
    fi
    
    print_info "Generated PoW event:"
    echo "$POW_EVENT_JSON" | jq '.'
    echo ""
    
    # Extract nonce info for verification
    NONCE_TAG=$(echo "$POW_EVENT_JSON" | jq -r '.tags[] | select(.[0] == "nonce") | .[1]' 2>/dev/null || echo "")
    TARGET_DIFF=$(echo "$POW_EVENT_JSON" | jq -r '.tags[] | select(.[0] == "nonce") | .[2]' 2>/dev/null || echo "")
    
    if [ -n "$NONCE_TAG" ] && [ -n "$TARGET_DIFF" ]; then
        print_info "PoW details: nonce=$NONCE_TAG, target_difficulty=$TARGET_DIFF"
    fi
    
    # Send event to relay via WebSocket using websocat
    print_info "Sending PoW event to relay..."
    
    # Create EVENT message in Nostr format
    POW_EVENT_MESSAGE="[\"EVENT\",$POW_EVENT_JSON]"
    
    # Send to relay and capture response
    if command -v websocat &> /dev/null; then
        RESPONSE=$(echo "$POW_EVENT_MESSAGE" | timeout 10s websocat "$RELAY_URL" 2>&1 || echo "Connection failed")
        
        print_info "Relay response: $RESPONSE"
        
        if [[ "$RESPONSE" == *"Connection failed"* ]]; then
            print_error "✗ Failed to connect to relay"
            record_test_result "Event Submission With Valid PoW" "FAIL" "Connection failed"
            return 1
        elif [[ "$RESPONSE" == *"true"* ]]; then
            print_success "✓ Event with valid PoW accepted"
            record_test_result "Event Submission With Valid PoW" "PASS" "PoW event accepted"
            return 0
        else
            print_error "✗ Event with valid PoW rejected"
            record_test_result "Event Submission With Valid PoW" "FAIL" "PoW event rejected: $RESPONSE"
            return 1
        fi
    else
        print_error "websocat not found - required for testing"
        record_test_result "Event Submission With Valid PoW" "SKIP" "websocat not available"
        return 0
    fi
}

# Test relay configuration with environment variables
test_pow_configuration() {
    print_test_header "PoW Configuration Via Environment Variables"
    
    print_info "Testing different PoW configurations requires relay restart"
    print_info "Current configuration from logs:"
    
    if [ -f "relay.log" ]; then
        grep "PoW Configuration:" relay.log | tail -1
    else
        print_warning "No relay.log found"
    fi
    
    # Test current configuration values
    RELAY_INFO=$(curl -s -H "Accept: application/nostr+json" "$HTTP_URL/")
    MIN_POW_DIFF=$(echo "$RELAY_INFO" | jq -r '.limitation.min_pow_difficulty')
    
    print_info "Current min_pow_difficulty from NIP-11: $MIN_POW_DIFF"
    
    # For now, just verify the configuration is readable
    if [ "$MIN_POW_DIFF" != "null" ] && [ "$MIN_POW_DIFF" != "missing" ]; then
        print_success "✓ PoW configuration is accessible via NIP-11"
        record_test_result "PoW Configuration Via Environment Variables" "PASS" "min_pow_difficulty=$MIN_POW_DIFF"
        return 0
    else
        print_error "✗ PoW configuration not accessible"
        record_test_result "PoW Configuration Via Environment Variables" "FAIL" "Cannot read min_pow_difficulty"
        return 1
    fi
}

# Test NIP-13 reference event validation
test_nip13_reference_event() {
    print_test_header "NIP-13 Reference Event Validation"
    
    # This is the official NIP-13 reference event
    NIP13_REF_EVENT='{"id":"000006d8c378af1779d2feebc7603a125d99eca0ccf1085959b307f64e5dd358","pubkey":"a48380f4cfcc1ad5378294fcac36439770f9c878dd880ffa94bb74ea54a6f243","created_at":1651794653,"kind":1,"tags":[["nonce","776797","20"]],"content":"It'\''s just me mining my own business","sig":"284622fc0a3f4f1303455d5175f7ba962a3300d136085b9566801bc2e0699de0c7e31e44c81fb40ad9049173742e904713c3594a1da0fc5d2382a25c11aba977"}'
    
    print_info "Testing NIP-13 reference event from specification:"
    echo "$NIP13_REF_EVENT" | jq '.'
    echo ""
    
    # Send reference event to relay via WebSocket using websocat
    print_info "Sending NIP-13 reference event to relay..."
    
    # Create EVENT message in Nostr format
    REF_EVENT_MESSAGE="[\"EVENT\",$NIP13_REF_EVENT]"
    
    # Send to relay and capture response
    if command -v websocat &> /dev/null; then
        RESPONSE=$(echo "$REF_EVENT_MESSAGE" | timeout 10s websocat "$RELAY_URL" 2>&1 || echo "Connection failed")
        
        print_info "Relay response: $RESPONSE"
        
        if [[ "$RESPONSE" == *"Connection failed"* ]] || [[ -z "$RESPONSE" ]]; then
            print_error "✗ Failed to connect to relay or no response"
            record_test_result "NIP-13 Reference Event Validation" "FAIL" "Connection failed or timeout"
            return 1
        elif [[ "$RESPONSE" == *"true"* ]]; then
            print_success "✓ NIP-13 reference event accepted"
            record_test_result "NIP-13 Reference Event Validation" "PASS" "Reference event accepted"
            return 0
        else
            print_error "✗ NIP-13 reference event rejected"
            record_test_result "NIP-13 Reference Event Validation" "FAIL" "Reference event rejected: $RESPONSE"
            return 1
        fi
    else
        print_error "websocat not found - required for testing"
        record_test_result "NIP-13 Reference Event Validation" "SKIP" "websocat not available"
        return 0
    fi
}

# Print test summary
print_test_summary() {
    echo ""
    echo -e "${BOLD}=== TEST SUMMARY ===${RESET}"
    echo "Total tests run: $TEST_COUNT"
    echo -e "${GREEN}Passed: $PASSED_COUNT${RESET}"
    echo -e "${RED}Failed: $FAILED_COUNT${RESET}"
    
    if [ $FAILED_COUNT -gt 0 ]; then
        echo ""
        echo -e "${RED}${BOLD}Failed tests:${RESET}"
        for result in "${TEST_RESULTS[@]}"; do
            IFS='|' read -r name status details <<< "$result"
            if [ "$status" = "FAIL" ]; then
                echo -e "  ${RED}✗ $name${RESET}"
                if [ -n "$details" ]; then
                    echo "    $details"
                fi
            fi
        done
    fi
    
    echo ""
    if [ $FAILED_COUNT -eq 0 ]; then
        echo -e "${GREEN}${BOLD}🎉 ALL TESTS PASSED!${RESET}"
        echo -e "${GREEN}✅ NIP-13 PoW validation is working correctly in the relay${RESET}"
        return 0
    else
        echo -e "${RED}${BOLD}❌ SOME TESTS FAILED${RESET}"
        echo "Please review the output above and check relay logs for more details."
        return 1
    fi
}

# Main test execution
main() {
    echo -e "${BOLD}=== NIP-13 Proof of Work Relay Test Suite ===${RESET}"
    echo "Testing NIP-13 PoW validation in the C Nostr Relay"
    echo "Relay URL: $RELAY_URL"
    echo ""
    
    # Check prerequisites
    if ! command -v curl &> /dev/null; then
        print_error "curl is required but not installed"
        exit 1
    fi
    
    if ! command -v jq &> /dev/null; then
        print_error "jq is required but not installed"
        exit 1
    fi
    
    if ! command -v websocat &> /dev/null; then
        print_warning "websocat not found - WebSocket tests will be skipped"
    fi
    
    # Run tests
    check_relay_running
    test_nip11_pow_support
    test_event_without_pow
    test_event_with_pow  
    test_pow_configuration
    test_nip13_reference_event
    
    # Print summary
    print_test_summary
    exit $?
}

# Run main function
main "$@"