"""Hash stability tests — verify deterministic JCS hashing across runs."""

from __future__ import annotations

import json
from pathlib import Path

from abi_control_core.sdk.canonical_hash import canonical_hash_jcs_sha256
from abi_control_core.sdk.validate import validate_json

from dpe.core_bridge._eval_suite import build_eval_suite
from dpe.core_bridge._plan_graph import build_plan_graph
from dpe.core_bridge._run_manifest_core import build_core_manifest
from dpe.models.config import DPEConfig
from dpe.models.manifest import RunManifest

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


class TestGoldenFixtureValidation:
    """Golden fixtures must pass core schema validation."""

    def test_golden_plan_graph_validates(self) -> None:
        data = json.loads((FIXTURES_DIR / "golden_plan_graph.json").read_text())
        validate_json(data, "plan_graph.schema.json")

    def test_golden_eval_suite_validates(self) -> None:
        data = json.loads((FIXTURES_DIR / "golden_eval_suite.json").read_text())
        validate_json(data, "eval_suite.schema.json")

    def test_golden_run_manifest_validates(self) -> None:
        data = json.loads(
            (FIXTURES_DIR / "golden_run_manifest_core.json").read_text()
        )
        validate_json(data, "run_manifest.schema.json")


class TestHashStability:
    """Same inputs must always produce the same JCS SHA-256 hash."""

    def test_plan_graph_hash_stable(
        self, completed_manifest: RunManifest
    ) -> None:
        pg1 = build_plan_graph(completed_manifest)
        pg2 = build_plan_graph(completed_manifest)
        assert canonical_hash_jcs_sha256(pg1) == canonical_hash_jcs_sha256(pg2)

    def test_eval_suite_hash_stable(
        self, completed_manifest: RunManifest
    ) -> None:
        es1 = build_eval_suite(completed_manifest)
        es2 = build_eval_suite(completed_manifest)
        assert canonical_hash_jcs_sha256(es1) == canonical_hash_jcs_sha256(es2)

    def test_core_manifest_hash_stable(
        self,
        completed_manifest: RunManifest,
        default_config: DPEConfig,
    ) -> None:
        cm1 = build_core_manifest(completed_manifest, default_config)
        cm2 = build_core_manifest(completed_manifest, default_config)
        assert canonical_hash_jcs_sha256(cm1) == canonical_hash_jcs_sha256(cm2)

    def test_core_manifest_hash_matches_golden(
        self,
        completed_manifest: RunManifest,
        default_config: DPEConfig,
    ) -> None:
        """The hash computed from the fixture inputs must match the golden fixture."""
        cm = build_core_manifest(completed_manifest, default_config)
        computed_hash = canonical_hash_jcs_sha256(cm)

        golden = json.loads(
            (FIXTURES_DIR / "golden_run_manifest_core.json").read_text()
        )
        golden_hash = golden["manifest_hash_jcs_sha256"].replace(
            "jcs_sha256:", ""
        )
        assert computed_hash == golden_hash

    def test_different_input_different_hash(
        self,
        completed_manifest: RunManifest,
        budget_exceeded_manifest: RunManifest,
        default_config: DPEConfig,
    ) -> None:
        cm1 = build_core_manifest(completed_manifest, default_config)
        cm2 = build_core_manifest(budget_exceeded_manifest, default_config)
        assert canonical_hash_jcs_sha256(cm1) != canonical_hash_jcs_sha256(cm2)
