#!/bin/bash

# Fuzzer Script for Wasot Compiler
# Runs fuzz testing to find edge cases and crashes

set -e

echo "🔍 Fuzzing Wasot Compiler Parser"
echo "================================"

# Check if we're in the right directory
if [ ! -f "Cargo.toml" ]; then
    echo "❌ Error: This script must be run from the project root directory"
    exit 1
fi

# Install cargo-fuzz if not already installed
if ! command -v cargo-fuzz &> /dev/null; then
    echo "📦 Installing cargo-fuzz..."
    cargo install cargo-fuzz
fi

# Create fuzz directory if it doesn't exist
if [ ! -d "fuzz" ]; then
    echo "🏗️  Setting up fuzz testing environment..."
    cargo fuzz init
fi

# Create fuzz target for parser if it doesn't exist
FUZZ_TARGET="fuzz/fuzz_targets/fuzz_parser.rs"
if [ ! -f "$FUZZ_TARGET" ]; then
    echo "📝 Creating parser fuzz target..."
    cargo fuzz add fuzz_parser
    
    # Write the fuzz target
    cat > "$FUZZ_TARGET" << 'EOF'
#![no_main]
use libfuzzer_sys::fuzz_target;
use wasot_compiler::{MetaLine, is_meta_line, parse_string};

fuzz_target!(|data: &[u8]| {
    // Convert bytes to string, ignoring invalid UTF-8
    if let Ok(input) = std::str::from_utf8(data) {
        // Test meta-line detection
        for line in input.lines() {
            let _ = is_meta_line(line);
            
            // Test meta-line parsing
            if is_meta_line(line) {
                let _ = MetaLine::parse(line);
            }
        }
        
        // Test full document parsing
        let _ = parse_string(input);
    }
});
EOF
fi

# Create fuzz target for XML converter if it doesn't exist
XML_FUZZ_TARGET="fuzz/fuzz_targets/fuzz_xml.rs"
if [ ! -f "$XML_FUZZ_TARGET" ]; then
    echo "📝 Creating XML converter fuzz target..."
    cargo fuzz add fuzz_xml
    
    # Write the XML fuzz target
    cat > "$XML_FUZZ_TARGET" << 'EOF'
#![no_main]
use libfuzzer_sys::fuzz_target;
use wasot_compiler::convert_string_to_xml_string;

fuzz_target!(|data: &[u8]| {
    // Convert bytes to string, ignoring invalid UTF-8
    if let Ok(input) = std::str::from_utf8(data) {
        // Test XML conversion
        let _ = convert_string_to_xml_string(input, false);
        let _ = convert_string_to_xml_string(input, true);
    }
});
EOF
fi

# Set default fuzz duration
FUZZ_DURATION=${1:-30}

echo "⏱️  Fuzzing duration: ${FUZZ_DURATION} seconds"
echo "🎯 Targets: parser, XML converter"
echo ""

# Create a corpus directory with some initial test cases
mkdir -p fuzz/corpus/fuzz_parser
mkdir -p fuzz/corpus/fuzz_xml

# Add some seed inputs
echo ".div" > fuzz/corpus/fuzz_parser/simple_div
echo ".p some text" > fuzz/corpus/fuzz_parser/paragraph_with_text
echo ".div .. class=\"main\"" > fuzz/corpus/fuzz_parser/div_with_params
echo "..h2 Title" > fuzz/corpus/fuzz_parser/nested_header
echo ".div :main-id" > fuzz/corpus/fuzz_parser/div_with_id
echo "text line" > fuzz/corpus/fuzz_parser/text_line

# Copy parser corpus to XML corpus
cp -r fuzz/corpus/fuzz_parser/* fuzz/corpus/fuzz_xml/ 2>/dev/null || true

echo "🚀 Starting parser fuzzing..."
echo "Press Ctrl+C to stop early"
echo ""

# Run parser fuzzing
timeout "${FUZZ_DURATION}s" cargo fuzz run fuzz_parser -- -max_total_time="${FUZZ_DURATION}" || true

echo ""
echo "🚀 Starting XML converter fuzzing..."
echo ""

# Run XML converter fuzzing  
timeout "${FUZZ_DURATION}s" cargo fuzz run fuzz_xml -- -max_total_time="${FUZZ_DURATION}" || true

echo ""
echo "🎉 Fuzzing Complete!"
echo "==================="
echo ""
echo "📊 Results:"
echo "   - Parser fuzz corpus: fuzz/corpus/fuzz_parser/"
echo "   - XML fuzz corpus: fuzz/corpus/fuzz_xml/"
echo "   - Crash artifacts: fuzz/artifacts/"
echo ""

# Check for crashes
if [ -d "fuzz/artifacts" ] && [ "$(ls -A fuzz/artifacts/)" ]; then
    echo "🚨 CRASHES FOUND!"
    echo "=================="
    echo "Crash artifacts saved in fuzz/artifacts/"
    echo ""
    for crash in fuzz/artifacts/*; do
        if [ -f "$crash" ]; then
            echo "💥 Crash: $(basename "$crash")"
            echo "   Size: $(stat -c%s "$crash") bytes"
        fi
    done
    echo ""
    echo "🔍 To reproduce crashes:"
    echo "   cargo fuzz run fuzz_parser fuzz/artifacts/[crash_file]"
    echo ""
else
    echo "✅ No crashes found during fuzzing!"
fi

echo "🔧 To continue fuzzing:"
echo "   cargo fuzz run fuzz_parser"
echo "   cargo fuzz run fuzz_xml"
echo ""
echo "📈 To view coverage:"
echo "   cargo fuzz coverage fuzz_parser"
echo ""