"""
Tests for Hash Verification: Proving Content-Hash Duality.

Uses known hash values to verify that the Content Handle system
correctly maintains cryptographic integrity of content.
"""

from pathlib import Path

import pytest
import yaml

from chapters.chapter_02_handle.hash_verification import (
    HashVerificationRegistry,
    compute_sha256,
    verify_all,
    verify_single,
)

# Known hashes from the CLM specification
KNOWN_HASHES = {
    "single_update": "84bb7bfbbf91801eb7353ee17d40a22b1e1b116b2d129fab863835e25504481c",
    "multiple_updates": "b741e20e045e904a474c85366c675d29d463a6895ee7d0a2ef32e8891c694f80",
    "content_lineage": "e019311898778ae05d51bbb1d445e35070a9de9375a75f7f9b092d76e8d75ba3",
}


class TestHashComputation:
    """Tests for SHA-256 hash computation."""

    def test_compute_sha256_deterministic(self):
        """Same content should always produce same hash."""
        content = b"Hello, World!"
        hash1 = compute_sha256(content)
        hash2 = compute_sha256(content)
        assert hash1 == hash2

    def test_compute_sha256_different_content(self):
        """Different content should produce different hashes."""
        hash1 = compute_sha256(b"Version A")
        hash2 = compute_sha256(b"Version B")
        assert hash1 != hash2


class TestKnownHashes:
    """Tests verifying known hash values from the CLM."""

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

    def test_single_update_hash(self, test_data_dir):
        """Verify single_update.yaml has the expected hash."""
        file_path = test_data_dir / "single_update.yaml"
        with open(file_path) as f:
            content = f.read()

        computed = compute_sha256(content.encode("utf-8"))
        expected = KNOWN_HASHES["single_update"]

        assert (
            computed == expected
        ), f"Expected {expected[:16]}..., got {computed[:16]}..."

    def test_multiple_updates_hash(self, test_data_dir):
        """Verify multiple_updates.yaml has the expected hash."""
        file_path = test_data_dir / "multiple_updates.yaml"
        with open(file_path) as f:
            content = f.read()

        computed = compute_sha256(content.encode("utf-8"))
        expected = KNOWN_HASHES["multiple_updates"]

        assert (
            computed == expected
        ), f"Expected {expected[:16]}..., got {computed[:16]}..."

    def test_content_lineage_hash(self, test_data_dir):
        """Verify content_lineage.yaml has the expected hash."""
        file_path = test_data_dir / "content_lineage.yaml"
        with open(file_path) as f:
            content = f.read()

        computed = compute_sha256(content.encode("utf-8"))
        expected = KNOWN_HASHES["content_lineage"]

        assert (
            computed == expected
        ), f"Expected {expected[:16]}..., got {computed[:16]}..."


class TestHashVerificationRegistry:
    """Tests for the HashVerificationRegistry."""

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

    def test_load_and_verify_matches_expected(self, test_data_dir):
        """Loading a file should produce the expected hash."""
        registry = HashVerificationRegistry()

        result = registry.load_and_verify(
            test_data_dir / "single_update.yaml",
            "single_update",
            KNOWN_HASHES["single_update"],
        )

        assert result["hash_matches_stored"] is True
        assert result["hash_matches_expected"] is True
        assert result["stored_hash"] == KNOWN_HASHES["single_update"]

    def test_verify_retrieval_duality(self, test_data_dir):
        """Verify that hash and handle retrieval return identical content."""
        registry = HashVerificationRegistry()

        registry.load_and_verify(
            test_data_dir / "multiple_updates.yaml",
            "multiple_updates",
            KNOWN_HASHES["multiple_updates"],
        )

        result = registry.verify_retrieval_duality("multiple_updates")

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

        assertions = result["assertions"]
        assert assertions["stored_equals_resolved"] is True
        assert assertions["stored_equals_recomputed"] is True
        assert assertions["content_by_hash_equals_content_by_handle"] is True
        assert assertions["card_hashes_equal"] is True


class TestCLMVerification:
    """Tests running the CLM verification entry points."""

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

    def test_verify_all(self, test_data_dir):
        """Verify all known MCards from the CLM."""
        result = verify_all({"test_data_dir": str(test_data_dir)})

        assert result["success"] is True
        assert result["summary"]["total_mcards"] == 3
        assert result["summary"]["all_hashes_match_expected"] is True
        assert result["summary"]["all_duality_verified"] is True

        # Verify each MCard in the hash registry
        for entry in result["hash_registry"]:
            assert entry["name"] in KNOWN_HASHES
            assert entry["hash"] == KNOWN_HASHES[entry["name"]]

    def test_verify_single(self, test_data_dir):
        """Verify a single MCard with known hash."""
        result = verify_single(
            {
                "test_data_dir": str(test_data_dir),
                "name": "content_lineage",
                "expected_hash": KNOWN_HASHES["content_lineage"],
            }
        )

        assert result["success"] is True
        assert result["load"]["hash_matches_expected"] is True
        assert result["duality"]["all_verified"] is True


class TestCLMIntegration:
    """Integration tests loading the CLM spec and executing."""

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

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

    def test_clm_known_mcards(self, clm_file, test_data_dir):
        """Verify all known_mcards from the CLM spec."""
        with open(clm_file) as f:
            clm_spec = yaml.safe_load(f)

        known_mcards = clm_spec.get("known_mcards", [])

        for mcard in known_mcards:
            name = mcard["name"]
            expected_hash = mcard["expected_hash"]
            source_file = mcard["source_file"]

            # Verify the expected hash in CLM matches our known hashes
            assert (
                expected_hash == KNOWN_HASHES[name]
            ), f"CLM expected_hash for '{name}' does not match KNOWN_HASHES"

            # Verify the file exists and has correct hash
            file_path = test_data_dir.parent / source_file
            with open(file_path) as f:
                content = f.read()

            computed = compute_sha256(content.encode("utf-8"))
            assert (
                computed == expected_hash
            ), f"File content hash for '{name}' does not match expected"
