"""
Tests for the Content Handle CLM examples.

These tests verify that the CLM logic correctly exercises
the Content Handle system features.
"""

from pathlib import Path

import pytest
import yaml

from chapters.chapter_02_handle.handle_logic import (
    register_handle,
    run_registration_examples,
    run_validation_examples,
    run_versioning_examples,
    update_handle,
    validate_handle_clm,
)


class TestHandleRegistrationCLM:
    """Tests for the handle registration CLM."""

    def test_register_simple_handle(self):
        """Register a simple handle and verify resolution."""
        result = register_handle({"handle": "my_first_doc", "content": "Hello, World!"})

        assert result["success"] is True
        assert result["hash"] is not None
        assert result["resolved_content"] == "Hello, World!"
        assert result["matches"] is True

    def test_register_handle_with_numbers(self):
        """Register a handle containing numbers."""
        result = register_handle(
            {"handle": "project_v2", "content": "Version 2 Content"}
        )

        assert result["success"] is True
        assert result["matches"] is True

    def test_register_max_length_handle(self):
        """Register a handle at max length (255 chars)."""
        max_handle = "a" + "b" * 254  # 255 chars
        result = register_handle({"handle": max_handle, "content": "Max length test"})

        assert result["success"] is True


class TestHandleVersioningCLM:
    """Tests for the handle versioning CLM."""

    def test_single_update(self):
        """Update a handle once and verify history."""
        result = update_handle(
            {
                "handle": "my_doc",
                "versions": [{"content": "Version 1"}, {"content": "Version 2"}],
            }
        )

        assert result["success"] is True
        assert result["history_length"] == 1
        assert result["final_content"] == "Version 2"

    def test_multiple_updates(self):
        """Update a handle multiple times and verify history."""
        result = update_handle(
            {
                "handle": "evolving_doc",
                "versions": [
                    {"content": "Draft"},
                    {"content": "Review"},
                    {"content": "Final"},
                ],
            }
        )

        assert result["success"] is True
        assert result["history_length"] == 2
        assert result["final_content"] == "Final"

    def test_content_lineage(self):
        """Verify a multi-version document lineage."""
        result = update_handle(
            {
                "handle": "specification",
                "versions": [
                    {"content": "# Spec v0.1\n\nInitial draft"},
                    {"content": "# Spec v0.2\n\nAdded requirements"},
                    {"content": "# Spec v0.3\n\nAdded implementation notes"},
                    {"content": "# Spec v1.0\n\nApproved for release"},
                ],
            }
        )

        assert result["success"] is True
        assert result["history_length"] == 3
        assert "# Spec v1.0" in result["final_content"]


class TestHandleValidationCLM:
    """Tests for the handle validation CLM."""

    @pytest.mark.parametrize(
        "handle,expected_valid,expected_normalized",
        [
            ("my_document", True, "my_document"),
            ("project_v2", True, "project_v2"),
            ("a", True, "a"),
            ("MyDocument", True, "mydocument"),  # Case normalized
            ("PROJECT_V2", True, "project_v2"),  # Case normalized
            ("my-document", True, "my-document"),  # Hyphens now allowed
        ],
    )
    def test_valid_handles(self, handle, expected_valid, expected_normalized):
        """Test that valid handles pass validation."""
        result = validate_handle_clm({"handle": handle})

        assert result["valid"] is expected_valid
        assert result["normalized"] == expected_normalized

    @pytest.mark.parametrize(
        "handle,expected_error_fragment",
        [
            ("1document", "start with a letter"),
            ("doc?query", "Invalid character"),
            ("", "empty"),
        ],
    )
    def test_invalid_handles(self, handle, expected_error_fragment):
        """Test that invalid handles are rejected."""
        result = validate_handle_clm({"handle": handle})

        assert result["valid"] is False
        assert expected_error_fragment.lower() in result["error"].lower()

    @pytest.mark.parametrize(
        "handle,expected_normalized",
        [
            ("my.document", "my.document"),
            ("my document", "my document"),
            ("path/to/doc", "path/to/doc"),
        ],
    )
    def test_valid_handles_with_special_chars(self, handle, expected_normalized):
        """Test that handles with periods, spaces, slashes are now valid."""
        result = validate_handle_clm({"handle": handle})

        assert result["valid"] is True
        assert result["normalized"] == expected_normalized

    def test_too_long_handle(self):
        """Test that handles over 255 chars are rejected."""
        too_long = "a" + "b" * 255  # 256 chars
        result = validate_handle_clm({"handle": too_long})

        assert result["valid"] is False


class TestCLMYAMLIntegration:
    """Tests that load and verify the YAML CLM files."""

    @pytest.fixture
    def yaml_dir(self):
        return Path(__file__).parent.parent / "chapters" / "chapter_02_handle"

    def test_registration_yaml_examples(self, yaml_dir):
        """Load and run examples from handle_registration.clm."""
        yaml_file = yaml_dir / "handle_registration.clm"
        if not yaml_file.exists():
            pytest.skip(f"YAML file not found: {yaml_file}")

        with open(yaml_file) as f:
            spec = yaml.safe_load(f)

        examples = spec.get("examples", [])
        results = run_registration_examples(examples)

        for result in results:
            assert result["success"] is True, f"Failed: {result['example_name']}"

    def test_versioning_yaml_examples(self, yaml_dir):
        """Load and run examples from handle_versioning.clm."""
        yaml_file = yaml_dir / "handle_versioning.clm"
        if not yaml_file.exists():
            pytest.skip(f"YAML file not found: {yaml_file}")

        with open(yaml_file) as f:
            spec = yaml.safe_load(f)

        examples = spec.get("examples", [])
        results = run_versioning_examples(examples)

        for result in results:
            assert result["passed"] is True, (
                f"Failed: {result['example_name']} - "
                f"Expected history_length={result['expected_history_length']}, "
                f"got {result.get('history_length', 'N/A')}"
            )

    def test_validation_yaml_examples(self, yaml_dir):
        """Load and run examples from handle_validation.clm."""
        yaml_file = yaml_dir / "handle_validation.clm"
        if not yaml_file.exists():
            pytest.skip(f"YAML file not found: {yaml_file}")

        with open(yaml_file) as f:
            spec = yaml.safe_load(f)

        examples = spec.get("examples", [])
        results = run_validation_examples(examples)

        for result in results:
            assert result["passed"] is True, (
                f"Failed: {result['example_name']} - "
                f"Expected valid={result['expected_valid']}, "
                f"got {result.get('valid', 'N/A')}"
            )
