from __future__ import annotations

import ast
import json
import pathlib
import tempfile
from dataclasses import dataclass
from typing import Any

from .archive_r10r2 import canonical_hash, extraction_fingerprint, runtime_artifacts, source_tree_manifest
from .policy_audit_r10r2 import _node_hazards, validate_independent_policy
from .supervisor_r10r2 import EventJournal, load_json_lines


@dataclass(frozen=True)
class R10R2Result:
    test_id: str
    assertion: str
    observed: dict[str, Any]
    passed: bool


def _result(test_id: str, assertion: str, observed: dict[str, Any], passed: bool) -> R10R2Result:
    return R10R2Result(test_id, assertion, observed, bool(passed))


def run_r10r2_rg(test_id: str) -> R10R2Result:
    number = int(test_id.rsplit("-", 1)[-1])
    mode = (number - 1) % 10
    if mode == 0:
        value = [{"path": "source/a.py", "size": 1, "sha256": "0" * 64}]
        first, second = canonical_hash(value), canonical_hash(json.loads(json.dumps(value)))
        return _result(test_id, "canonical JSON hash is deterministic", {"first": first, "second": second}, first == second)
    if mode == 1:
        with tempfile.TemporaryDirectory() as directory:
            root = pathlib.Path(directory); (root / "b.txt").write_text("b", encoding="utf-8"); (root / "a.txt").write_text("a", encoding="utf-8")
            manifest = source_tree_manifest(root); paths = [row["path"] for row in manifest["entries"]]
        return _result(test_id, "source manifest is sorted and canonical", {"paths": paths}, paths == sorted(paths) and len(paths) == 2)
    if mode == 2:
        with tempfile.TemporaryDirectory() as directory:
            root = pathlib.Path(directory); (root / "__pycache__").mkdir(); (root / "__pycache__" / "x.pyc").write_bytes(b"x")
            (root / "stable.py").write_text("x=1\n", encoding="utf-8"); artifacts = runtime_artifacts(root); manifest = source_tree_manifest(root)
        return _result(test_id, "runtime artifacts are detected and excluded", {"artifacts": artifacts, "entries": manifest["entries"]}, len(artifacts) == 1 and len(manifest["entries"]) == 1)
    if mode == 3:
        with tempfile.TemporaryDirectory() as directory:
            root = pathlib.Path(directory); (root / ".r10r2_sealed_result.json").write_text("{}", encoding="utf-8")
            first = extraction_fingerprint(root, "pair-a")
            second = extraction_fingerprint(root, "pair-a")
            distinct = extraction_fingerprint(root, "pair-b")
        return _result(
            test_id,
            "extraction fingerprint is stable within one pair and distinct across cold roots",
            {"fingerprint": first, "distinct_fingerprint": distinct},
            first == second and first != distinct and len(first) == len(distinct) == 64,
        )
    if mode == 4:
        with tempfile.TemporaryDirectory() as directory:
            path = pathlib.Path(directory) / "events.jsonl"; journal = EventJournal(path, "run", "c" * 64)
            journal.append("SUITE_START"); journal.append("SUITE_END", passed=True); rows = load_json_lines(path)
        return _result(test_id, "append-only journal preserves ordered complete rows", {"rows": rows}, [row["sequence"] for row in rows] == [1, 2])
    if mode == 5:
        tree = ast.parse("import subprocess\ndef test_x():\n subprocess.run(['x'])\n")
        hazards = sorted(_node_hazards(tree))
        return _result(test_id, "AST audit derives process sensitivity", {"hazards": hazards}, any("subprocess" in item for item in hazards))
    if mode == 6:
        discovered = ["tests.x.Case.test_a"]
        manifest = {"tests": [{"test_id": discovered[0], "policy": "SAFE_SHARED_WORKER"}]}
        ast_audit = {"rows": [{}], "ast_sensitive_test_ids": [discovered[0]]}
        report = validate_independent_policy(discovered, manifest, ast_audit)
        return _result(test_id, "forged SAFE policy is rejected", report, report["passed"] is False and bool(report["sensitive_safe_shared_intersection"]))
    if mode == 7:
        discovered = ["tests.x.Case.test_a", "tests.x.Case.test_b"]
        manifest = {"tests": [{"test_id": item, "policy": "ISOLATED_TEST_PROCESS"} for item in discovered]}
        report = validate_independent_policy(discovered, manifest, {"rows": [{}, {}], "ast_sensitive_test_ids": discovered})
        return _result(test_id, "exact policy coverage passes", report, report["passed"] is True and report["unclassified_count"] == 0)
    if mode == 8:
        discovered = ["tests.x.Case.test_a"]
        manifest = {"tests": [{"test_id": discovered[0], "policy": "ISOLATED_TEST_PROCESS"}, {"test_id": "ghost", "policy": "ISOLATED_TEST_PROCESS"}]}
        report = validate_independent_policy(discovered, manifest, {"rows": [{}], "ast_sensitive_test_ids": discovered})
        return _result(test_id, "ghost manifest entries are rejected", report, report["passed"] is False and report["ghost_count"] == 1)
    entries = [{"path": "source/x", "size": 3, "sha256": canonical_hash("abc")}]
    tree_hash = canonical_hash(entries)
    payload = {"entries": entries, "tree_sha256": tree_hash}
    return _result(test_id, "source tree hash is derived from entries", payload, payload["tree_sha256"] == canonical_hash(payload["entries"]))
