#!/usr/bin/env python3
"""Simple parity test to verify basic functionality with smart JSON comparison."""

import subprocess
import json
import sys
from pathlib import Path
from loguru import logger
from typing import Dict, Any, List, Tuple
from hypothesis import given, settings, strategies as st
import pytest


def smart_json_compare(
    python_data: Dict[str, Any], perl_data: Dict[str, Any], tolerance: float = 1e-6
) -> Tuple[bool, List[str]]:
    """
    Compare JSON data from Python and Perl implementations with smart handling of:
    - Interval values (tolerances for floating point differences)
    - Different field names (map equivalent fields)
    - Missing fields (report fields that don't exist in both)
    - String normalization (trim whitespace, case insensitive where appropriate)
    - Complete field validation (ensure all fields match)
    """
    differences = []

    # Field mapping between Python and Perl outputs
    field_mapping = {
        # Direct field mappings (when both have same field name)
        "year": "year",
        "month": "month",
        "day": "day",
        "saka_year": "saka_year",
        "vikrama_year": "vikrama_year",
        "masa": "masa",
        "paksa": "paksa",
        "tithi": "tithi",
        "naksatra": "naksatra",
        "modern_year": "modern_year",
        "modern_month": "modern_month",
        "modern_day": "modern_day",
        "weekday": "weekday",
        # Additional mappings for verbose command
        "weekday_name": "weekday_name",
        "sukla_krsna": "sukla_krsna",
        "tithi_day": "tithi_day",
    }

    # Fields to ignore (advanced calculations not implemented in Perl)
    ignored_fields = {
        "next_samkranti_year",
        "next_samkranti_month",
        "next_samkranti_day",
        "next_samkranti_hour",
        "next_samkranti_minute",
        "vikrama_solar_year",
        "vikram_saura_masa",
    }

    # Fields that should be compared with tolerance (floating point)
    tolerance_fields = {
        "ftithi",
        "ahargana",
        "julian_day",
        "tslong",
        "tllong",
        "ayanadeg",
        "ayanamin",
        "sunrise_hour",
        "sunrise_minute",
    }

    # Fields that should be normalized (trimmed strings)
    normalize_fields = {
        "masa",
        "paksa",
        "sukla_krsna",
        "naksatra",
        "karana",
        "yoga",
        "weekday",
        "weekday_name",
        "saura_masa",
        "vikram_saura_masa",
    }

    def normalize_string(value: str) -> str:
        """Normalize string by trimming whitespace and converting to lowercase for comparison."""
        if isinstance(value, str):
            return value.strip().lower()
        return value

    def get_nested_value(data: Dict[str, Any], key: str) -> Any:
        """Get value from nested dictionary using dot notation."""
        keys = key.split(".")
        value = data
        for k in keys:
            if isinstance(value, dict) and k in value:
                value = value[k]
            else:
                return None
        return value

    def compare_values(python_val: Any, perl_val: Any, field_name: str) -> bool:
        """Compare two values with appropriate tolerance/normalization."""
        if python_val is None or perl_val is None:
            return python_val == perl_val

        # Handle floating point comparison with tolerance
        if field_name in tolerance_fields:
            try:
                py_float = float(python_val)
                pl_float = float(perl_val)
                return abs(py_float - pl_float) <= tolerance
            except (ValueError, TypeError):
                return python_val == perl_val

        # Handle string normalization
        if field_name in normalize_fields:
            py_str = normalize_string(str(python_val))
            pl_str = normalize_string(str(perl_val))
            return py_str == pl_str

        # Direct comparison for other types
        return python_val == perl_val

    # Collect all unique field names from both datasets
    python_fields = set()
    perl_fields = set()

    # Add fields from Python data (including nested)
    def collect_fields(data: Dict[str, Any], prefix: str = ""):
        fields = set()
        for key, value in data.items():
            full_key = f"{prefix}.{key}" if prefix else key
            if isinstance(value, dict):
                fields.update(collect_fields(value, full_key))
            else:
                fields.add(full_key)
        return fields

    python_fields = collect_fields(python_data)
    perl_fields = collect_fields(perl_data)

    # Check for missing fields in Perl (Python has field but Perl doesn't)
    for py_field in python_fields:
        # Skip ignored fields
        if py_field in ignored_fields:
            continue

        perl_field = field_mapping.get(py_field, py_field)
        if perl_field not in perl_fields:
            differences.append(f"Field '{py_field}' exists in Python but missing in Perl")
        else:
            python_val = get_nested_value(python_data, py_field)
            perl_val = get_nested_value(perl_data, perl_field)

            if not compare_values(python_val, perl_val, py_field):
                differences.append(
                    f"Field '{py_field}' differs: Python={python_val}, Perl={perl_val}"
                )

    # Check for extra fields in Perl (Perl has field but Python doesn't)
    for pl_field in perl_fields:
        # Skip ignored fields
        if pl_field in ignored_fields:
            continue

        python_field = None
        # Find the Python field that maps to this Perl field
        for py_field, mapped_field in field_mapping.items():
            if mapped_field == pl_field:
                python_field = py_field
                break

        if python_field is None:
            python_field = pl_field  # Direct mapping

        if python_field not in python_fields:
            differences.append(f"Field '{pl_field}' exists in Perl but missing in Python")

    return len(differences) == 0, differences


def parse_json_lines(json_text: str) -> List[Dict[str, Any]]:
    """Parse multiple JSON objects from text (one per line)."""
    results = []
    lines = json_text.strip().split("\n")
    current_json = ""
    brace_count = 0

    for line in lines:
        line = line.strip()
        if not line:
            continue

        current_json += line

        # Count braces to determine when we have a complete JSON object
        brace_count += line.count("{") - line.count("}")

        if brace_count == 0 and current_json:
            try:
                results.append(json.loads(current_json))
                current_json = ""
            except json.JSONDecodeError:
                # If parsing fails, try to continue with next object
                current_json = ""
                continue

    return results


def test_simple_parity():
    """Test basic parity between Python and Perl implementations with smart JSON comparison."""

    project_root = Path(__file__).parent.parent.parent.parent
    perl_script = project_root / "perl-panchanga-implementation" / "src" / "pancanga.pl"

    logger.info("=" * 80)
    logger.info("PANCHANGA PARITY TEST - Python vs Perl Implementation")
    logger.info("=" * 80)
    logger.info(f"Project root: {project_root}")
    logger.info(f"Perl script: {perl_script}")
    logger.info(f"Python executable: {sys.executable}")
    logger.info("")

    # Track overall test results
    try_command_passed = False
    list_command_passed = False
    verbose_command_passed = False
    all_differences = []

    # Test case: Saka 1945, Caitra (month 0), Sukla paksa, tithi 1
    logger.info("1. TESTING TRY COMMAND")
    logger.info("-" * 50)
    logger.info("Test case: Saka 1945, Caitra (month 0), Sukla paksa, tithi 1")
    logger.info(
        "Expected: Find the modern date for Saka year 1945, Caitra month, Sukla paksa, tithi 1"
    )
    logger.info("")

    # Python command
    python_cmd = [
        sys.executable,
        "-m",
        "panchanga_cli.cli",
        "--json",
        "try",
        "1945",
        "0",
        "1",
        "--year-system",
        "saka",
        "--paksa",
        "S",
    ]
    logger.info(f"Python command: {' '.join(python_cmd)}")

    python_data = None
    try:
        logger.info("Executing Python command...")
        python_result = subprocess.run(python_cmd, capture_output=True, text=True, timeout=30)
        logger.info(f"Python exit code: {python_result.returncode}")
        if python_result.returncode == 0:
            python_data = json.loads(python_result.stdout)
            logger.info("✅ Python command succeeded")
            logger.info(f"Python JSON output: {json.dumps(python_data, indent=2)}")
        else:
            logger.error(f"❌ Python command failed: {python_result.stderr}")
    except Exception as e:
        logger.error(f"❌ Python exception: {e}")

    # Perl command
    perl_cmd = [
        "perl",
        str(perl_script),
        "try",
        "1945",
        "0",
        "1",
        "--paksa",
        "S",
        "--year-system",
        "S",
        "--json",
    ]
    logger.info(f"Perl command: {' '.join(perl_cmd)}")

    perl_data = None
    try:
        logger.info("Executing Perl command...")
        perl_result = subprocess.run(
            perl_cmd,
            cwd=project_root / "perl-panchanga-implementation" / "src",
            capture_output=True,
            text=True,
            timeout=30,
        )
        logger.info(f"Perl exit code: {perl_result.returncode}")
        if perl_result.returncode == 0:
            perl_data = json.loads(perl_result.stdout)
            logger.info("✅ Perl command succeeded")
            logger.info(f"Perl JSON output: {json.dumps(perl_data, indent=2)}")
        else:
            logger.error(f"❌ Perl command failed: {perl_result.stderr}")
        if perl_result.stderr:
            logger.warning(f"Perl stderr: {repr(perl_result.stderr)}")
    except Exception as e:
        logger.error(f"❌ Perl exception: {e}")

    # Smart comparison for try command
    logger.info("")
    logger.info("COMPARING TRY COMMAND RESULTS")
    logger.info("-" * 50)
    if python_data and perl_data:
        logger.info("Both Python and Perl commands succeeded, comparing outputs...")
        match, differences = smart_json_compare(python_data, perl_data)
        if match:
            logger.info("✅ Try command: Python and Perl outputs match perfectly!")
            try_command_passed = True
        else:
            logger.error("❌ Try command: Differences found between Python and Perl outputs:")
            for diff in differences:
                logger.error(f"  - {diff}")
            all_differences.extend([f"Try command: {diff}" for diff in differences])
    else:
        logger.error("⚠️ Try command: Could not compare (missing data)")
        all_differences.append("Try command: Could not compare (missing data)")

    logger.info("")
    logger.info("2. TESTING LIST COMMAND")
    logger.info("-" * 50)
    logger.info("Test case: List 10 days starting from 2023-03-23")
    logger.info("Expected: Generate panchanga data for 10 consecutive days")
    logger.info("")

    # Python list command
    python_list_cmd = [
        sys.executable,
        "-m",
        "panchanga_cli.cli",
        "--json",
        "list",
        "2023 3 23",
    ]
    logger.info(f"Python list command: {' '.join(python_list_cmd)}")

    python_list_data = None
    try:
        logger.info("Executing Python list command...")
        python_list_result = subprocess.run(
            python_list_cmd, capture_output=True, text=True, timeout=30
        )
        logger.info(f"Python list exit code: {python_list_result.returncode}")
        if python_list_result.returncode == 0:
            python_list_data = parse_json_lines(python_list_result.stdout)
            logger.info(f"✅ Python list command succeeded - {len(python_list_data)} entries")
            logger.info("Python list output (first 3 entries):")
            for i, entry in enumerate(python_list_data[:3]):
                logger.info(f"  Entry {i + 1}: {json.dumps(entry, indent=4)}")
        else:
            logger.error(f"❌ Python list command failed: {python_list_result.stderr}")
    except Exception as e:
        logger.error(f"❌ Python list exception: {e}")

    # Perl list command
    perl_list_cmd = ["perl", str(perl_script), "list", "2023", "3", "23", "--json"]
    logger.info(f"Perl list command: {' '.join(perl_list_cmd)}")

    perl_list_data = None
    try:
        logger.info("Executing Perl list command...")
        perl_list_result = subprocess.run(
            perl_list_cmd,
            cwd=project_root / "perl-panchanga-implementation" / "src",
            capture_output=True,
            text=True,
            timeout=30,
        )
        logger.info(f"Perl list exit code: {perl_list_result.returncode}")
        if perl_list_result.returncode == 0:
            perl_list_data = parse_json_lines(perl_list_result.stdout)
            logger.info(f"✅ Perl list command succeeded - {len(perl_list_data)} entries")
            logger.info("Perl list output (first 3 entries):")
            for i, entry in enumerate(perl_list_data[:3]):
                logger.info(f"  Entry {i + 1}: {json.dumps(entry, indent=4)}")
        else:
            logger.error(f"❌ Perl list command failed: {perl_list_result.stderr}")
        if perl_list_result.stderr:
            logger.warning(f"Perl list stderr: {repr(perl_list_result.stderr)}")
    except Exception as e:
        logger.error(f"❌ Perl list exception: {e}")

    # Smart comparison for list command
    logger.info("")
    logger.info("COMPARING LIST COMMAND RESULTS")
    logger.info("-" * 50)
    if python_list_data and perl_list_data:
        logger.info("Both Python and Perl list commands succeeded")
        logger.info(f"Python entries: {len(python_list_data)}, Perl entries: {len(perl_list_data)}")
        all_match = True
        total_differences = []

        # Compare each day's data
        min_entries = min(len(python_list_data), len(perl_list_data))
        logger.info(f"Comparing first {min_entries} entries...")

        for i in range(min_entries):
            match, differences = smart_json_compare(python_list_data[i], perl_list_data[i])
            if not match:
                all_match = False
                total_differences.extend([f"Day {i + 1}: {diff}" for diff in differences])
                logger.warning(f"Day {i + 1} has {len(differences)} differences")

        if all_match:
            logger.info(f"✅ List command: All {min_entries} days match between Python and Perl!")
            list_command_passed = True
        else:
            logger.error(f"❌ List command: Found differences in {len(total_differences)} fields:")
            for diff in total_differences[:10]:  # Show first 10 differences
                logger.error(f"  - {diff}")
            if len(total_differences) > 10:
                logger.error(f"  ... and {len(total_differences) - 10} more differences")
            all_differences.extend([f"List command: {diff}" for diff in total_differences])
    else:
        logger.error("⚠️ List command: Could not compare (missing data)")
        all_differences.append("List command: Could not compare (missing data)")

    logger.info("")
    logger.info("3. TESTING VERBOSE COMMAND")
    logger.info("-" * 50)
    logger.info("Test case: Verbose output for 2023-03-23 with Kathmandu coordinates")
    logger.info("Expected: Detailed panchanga information including astronomical calculations")
    logger.info("")

    # Python verbose command with Kathmandu coordinates
    python_verbose_cmd = [
        sys.executable,
        "-m",
        "panchanga_cli.cli",
        "--json",
        "--place",
        "kathmandu",
        "verbose",
        "2023 3 23",
    ]
    logger.info(f"Python verbose command: {' '.join(python_verbose_cmd)}")

    python_verbose_data = None
    try:
        logger.info("Executing Python verbose command...")
        python_verbose_result = subprocess.run(
            python_verbose_cmd, capture_output=True, text=True, timeout=30
        )
        logger.info(f"Python verbose exit code: {python_verbose_result.returncode}")
        if python_verbose_result.returncode == 0:
            python_verbose_data = json.loads(python_verbose_result.stdout)
            logger.info("✅ Python verbose command succeeded")
            logger.info(f"Python verbose output: {json.dumps(python_verbose_data, indent=2)}")
        else:
            logger.error(f"❌ Python verbose command failed: {python_verbose_result.stderr}")
    except Exception as e:
        logger.error(f"❌ Python verbose exception: {e}")

    # Perl verbose command with Kathmandu coordinates
    perl_verbose_cmd = [
        "perl",
        str(perl_script),
        "--place",
        "kathmandu",
        "verbose",
        "2023",
        "3",
        "23",
        "--json",
    ]
    logger.info(f"Perl verbose command: {' '.join(perl_verbose_cmd)}")

    perl_verbose_data = None
    try:
        logger.info("Executing Perl verbose command...")
        perl_verbose_result = subprocess.run(
            perl_verbose_cmd,
            cwd=project_root / "perl-panchanga-implementation" / "src",
            capture_output=True,
            text=True,
            timeout=30,
        )
        logger.info(f"Perl verbose exit code: {perl_verbose_result.returncode}")
        if perl_verbose_result.returncode == 0:
            perl_verbose_data = json.loads(perl_verbose_result.stdout)
            logger.info("✅ Perl verbose command succeeded")
            logger.info(f"Perl verbose output: {json.dumps(perl_verbose_data, indent=2)}")
        else:
            logger.error(f"❌ Perl verbose command failed: {perl_verbose_result.stderr}")
        if perl_verbose_result.stderr:
            logger.warning(f"Perl verbose stderr: {repr(perl_verbose_result.stderr)}")
    except Exception as e:
        logger.error(f"❌ Perl verbose exception: {e}")

    # Smart comparison for verbose command
    logger.info("")
    logger.info("COMPARING VERBOSE COMMAND RESULTS")
    logger.info("-" * 50)
    verbose_command_passed = False
    if python_verbose_data and perl_verbose_data:
        logger.info("Both Python and Perl verbose commands succeeded, comparing outputs...")
        match, differences = smart_json_compare(python_verbose_data, perl_verbose_data)
        if match:
            logger.info("✅ Verbose command: Python and Perl outputs match perfectly!")
            verbose_command_passed = True
        else:
            logger.error("❌ Verbose command: Differences found between Python and Perl outputs:")
            for diff in differences:
                logger.error(f"  - {diff}")
            all_differences.extend([f"Verbose command: {diff}" for diff in differences])
    else:
        logger.error("⚠️ Verbose command: Could not compare (missing data)")
        all_differences.append("Verbose command: Could not compare (missing data)")

    logger.info("")
    logger.info("4. TEST SUMMARY")
    logger.info("=" * 80)
    logger.info("Smart JSON comparison completed with tolerance handling for floating point values")
    logger.info("and normalization for string comparisons.")
    logger.info("")

    # Summary of results
    logger.info("RESULTS SUMMARY:")
    logger.info(f"  Try command: {'✅ PASSED' if try_command_passed else '❌ FAILED'}")
    logger.info(f"  List command: {'✅ PASSED' if list_command_passed else '❌ FAILED'}")
    logger.info(f"  Verbose command: {'✅ PASSED' if verbose_command_passed else '❌ FAILED'}")
    logger.info(f"  Total differences found: {len(all_differences)}")

    if all_differences:
        logger.info("")
        logger.error("OVERALL RESULT: ❌ PARITY TEST FAILED")
        logger.error("The Python and Perl implementations are not producing identical outputs.")
    else:
        logger.info("")
        logger.info("OVERALL RESULT: ✅ PARITY TEST PASSED")
        logger.info("The Python and Perl implementations are producing identical outputs!")

    logger.info("=" * 80)

    # Fail the test if there are any differences
    if all_differences:
        error_message = f"Parity test failed with {len(all_differences)} differences:\n"
        for diff in all_differences[:20]:  # Show first 20 differences
            error_message += f"  - {diff}\n"
        if len(all_differences) > 20:
            error_message += f"  ... and {len(all_differences) - 20} more differences\n"

        # Use pytest's assert to fail the test
        assert False, error_message

    # If we get here, all tests passed
    assert try_command_passed, "Try command parity test failed"
    assert list_command_passed, "List command parity test failed"
    assert verbose_command_passed, "Verbose command parity test failed"


@pytest.mark.slow
@given(
    year=st.integers(min_value=1800, max_value=2200),
    month=st.integers(min_value=1, max_value=12),
    day=st.integers(min_value=1, max_value=28),  # Use 28 to avoid invalid dates
)
@settings(max_examples=50, deadline=None)  # 1000 random dates
def test_list_command_parity_hypothesis(year, month, day):
    """Property-based test: Verify list command parity across random dates from 1800-2200."""

    project_root = Path(__file__).parent.parent.parent.parent
    perl_script = project_root / "perl-panchanga-implementation" / "src" / "pancanga.pl"

    # Python list command
    python_list_cmd = [
        sys.executable,
        "-m",
        "panchanga_cli.cli",
        "--json",
        "list",
        f"{year} {month} {day}",
    ]

    # Perl list command
    perl_list_cmd = [
        "perl",
        str(perl_script),
        "list",
        str(year),
        str(month),
        str(day),
        "--json",
    ]

    python_list_data = None
    perl_list_data = None

    try:
        # Execute Python command
        python_list_result = subprocess.run(
            python_list_cmd, capture_output=True, text=True, timeout=30
        )
        if python_list_result.returncode == 0:
            python_list_data = parse_json_lines(python_list_result.stdout)

        # Execute Perl command
        perl_list_result = subprocess.run(
            perl_list_cmd,
            cwd=project_root / "perl-panchanga-implementation" / "src",
            capture_output=True,
            text=True,
            timeout=30,
        )
        if perl_list_result.returncode == 0:
            perl_list_data = parse_json_lines(perl_list_result.stdout)

        # Compare results if both succeeded
        if python_list_data and perl_list_data:
            assert len(python_list_data) == len(perl_list_data), (
                f"Date {year}-{month}-{day}: Different number of entries - Python: {len(python_list_data)}, Perl: {len(perl_list_data)}"
            )

            # Compare first entry (the requested date)
            if len(python_list_data) > 0 and len(perl_list_data) > 0:
                match, differences = smart_json_compare(python_list_data[0], perl_list_data[0])
                assert match, (
                    f"Date {year}-{month}-{day}: Parity mismatch in first entry:\n"
                    + "\n".join(differences[:5])
                )

    except subprocess.TimeoutExpired:
        # Skip tests that timeout (very rare edge cases)
        pass
    except Exception as e:
        # Log unexpected errors but don't fail the test
        logger.warning(f"Date {year}-{month}-{day}: Exception during test: {e}")


@pytest.mark.slow
@given(
    year=st.integers(min_value=1800, max_value=2200),
    month=st.integers(min_value=1, max_value=12),
    day=st.integers(min_value=1, max_value=28),  # Use 28 to avoid invalid dates
)
@settings(max_examples=50, deadline=None)  # 1000 random dates
def test_verbose_command_parity_hypothesis(year, month, day):
    """Property-based test: Verify verbose command parity across random dates from 1800-2200."""

    project_root = Path(__file__).parent.parent.parent.parent
    perl_script = project_root / "perl-panchanga-implementation" / "src" / "pancanga.pl"

    # Python verbose command (with Kathmandu coordinates)
    python_verbose_cmd = [
        sys.executable,
        "-m",
        "panchanga_cli.cli",
        "--json",
        "--place",
        "kathmandu",
        "verbose",
        f"{year} {month} {day}",
    ]

    # Perl verbose command (with Kathmandu coordinates)
    perl_verbose_cmd = [
        "perl",
        str(perl_script),
        "--place",
        "kathmandu",
        "verbose",
        str(year),
        str(month),
        str(day),
        "--json",
    ]

    python_verbose_data = None
    perl_verbose_data = None

    try:
        # Execute Python command
        python_verbose_result = subprocess.run(
            python_verbose_cmd, capture_output=True, text=True, timeout=30
        )
        if python_verbose_result.returncode == 0:
            python_verbose_data = json.loads(python_verbose_result.stdout)

        # Execute Perl command
        perl_verbose_result = subprocess.run(
            perl_verbose_cmd,
            cwd=project_root / "perl-panchanga-implementation" / "src",
            capture_output=True,
            text=True,
            timeout=30,
        )
        if perl_verbose_result.returncode == 0:
            perl_verbose_data = json.loads(perl_verbose_result.stdout)

        # Compare results if both succeeded
        if python_verbose_data and perl_verbose_data:
            match, differences = smart_json_compare(python_verbose_data, perl_verbose_data)
            assert match, (
                f"Date {year}-{month}-{day}: Parity mismatch in verbose output:\n"
                + "\n".join(differences[:10])
            )

    except subprocess.TimeoutExpired:
        # Skip tests that timeout (very rare edge cases)
        pass
    except Exception as e:
        # Log unexpected errors but don't fail the test
        logger.warning(f"Date {year}-{month}-{day}: Exception during test: {e}")


@pytest.mark.slow
def test_exhaustive_year_parity():
    """Exhaustive test: Verify parity for every day in the year 2023."""

    project_root = Path(__file__).parent.parent.parent.parent
    perl_script = project_root / "perl-panchanga-implementation" / "src" / "pancanga.pl"

    logger.info("=" * 80)
    logger.info("EXHAUSTIVE PARITY TEST - Testing all days in 2023")
    logger.info("=" * 80)

    year = 2023
    failed_dates = []
    total_tested = 0

    # Test every day in 2023
    for month in range(1, 13):
        # Determine days in month
        if month in [1, 3, 5, 7, 8, 10, 12]:
            days_in_month = 31
        elif month in [4, 6, 9, 11]:
            days_in_month = 30
        else:  # February
            days_in_month = 28  # 2023 is not a leap year

        for day in range(1, days_in_month + 1):
            total_tested += 1

            # Python list command
            python_list_cmd = [
                sys.executable,
                "-m",
                "panchanga_cli.cli",
                "--json",
                "--place",
                "kathmandu",
                "list",
                f"{year} {month} {day}",
            ]

            # Perl list command
            perl_list_cmd = [
                "perl",
                str(perl_script),
                "--place",
                "kathmandu",
                "list",
                str(year),
                str(month),
                str(day),
                "--json",
            ]

            try:
                # Execute both commands
                python_result = subprocess.run(
                    python_list_cmd, capture_output=True, text=True, timeout=10
                )
                perl_result = subprocess.run(
                    perl_list_cmd,
                    cwd=project_root / "perl-panchanga-implementation" / "src",
                    capture_output=True,
                    text=True,
                    timeout=10,
                )

                # Compare results
                if python_result.returncode == 0 and perl_result.returncode == 0:
                    python_data = parse_json_lines(python_result.stdout)
                    perl_data = parse_json_lines(perl_result.stdout)

                    if python_data and perl_data and len(python_data) > 0 and len(perl_data) > 0:
                        match, differences = smart_json_compare(python_data[0], perl_data[0])
                        if not match:
                            failed_dates.append(
                                {
                                    "date": f"{year}-{month:02d}-{day:02d}",
                                    "differences": differences,
                                }
                            )
                            logger.warning(
                                f"❌ {year}-{month:02d}-{day:02d}: {len(differences)} differences"
                            )

            except subprocess.TimeoutExpired:
                logger.warning(f"⚠️ {year}-{month:02d}-{day:02d}: Timeout")
            except Exception as e:
                logger.warning(f"⚠️ {year}-{month}-{day}: {e}")

    # Report results
    logger.info("")
    logger.info("=" * 80)
    logger.info("EXHAUSTIVE TEST COMPLETE")
    logger.info(f"Total dates tested: {total_tested}")
    logger.info(f"Passed: {total_tested - len(failed_dates)}")
    logger.info(f"Failed: {len(failed_dates)}")

    if failed_dates:
        logger.error("\n❌ Failed dates (showing first 10):")
        for failure in failed_dates[:10]:
            logger.error(f"  {failure['date']}: {len(failure['differences'])} differences")
            for diff in failure["differences"][:3]:
                logger.error(f"    - {diff}")

        if len(failed_dates) > 10:
            logger.error(f"  ... and {len(failed_dates) - 10} more failed dates")
    else:
        logger.info("\n✅ All dates passed!")

    logger.info("=" * 80)

    # Assert that all dates passed
    assert len(failed_dates) == 0, (
        f"Exhaustive parity test failed for {len(failed_dates)}/{total_tested} dates"
    )
