"""Comparison tests: parametrized tests that compare merm vs mmdc output.

These tests auto-discover .mmd fixtures and compare rendered SVGs against
reference SVGs generated by mermaid-cli. They skip gracefully when no
merm renderer is available yet.
"""

from pathlib import Path

import pytest

from tests.comparison import (
    parse_svg_edges,
    parse_svg_nodes,
    structural_compare,
)

FIXTURES_DIR = Path(__file__).parent / "fixtures"
REFERENCE_DIR = Path(__file__).parent / "reference"

def discover_fixtures() -> list[str]:
    """Discover all .mmd fixture files and return their stem names."""
    return sorted(p.stem for p in FIXTURES_DIR.glob("*.mmd"))

def _render_with_merm(mmd_text: str) -> str:
    """Attempt to render with merm. Returns SVG text or raises."""
    from merm import render

    return render(mmd_text)

# --- Parametrized comparison tests ---

@pytest.mark.comparison
class TestFixtureComparison:
    """Compare merm output against mmdc reference for each fixture."""

    @pytest.fixture(params=discover_fixtures())
    def fixture_name(self, request):
        return request.param

    def test_reference_svg_exists(self, fixture_name):
        """Each fixture must have a corresponding reference SVG."""
        ref_path = REFERENCE_DIR / f"{fixture_name}.svg"
        assert ref_path.exists(), (
            f"Reference SVG missing for fixture '{fixture_name}'. "
            f"Run scripts/regenerate_references.sh to generate it."
        )

    def test_reference_svg_is_valid_xml(self, fixture_name):
        """Reference SVGs must be valid XML."""
        import xml.etree.ElementTree as ET

        ref_path = REFERENCE_DIR / f"{fixture_name}.svg"
        if not ref_path.exists():
            pytest.skip("Reference SVG not found")
        svg_text = ref_path.read_text()
        # Should not raise
        ET.fromstring(svg_text)

    def test_reference_has_nodes(self, fixture_name):
        """Reference SVGs should contain at least one node."""
        ref_path = REFERENCE_DIR / f"{fixture_name}.svg"
        if not ref_path.exists():
            pytest.skip("Reference SVG not found")
        svg_text = ref_path.read_text()
        nodes = parse_svg_nodes(svg_text)
        assert len(nodes) > 0, f"No nodes found in reference SVG for '{fixture_name}'"

    def test_reference_has_edges(self, fixture_name):
        """Reference SVGs should contain at least one edge."""
        ref_path = REFERENCE_DIR / f"{fixture_name}.svg"
        if not ref_path.exists():
            pytest.skip("Reference SVG not found")
        svg_text = ref_path.read_text()
        edges = parse_svg_edges(svg_text)
        assert len(edges) > 0, f"No edges found in reference SVG for '{fixture_name}'"

    def test_structural_comparison(self, fixture_name):
        """Compare merm output against reference SVG structurally.

        This test is expected to xfail until the merm renderer is
        implemented.
        """
        ref_path = REFERENCE_DIR / f"{fixture_name}.svg"
        mmd_path = FIXTURES_DIR / f"{fixture_name}.mmd"

        if not ref_path.exists():
            pytest.skip("Reference SVG not found")

        mmd_text = mmd_path.read_text()

        try:
            our_svg = _render_with_merm(mmd_text)
        except NotImplementedError:
            pytest.xfail("merm renderer not implemented yet")
        except Exception as exc:
            pytest.xfail(f"merm renderer failed: {exc}")

        reference_svg = ref_path.read_text()
        diff = structural_compare(our_svg, reference_svg)

        assert diff.identical, (
            f"Structural mismatch for '{fixture_name}': {diff.summary()}"
        )
