#![no_main]

use imara_diff::{Algorithm, BasicLineDiffPrinter, Diff, InternedInput, UnifiedDiffConfig};
use libfuzzer_sys::arbitrary;
use libfuzzer_sys::fuzz_target;

/// Valid prefixes for unified diff output lines
const VALID_DIFF_LINE_PREFIXES: [char; 4] = [' ', '+', '-', '@'];

#[derive(arbitrary::Arbitrary, Debug)]
struct Input<'a> {
    before: &'a str,
    after: &'a str,
    context_len: u32,
}

/// Tests unified diff printing with:
/// - Different context lengths (0-10)
/// - Various input combinations
/// - Validates output format (lines start with ' ', '+', '-', or '@')
fn do_fuzz(
    Input {
        before,
        after,
        context_len,
    }: Input<'_>,
) {
    let input = InternedInput::new(before, after);

    // Test with different algorithms
    for algorithm in [
        Algorithm::Histogram,
        Algorithm::Myers,
        Algorithm::MyersMinimal,
    ] {
        let mut diff = Diff::compute(algorithm, &input);

        // Postprocess before printing
        diff.postprocess_lines(&input);

        // Create printer and config
        let printer = BasicLineDiffPrinter(&input.interner);
        let mut config = UnifiedDiffConfig::default();
        config.context_len(context_len);

        // Generate unified diff
        let unified = diff.unified_diff(&printer, config, &input);
        let output = unified.to_string();

        // Basic sanity checks on output
        // It should be valid UTF-8 (already guaranteed by to_string)
        // Lines should start with valid diff prefixes
        for line in output.lines() {
            if !line.is_empty() {
                let first_char = line.chars().next().unwrap();
                // Should be a valid diff line prefix
                assert!(
                    VALID_DIFF_LINE_PREFIXES.contains(&first_char),
                    "Invalid diff line prefix: '{}' in line: '{}'",
                    first_char,
                    line
                );
            }
        }
    }
}

fuzz_target!(|input: Input<'_>| {
    do_fuzz(input);
});
