#!/usr/bin/env python3
"""
Compare wasot parser output with tree-sitter-wasot parser output.

Takes a number N and runs files 0000 through 000N from progressive_complexity/
through both parsers, comparing their s-expression outputs.

Usage:
    python scripts/compare_parsers.py 10      # Test files 0000-0010
    python scripts/compare_parsers.py 86      # Test all files
    python scripts/compare_parsers.py -1      # Test all files (shortcut)
    python scripts/compare_parsers.py -1 -v   # Verbose: show all output
"""

import argparse
import subprocess
import sys
from pathlib import Path


def get_wasot_sexp(file_path: Path) -> tuple[bool, str]:
    """Run wasot -t sexp on a file and return (success, output)."""
    try:
        result = subprocess.run(
            ["cargo", "run", "-q", "--bin", "wasot", "--", "-t", "sexp", str(file_path)],
            capture_output=True,
            text=True,
            timeout=10,
        )
        if result.returncode != 0:
            return False, result.stderr.strip()
        return True, result.stdout.strip()
    except subprocess.TimeoutExpired:
        return False, "TIMEOUT"
    except Exception as e:
        return False, str(e)


def get_treesitter_sexp(file_path: Path, ts_dir: Path) -> tuple[bool, str]:
    """Run tree-sitter parse on a file and return (success, output)."""
    try:
        result = subprocess.run(
            ["npx", "tree-sitter", "parse", str(file_path)],
            capture_output=True,
            text=True,
            timeout=10,
            cwd=ts_dir,
        )
        # tree-sitter returns 0 even with parse errors, but stderr has errors
        output = result.stdout.strip()
        has_error = "ERROR" in output or "MISSING" in output
        return not has_error, output
    except subprocess.TimeoutExpired:
        return False, "TIMEOUT"
    except Exception as e:
        return False, str(e)


def main():
    parser = argparse.ArgumentParser(
        description="Compare wasot and tree-sitter parsers on progressive_complexity files."
    )
    parser.add_argument(
        "max_num",
        type=int,
        help="Maximum file number to test (e.g., 10 for 0000-0010, -1 for all)",
    )
    parser.add_argument(
        "-v", "--verbose",
        action="store_true",
        help="Print output for all files, not just failures",
    )
    args = parser.parse_args()

    # Find the project root and paths
    script_dir = Path(__file__).parent
    project_root = script_dir.parent
    prog_dir = project_root / "progressive_complexity"
    ts_dir = project_root / "tree-sitter-wasot"

    if not prog_dir.exists():
        print(f"Error: {prog_dir} does not exist", file=sys.stderr)
        sys.exit(1)

    if not ts_dir.exists():
        print(f"Error: {ts_dir} does not exist", file=sys.stderr)
        sys.exit(1)

    # Get all wasot files, sorted
    all_files = sorted(prog_dir.glob("*.wasot"))

    if not all_files:
        print(f"Error: No .wasot files found in {prog_dir}", file=sys.stderr)
        sys.exit(1)

    # Filter by max number
    if args.max_num >= 0:
        files = [f for f in all_files if int(f.stem.split('_')[0]) <= args.max_num]
    else:
        files = all_files

    if args.verbose:
        print(f"Testing {len(files)} files from {prog_dir.name}/")
        print(f"{'=' * 70}")
        print()

    stats = {
        "total": len(files),
        "wasot_ok": 0,
        "treesitter_ok": 0,
        "both_ok": 0,
        "failures": 0,
    }

    failed_files = []

    for file_path in files:
        file_name = file_path.name

        # Get outputs from both parsers
        wasot_ok, wasot_out = get_wasot_sexp(file_path)
        ts_ok, ts_out = get_treesitter_sexp(file_path, ts_dir)

        # Update stats
        if wasot_ok:
            stats["wasot_ok"] += 1
        if ts_ok:
            stats["treesitter_ok"] += 1
        if wasot_ok and ts_ok:
            stats["both_ok"] += 1

        # Determine status
        both_ok = wasot_ok and ts_ok

        if both_ok:
            status = "✓ BOTH OK"
        elif wasot_ok and not ts_ok:
            status = "⚠ WASOT OK, TREE-SITTER ERROR"
            stats["failures"] += 1
            failed_files.append(file_name)
        elif not wasot_ok and ts_ok:
            status = "⚠ WASOT ERROR, TREE-SITTER OK"
            stats["failures"] += 1
            failed_files.append(file_name)
        else:
            status = "✗ BOTH ERROR"
            stats["failures"] += 1
            failed_files.append(file_name)

        # Only print if verbose OR if there's a failure
        should_print = args.verbose or not both_ok

        if should_print:
            print(f"{'─' * 70}")
            print(f"FILE: {file_name}")
            print(f"STATUS: {status}")
            print()

            print("WASOT OUTPUT:")
            if wasot_ok:
                print(wasot_out if wasot_out else "(empty)")
            else:
                print(f"ERROR: {wasot_out}")
            print()

            print("TREE-SITTER OUTPUT:")
            if ts_ok:
                print(ts_out if ts_out else "(empty)")
            else:
                print(f"ERROR/PARSE ISSUE: {ts_out}")
            print()

    # Print summary
    if args.verbose or stats["failures"] > 0:
        print(f"{'=' * 70}")
        print("SUMMARY")
        print(f"{'=' * 70}")
        print(f"Total files tested: {stats['total']}")
        print(f"Wasot parsed OK:    {stats['wasot_ok']}/{stats['total']}")
        print(f"Tree-sitter OK:     {stats['treesitter_ok']}/{stats['total']}")
        print(f"Both parsers OK:    {stats['both_ok']}/{stats['total']}")
        print()

    if stats["failures"] > 0:
        print(f"✗ {stats['failures']} file(s) with errors:")
        for f in failed_files:
            print(f"  - {f}")
        sys.exit(1)
    else:
        if args.verbose:
            print("✓ All files parsed successfully by both parsers!")
        sys.exit(0)


if __name__ == "__main__":
    main()
