#!/bin/bash

# Comprehensive test runner for hyperscan-tokio
# This script runs all tests including property-based tests, edge cases, stress tests, and fuzzing

set -e

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

# Function to print colored output
print_status() {
    echo -e "${GREEN}[*]${NC} $1"
}

print_error() {
    echo -e "${RED}[!]${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}[!]${NC} $1"
}

# Parse command line arguments
RUN_UNIT=true
RUN_INTEGRATION=true
RUN_PROPTEST=true
RUN_STRESS=true
RUN_FUZZ=false
FUZZ_TIME=60
THREADS=

while [[ $# -gt 0 ]]; do
    case $1 in
        --no-unit)
            RUN_UNIT=false
            shift
            ;;
        --no-integration)
            RUN_INTEGRATION=false
            shift
            ;;
        --no-proptest)
            RUN_PROPTEST=false
            shift
            ;;
        --no-stress)
            RUN_STRESS=false
            shift
            ;;
        --fuzz)
            RUN_FUZZ=true
            shift
            ;;
        --fuzz-time)
            FUZZ_TIME="$2"
            shift 2
            ;;
        --threads)
            THREADS="$2"
            shift 2
            ;;
        --help)
            echo "Usage: $0 [options]"
            echo "Options:"
            echo "  --no-unit         Skip unit tests"
            echo "  --no-integration  Skip integration tests"
            echo "  --no-proptest     Skip property-based tests"
            echo "  --no-stress       Skip stress tests"
            echo "  --fuzz            Run fuzzing tests"
            echo "  --fuzz-time N     Run each fuzzer for N seconds (default: 60)"
            echo "  --threads N       Number of threads for tests"
            echo "  --help            Show this help message"
            exit 0
            ;;
        *)
            print_error "Unknown option: $1"
            exit 1
            ;;
    esac
done

# Set thread count if specified
if [ -n "$THREADS" ]; then
    export RUST_TEST_THREADS=$THREADS
fi

# Run unit tests
if [ "$RUN_UNIT" = true ]; then
    print_status "Running unit tests..."
    cargo test --lib
fi

# Run integration tests
if [ "$RUN_INTEGRATION" = true ]; then
    print_status "Running integration tests..."
    cargo test --tests integration
fi

# Run property-based tests
if [ "$RUN_PROPTEST" = true ]; then
    print_status "Running property-based tests..."
    cargo test --test proptest_tests
    cargo test --test proptest_advanced_tests
fi

# Run edge case tests
print_status "Running edge case tests..."
cargo test --test edge_case_tests

# Run stress tests
if [ "$RUN_STRESS" = true ]; then
    print_status "Running stress tests..."
    print_warning "This may take a while and use significant resources..."
    cargo test --test stress_tests --release
    cargo test --test stress_tests_extended --release
fi

# Run fuzzing tests
if [ "$RUN_FUZZ" = true ]; then
    if ! command -v cargo-fuzz &> /dev/null; then
        print_error "cargo-fuzz not found. Install with: cargo install cargo-fuzz"
        exit 1
    fi
    
    print_status "Running fuzz tests (${FUZZ_TIME}s each)..."
    
    FUZZ_TARGETS=(
        "fuzz_pattern_compile_enhanced"
        "fuzz_scan_comprehensive"
        "fuzz_edge_cases"
        "fuzz_streaming"
        "fuzz_database_serialization"
    )
    
    for target in "${FUZZ_TARGETS[@]}"; do
        print_status "Fuzzing $target for ${FUZZ_TIME}s..."
        cd fuzz
        cargo +nightly fuzz run "$target" -- -max_total_time="$FUZZ_TIME" || true
        cd ..
    done
    
    # Run Chimera fuzzer if feature is enabled
    if cargo test --features chimera --lib 2>/dev/null; then
        print_status "Fuzzing fuzz_chimera for ${FUZZ_TIME}s..."
        cd fuzz
        cargo +nightly fuzz run fuzz_chimera -- -max_total_time="$FUZZ_TIME" || true
        cd ..
    fi
fi

# Run feature-specific tests
print_status "Running feature-specific tests..."

# Test with different allocators
if cargo test --no-default-features --features mimalloc,simd-accel,system --lib 2>/dev/null; then
    print_status "Testing with mimalloc..."
    cargo test --no-default-features --features mimalloc,simd-accel,system --lib
fi

# Test with arrow feature
if cargo test --features arrow --lib 2>/dev/null; then
    print_status "Testing with arrow feature..."
    cargo test --features arrow --test proptest_advanced_tests
fi

# Test with chimera feature
if cargo test --features chimera --lib 2>/dev/null; then
    print_status "Testing with chimera feature..."
    cargo test --features chimera --test edge_case_tests
    cargo test --features chimera --test proptest_tests
fi

# Generate test coverage report (optional)
if command -v cargo-tarpaulin &> /dev/null; then
    print_status "Generating coverage report..."
    cargo tarpaulin --out Html --output-dir target/coverage
    print_status "Coverage report generated at target/coverage/tarpaulin-report.html"
fi

print_status "All tests completed successfully!"
