"""Fixture-driven tests for miscellaneous node rules."""

import pytest

from fixtures import workflows_dir
from valn8n_lib.rules import get_rules
from valn8n_lib.types import SuggestionLevel
from valn8n_lib.validator import validate_workflow

FIXTURE_DIR = workflows_dir() / "test_other"


def _discover_cases() -> list[str]:
    """Discover test cases from .lst companion files."""
    return sorted(p.stem for p in FIXTURE_DIR.glob("*.lst"))


@pytest.mark.parametrize("case", _discover_cases())
def test_other_rule(case: str) -> None:
    lst_path = FIXTURE_DIR / f"{case}.lst"
    json_path = FIXTURE_DIR / f"{case}.json"
    assert json_path.exists(), f"Missing fixture: {json_path}"

    expected = sorted(line.strip() for line in lst_path.read_text().splitlines() if line.strip())

    diagnostics = validate_workflow(json_path, rules=get_rules())
    actual = sorted(d.code.code for d in diagnostics)

    assert actual == expected, f"{case}: expected {expected}, got {actual}"


class TestND0201Suggestions:
    """Test that ND0201 includes valid keys in message."""

    def test_message_contains_valid_keys(self) -> None:
        json_path = FIXTURE_DIR / "invalid_key.json"
        diagnostics = validate_workflow(json_path, rules=get_rules(select={"ND0201"}))
        assert diagnostics, "Expected at least one ND0201 diagnostic"
        msg = diagnostics[0].message
        assert "valid values:" in msg

    def test_suggestions_none_hides_keys(self) -> None:
        json_path = FIXTURE_DIR / "invalid_key.json"
        diagnostics = validate_workflow(
            json_path,
            rules=get_rules(select={"ND0201"}),
            suggestions=SuggestionLevel.NONE,
        )
        assert diagnostics
        msg = diagnostics[0].message
        assert "valid values:" not in msg

    def test_suggestions_short_truncates(self) -> None:
        json_path = FIXTURE_DIR / "invalid_key.json"
        diagnostics = validate_workflow(
            json_path,
            rules=get_rules(select={"ND0201"}),
            suggestions=SuggestionLevel.SHORT,
        )
        assert diagnostics
        msg = diagnostics[0].message
        assert "valid values:" in msg
        assert "total)" in msg


class TestTolerateNodeKeys:
    """Test tolerate_node_keys post-filtering in validate_workflow."""

    def test_empty_frozenset_preserves_all(self) -> None:
        json_path = FIXTURE_DIR / "invalid_key.json"
        diagnostics = validate_workflow(
            json_path,
            rules=get_rules(select={"ND0201"}),
            tolerate_node_keys=frozenset(),
        )
        assert any(d.code.code == "ND0201" for d in diagnostics)

    def test_specific_key_suppressed(self) -> None:
        json_path = FIXTURE_DIR / "invalid_key.json"
        # First, find out what key is flagged
        all_diags = validate_workflow(
            json_path,
            rules=get_rules(select={"ND0201"}),
        )
        assert all_diags, "Expected ND0201 diagnostics"
        flagged_key = all_diags[0].location.field_path  # type: ignore[union-attr]

        # Now tolerate that key
        filtered = validate_workflow(
            json_path,
            rules=get_rules(select={"ND0201"}),
            tolerate_node_keys=frozenset({flagged_key}),
        )
        assert not any(
            d.code.code == "ND0201"
            and d.location is not None
            and d.location.field_path == flagged_key
            for d in filtered
        )

    def test_wildcard_suppresses_all_nd0003(self) -> None:
        json_path = FIXTURE_DIR / "invalid_key.json"
        diagnostics = validate_workflow(
            json_path,
            rules=get_rules(select={"ND0201"}),
            tolerate_node_keys=None,
        )
        assert not any(d.code.code == "ND0201" for d in diagnostics)
