from __future__ import annotations

import hashlib
import importlib.util
import json
from pathlib import Path
from types import ModuleType

import pytest


def _worker_module() -> ModuleType:
    path = (
        Path(__file__).parents[1]
        / "experiments"
        / "perception"
        / "worker"
        / "run_recorded_perception_epoch.py"
    )
    spec = importlib.util.spec_from_file_location("recorded_perception_worker", path)
    assert spec is not None and spec.loader is not None
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module


def _job(root: Path) -> dict[str, object]:
    payload = root / "input" / "payload.bin"
    payload.parent.mkdir(parents=True)
    payload.write_bytes(b"immutable-camera-input")
    input_document = {
        "byte_length": payload.stat().st_size,
        "files": [
            {
                "path": "input/payload.bin",
                "byte_length": payload.stat().st_size,
                "sha256": hashlib.sha256(payload.read_bytes()).hexdigest(),
            }
        ],
    }
    encoded = json.dumps(
        input_document,
        ensure_ascii=False,
        sort_keys=True,
        separators=(",", ":"),
        allow_nan=False,
    ).encode()
    input_sha256 = hashlib.sha256(encoded).hexdigest()
    document: dict[str, object] = {
        "schema_version": "missioncore.compute-job/v1",
        "job_id": f"recorded-camera-{input_sha256[:24]}",
        "input_sha256": input_sha256,
        "input": input_document,
    }
    (root / "job.json").write_text(json.dumps(document), encoding="utf-8")
    return document


def test_worker_validates_job_identity_independently_of_container_mount_name(
    tmp_path: Path,
) -> None:
    worker = _worker_module()
    mounted_root = tmp_path / "job"
    mounted_root.mkdir()
    expected = _job(mounted_root)

    validated = worker._validate_job(mounted_root)

    assert validated["job_id"] == expected["job_id"]
    assert mounted_root.name != expected["job_id"]


def test_worker_rejects_a_transferred_payload_that_changed(tmp_path: Path) -> None:
    worker = _worker_module()
    mounted_root = tmp_path / "job"
    mounted_root.mkdir()
    _job(mounted_root)
    (mounted_root / "input" / "payload.bin").write_bytes(b"changed")

    with pytest.raises(RuntimeError, match="compute job artifact changed"):
        worker._validate_job(mounted_root)
