"""
Unit tests for YAML merger functionality.
"""

from persuade.yaml_merger import (
    YAMLMergeResult,
    compute_yaml_diff,
    extract_managed_blocks,
    is_section_managed,
    merge_yaml_content,
)


class TestIsSectionManaged:
    """Tests for is_section_managed function."""

    def test_managed_marker_on_line_before(self) -> None:
        """Detect marker on line before section."""
        content = """# persuade-managed
pre-commit:
  commands:
    test: run tests
"""
        assert is_section_managed(content, "pre-commit") is True

    def test_managed_marker_on_same_line(self) -> None:
        """Detect marker on same line as section."""
        content = """pre-commit:  # persuade-managed
  commands:
    test: run tests
"""
        assert is_section_managed(content, "pre-commit") is True

    def test_no_managed_marker(self) -> None:
        """Section without marker should not be managed."""
        content = """pre-commit:
  commands:
    test: run tests
"""
        assert is_section_managed(content, "pre-commit") is False


class TestExtractManagedBlocks:
    """Tests for extract_managed_blocks function."""

    def test_extract_single_block(self) -> None:
        """Extract a single managed block."""
        content = """# persuade-managed-start: quality
pre-commit:
  commands:
    lint: ruff check
# persuade-managed-end: quality
"""
        blocks = extract_managed_blocks(content)

        assert "quality" in blocks
        assert "ruff check" in blocks["quality"]

    def test_no_blocks(self) -> None:
        """Content without blocks returns empty dict."""
        content = """pre-commit:
  commands:
    lint: ruff check
"""
        blocks = extract_managed_blocks(content)

        assert blocks == {}


class TestMergeYamlContent:
    """Tests for merge_yaml_content function."""

    def test_merge_preserves_target_sections(self) -> None:
        """Sections in target but not source should be preserved."""
        source = """name: template
jobs:
  test:
    runs-on: ubuntu-latest
"""
        target = """name: project
jobs:
  test:
    runs-on: ubuntu-latest
custom:
  setting: value
"""
        result = merge_yaml_content(source, target)

        assert "custom" in result.merged_content
        assert "custom" in result.sections_preserved

    def test_merge_adds_new_sections(self) -> None:
        """Sections in source but not target should be added."""
        source = """name: template
jobs:
  test:
    runs-on: ubuntu-latest
new_section:
  value: new
"""
        target = """name: project
jobs:
  test:
    runs-on: ubuntu-latest
"""
        result = merge_yaml_content(source, target)

        assert "new_section" in result.merged_content
        assert "new_section" in result.sections_added

    def test_merge_updates_managed_sections(self) -> None:
        """Managed sections should be updated from source."""
        source = """# persuade-managed
jobs:
  test:
    runs-on: ubuntu-22.04
"""
        target = """# persuade-managed
jobs:
  test:
    runs-on: ubuntu-20.04
"""
        result = merge_yaml_content(source, target)

        assert "ubuntu-22.04" in result.merged_content
        assert "jobs" in result.sections_updated


class TestComputeYamlDiff:
    """Tests for compute_yaml_diff function."""

    def test_diff_identifies_updates(self) -> None:
        """Diff should identify sections that would be updated."""
        source = """# persuade-managed
jobs:
  test:
    runs-on: ubuntu-22.04
"""
        target = """# persuade-managed
jobs:
  test:
    runs-on: ubuntu-20.04
"""
        diff = compute_yaml_diff(source, target)

        assert "jobs" in diff["sections_to_update"]

    def test_diff_identifies_additions(self) -> None:
        """Diff should identify sections that would be added."""
        source = """name: template
new_section:
  value: new
"""
        target = """name: project
"""
        diff = compute_yaml_diff(source, target)

        assert "new_section" in diff["sections_to_add"]


class TestYAMLMergeResult:
    """Tests for YAMLMergeResult dataclass."""

    def test_result_structure(self) -> None:
        """Result should have correct structure."""
        result = YAMLMergeResult(
            merged_content="content",
            sections_updated=["a"],
            sections_preserved=["b"],
            sections_added=["c"],
        )

        assert result.merged_content == "content"
        assert result.sections_updated == ["a"]
        assert result.sections_preserved == ["b"]
        assert result.sections_added == ["c"]
