#!/bin/bash

# C-Relay Comprehensive Test Suite Runner
# This script runs all security and stability tests for the Nostr relay

set -e

# Configuration
RELAY_HOST="127.0.0.1"
RELAY_PORT="8888"
RELAY_URL="ws://$RELAY_HOST:$RELAY_PORT"
TEST_TIMEOUT=30
LOG_FILE="test_results_$(date +%Y%m%d_%H%M%S).log"
REPORT_FILE="test_report_$(date +%Y%m%d_%H%M%S).html"

# Test keys for authentication (from AGENTS.md)
ADMIN_PRIVATE_KEY="6a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3"
RELAY_PUBKEY="4f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Test results tracking
TOTAL_SUITES=0
PASSED_SUITES=0
FAILED_SUITES=0
SKIPPED_SUITES=0

SUITE_RESULTS=()

# Function to create authenticated WebSocket connection
# Usage: authenticated_websocat <subscription_id> <filter_json>
authenticated_websocat() {
    local sub_id="$1"
    local filter="$2"

    # Create a temporary script for authenticated connection
    cat > /tmp/auth_ws_$$.sh << EOF
#!/bin/bash
# Authenticated WebSocket connection helper

# Connect and handle AUTH challenge
exec websocat -B 1048576 --no-close ws://$RELAY_HOST:$RELAY_PORT 2>/dev/null << 'INNER_EOF'
["REQ","$sub_id",$filter]
INNER_EOF
EOF

    chmod +x /tmp/auth_ws_$$.sh
    timeout $TEST_TIMEOUT bash /tmp/auth_ws_$$.sh
    rm -f /tmp/auth_ws_$$.sh
}

# Function to log messages
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE"
}

# Function to run a test suite
run_test_suite() {
    local suite_name="$1"
    local suite_script="$2"
    local description="$3"

    TOTAL_SUITES=$((TOTAL_SUITES + 1))

    log "=========================================="
    log "Running Test Suite: $suite_name"
    log "Description: $description"
    log "=========================================="

    if [[ ! -f "$suite_script" ]]; then
        log "${RED}ERROR: Test script $suite_script not found${NC}"
        FAILED_SUITES=$((FAILED_SUITES + 1))
        SUITE_RESULTS+=("$suite_name: FAILED (script not found)")
        return 1
    fi

    # Make script executable if not already
    chmod +x "$suite_script"

    # Run the test suite and capture output
    local start_time=$(date +%s)
    if bash "$suite_script" >> "$LOG_FILE" 2>&1; then
        local end_time=$(date +%s)
        local duration=$((end_time - start_time))
        log "${GREEN}✓ $suite_name PASSED${NC} (Duration: ${duration}s)"
        PASSED_SUITES=$((PASSED_SUITES + 1))
        SUITE_RESULTS+=("$suite_name: PASSED (${duration}s)")
        return 0
    else
        local end_time=$(date +%s)
        local duration=$((end_time - start_time))
        log "${RED}✗ $suite_name FAILED${NC} (Duration: ${duration}s)"
        FAILED_SUITES=$((FAILED_SUITES + 1))
        SUITE_RESULTS+=("$suite_name: FAILED (${duration}s)")
        return 1
    fi
}

# Function to check if relay is running
check_relay_status() {
    log "Checking relay status at $RELAY_URL..."

    # First check if HTTP endpoint is accessible
    if curl -s -H "Accept: application/nostr+json" "http://$RELAY_HOST:$RELAY_PORT" >/dev/null 2>&1; then
        log "${GREEN}✓ Relay HTTP endpoint is accessible${NC}"
        return 0
    fi

    # Fallback: Try WebSocket connection
    if echo '["REQ","status_check",{}]' | timeout 5 websocat -B 1048576 --no-close "$RELAY_URL" >/dev/null 2>&1; then
        log "${GREEN}✓ Relay WebSocket endpoint is accessible${NC}"
        return 0
    else
        log "${RED}✗ Relay is not accessible at $RELAY_URL${NC}"
        log "Please start the relay first using: ./make_and_restart_relay.sh"
        return 1
    fi
}

# Function to generate HTML report
generate_html_report() {
    local total_duration=$1

    cat > "$REPORT_FILE" << EOF
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>C-Relay Test Report - $(date)</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; background-color: #f5f5f5; }
        .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 8px; margin-bottom: 30px; }
        .summary { background: white; padding: 20px; border-radius: 8px; margin-bottom: 30px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
        .suite { background: white; margin-bottom: 10px; padding: 15px; border-radius: 5px; box-shadow: 0 1px 5px rgba(0,0,0,0.1); }
        .passed { border-left: 5px solid #28a745; }
        .failed { border-left: 5px solid #dc3545; }
        .skipped { border-left: 5px solid #ffc107; }
        .metric { display: inline-block; margin: 10px; padding: 10px; background: #e9ecef; border-radius: 5px; }
        .status-passed { color: #28a745; font-weight: bold; }
        .status-failed { color: #dc3545; font-weight: bold; }
        .status-skipped { color: #ffc107; font-weight: bold; }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }
        th { background-color: #f8f9fa; }
    </style>
</head>
<body>
    <div class="header">
        <h1>C-Relay Comprehensive Test Report</h1>
        <p>Generated on: $(date)</p>
        <p>Test Environment: $RELAY_URL</p>
    </div>

    <div class="summary">
        <h2>Test Summary</h2>
        <div class="metric">
            <strong>Total Suites:</strong> $TOTAL_SUITES
        </div>
        <div class="metric">
            <strong>Passed:</strong> <span class="status-passed">$PASSED_SUITES</span>
        </div>
        <div class="metric">
            <strong>Failed:</strong> <span class="status-failed">$FAILED_SUITES</span>
        </div>
        <div class="metric">
            <strong>Skipped:</strong> <span class="status-skipped">$SKIPPED_SUITES</span>
        </div>
        <div class="metric">
            <strong>Total Duration:</strong> ${total_duration}s
        </div>
        <div class="metric">
            <strong>Success Rate:</strong> $(( (PASSED_SUITES * 100) / TOTAL_SUITES ))%
        </div>
    </div>

    <h2>Test Suite Results</h2>
EOF

    for result in "${SUITE_RESULTS[@]}"; do
        local suite_name=$(echo "$result" | cut -d: -f1)
        local status=$(echo "$result" | cut -d: -f2 | cut -d' ' -f1)
        local duration=$(echo "$result" | cut -d: -f2 | cut -d'(' -f2 | cut -d')' -f1)

        local css_class="passed"
        if [[ "$status" == "FAILED" ]]; then
            css_class="failed"
        elif [[ "$status" == "SKIPPED" ]]; then
            css_class="skipped"
        fi

        cat >> "$REPORT_FILE" << EOF
    <div class="suite $css_class">
        <strong>$suite_name</strong> - <span class="status-$css_class">$status</span> ($duration)
    </div>
EOF
    done

    cat >> "$REPORT_FILE" << EOF
</body>
</html>
EOF

    log "HTML report generated: $REPORT_FILE"
}

# Main execution
log "=========================================="
log "C-Relay Comprehensive Test Suite Runner"
log "=========================================="
log "Relay URL: $RELAY_URL"
log "Log file: $LOG_FILE"
log "Report file: $REPORT_FILE"
log ""

# Check if relay is running
if ! check_relay_status; then
    log "${RED}Cannot proceed without a running relay. Exiting.${NC}"
    exit 1
fi

log ""
log "Starting comprehensive test execution..."
log ""

# Record start time
OVERALL_START_TIME=$(date +%s)

# Run Security Test Suites
log "${BLUE}=== SECURITY TEST SUITES ===${NC}"

run_test_suite "SQL Injection Tests" "sql_injection_tests.sh" "Comprehensive SQL injection vulnerability testing"
run_test_suite "Filter Validation Tests" "filter_validation_test.sh" "Input validation for REQ and COUNT messages"
run_test_suite "Subscription Validation Tests" "subscription_validation.sh" "Subscription ID and message validation"
run_test_suite "Memory Corruption Tests" "memory_corruption_tests.sh" "Buffer overflow and memory safety testing"
run_test_suite "Input Validation Tests" "input_validation_tests.sh" "Comprehensive input boundary testing"

# Run Performance Test Suites
log ""
log "${BLUE}=== PERFORMANCE TEST SUITES ===${NC}"

run_test_suite "Subscription Limit Tests" "subscription_limits.sh" "Subscription limit enforcement testing"
run_test_suite "Load Testing" "load_tests.sh" "High concurrent connection testing"
run_test_suite "Stress Testing" "stress_tests.sh" "Resource usage and stability testing"
run_test_suite "Rate Limiting Tests" "rate_limiting_tests.sh" "Rate limiting and abuse prevention"

# Run Integration Test Suites
log ""
log "${BLUE}=== INTEGRATION TEST SUITES ===${NC}"

run_test_suite "NIP Protocol Tests" "run_nip_tests.sh" "All NIP protocol compliance tests"
run_test_suite "Configuration Tests" "config_tests.sh" "Configuration management and persistence"
run_test_suite "Authentication Tests" "auth_tests.sh" "NIP-42 authentication testing"

# Run Benchmarking Suites
log ""
log "${BLUE}=== BENCHMARKING SUITES ===${NC}"

run_test_suite "Performance Benchmarks" "performance_benchmarks.sh" "Performance metrics and benchmarking"
run_test_suite "Resource Monitoring" "resource_monitoring.sh" "Memory and CPU usage monitoring"

# Calculate total duration
OVERALL_END_TIME=$(date +%s)
TOTAL_DURATION=$((OVERALL_END_TIME - OVERALL_START_TIME))

# Generate final report
log ""
log "=========================================="
log "TEST EXECUTION COMPLETE"
log "=========================================="
log "Total test suites: $TOTAL_SUITES"
log "Passed: $PASSED_SUITES"
log "Failed: $FAILED_SUITES"
log "Skipped: $SKIPPED_SUITES"
log "Total duration: ${TOTAL_DURATION}s"
log "Success rate: $(( (PASSED_SUITES * 100) / TOTAL_SUITES ))%"
log ""
log "Detailed log: $LOG_FILE"

# Generate HTML report
generate_html_report "$TOTAL_DURATION"

# Exit with appropriate code
if [[ $FAILED_SUITES -eq 0 ]]; then
    log "${GREEN}✓ ALL TESTS PASSED${NC}"
    exit 0
else
    log "${RED}✗ SOME TESTS FAILED${NC}"
    log "Check $LOG_FILE for detailed error information"
    exit 1
fi