"""Independent r71b package replay verification."""

from __future__ import annotations

import hashlib
from datetime import date, datetime
from pathlib import Path
from types import SimpleNamespace

import pytest
from pydantic import JsonValue

from gateway.platforms.nutrition_weekly_maintenance_contract import canonical_document
from scripts.nutricoach_v150_r71b_preparation import (
    HistoricalSendingRow,
    MaintenanceWindow,
    NoSendFacts,
    SanitizedTopic59Preflight,
    prepare_r71b_maintenance,
)
from scripts import nutricoach_v150_r71b_preseal_verifier as verifier
from scripts.nutricoach_v150_r71b_preseal_verifier import (
    R71bPresealVerificationError,
    verify_r71b_preseal,
)


def test_verifier_rejects_a_stored_binding_that_differs_from_reconstruction(
    tmp_path: Path,
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    # Given
    window = MaintenanceWindow(
        date(2026, 9, 1),
        datetime.fromisoformat("2026-09-01T16:00:00+09:00"),
        datetime.fromisoformat("2026-09-01T16:10:00+09:00"),
    )
    preflight = SanitizedTopic59Preflight(
        candidate_digest="1" * 64,
        successor_config_digest="2" * 64,
        route_digest="3" * 64,
        customer_identity_digest="4" * 64,
        card_slot="5" * 64,
        publication_ledger_sha256="6" * 64,
        historical_sending_rows=(
            HistoricalSendingRow("7" * 64, "8" * 64),
            HistoricalSendingRow("9" * 64, "a" * 64),
        ),
    )
    facts = NoSendFacts(0, 0, 0, 0, 1)
    seed: dict[str, JsonValue] = {
        "schema": "nutricoach-v150-r71b-package-binding-inputs-v1",
        "product_generation": "r71",
        "package_namespace": "r71b-maintenance",
        "authority_id": "nutricoach-v150-v15-runtime-authority-r71b-maintenance",
        "paths": {"preseal_root": str(tmp_path)},
        "candidate": {"candidate_digest": "1" * 64},
        "wheels": [],
        "controller": {"files": {}},
        "protected_inventory": {"explicit_maintenance_volatile_paths": []},
        "dependency_snapshot": {"dependency_snapshot_sha256": "b" * 64},
        "authority_baseline": {"candidate_digest": "c" * 64},
        "target_binding_base": {"profile_root": str(tmp_path / "profile")},
        "service_preparation": {"ActiveState": "active"},
        "diagnosed_blocker_evidence": [],
    }
    prepared = prepare_r71b_maintenance(preflight, window, facts, seed)
    authority = tmp_path / "maintenance-authority/nutricoach-topic59-maintenance-r71b.json"
    authority.parent.mkdir()
    _ = authority.write_bytes(prepared.artifacts.authority_bytes)
    scope_path = tmp_path / "maintenance/maintenance-scope.json"
    scope_path.parent.mkdir()
    _ = scope_path.write_bytes(canonical_document(prepared.scope))
    binding_path = tmp_path / "maintenance/package-binding-inputs.json"
    _ = binding_path.write_bytes(prepared.artifacts.binding_inputs_bytes)
    package = tmp_path / "package.json"
    _ = package.write_bytes(prepared.artifacts.permission_package_bytes)
    target = tmp_path / "sealed-target.json"
    _ = target.write_text(
        "{" + ",".join((
            '"schema":"nutricoach-v150-sealed-live-target-r71b"',
            f'"permission_package":"{package}"',
            f'"package_digest":"{prepared.artifacts.final_package_digest}"',
            f'"approval_phrase":"{prepared.artifacts.permission_package["approval_phrase"]}"',
            f'"package_binding_digest":"{prepared.artifacts.package_binding_digest}"',
            f'"maintenance_authority_path":"{authority}"',
            f'"maintenance_authority_sha256":"{prepared.artifacts.authority_sha256}"',
            f'"maintenance_hold_id":"{prepared.artifacts.hold.hold_id}"',
            f'"maintenance_hold_sha256":"{prepared.artifacts.hold_sha256}"',
            f'"maintenance_scope_path":"{scope_path}"',
            f'"maintenance_scope_sha256":"{hashlib.sha256(scope_path.read_bytes()).hexdigest()}"',
        )) + "}\n",
        encoding="utf-8",
    )
    reconstructed = SimpleNamespace(
        preflight=preflight,
        window=window,
        facts=facts,
        binding_seed=seed,
    )
    def reconstruct(
        _path: Path,
        _target: dict[str, JsonValue],
    ) -> SimpleNamespace:
        return reconstructed

    monkeypatch.setattr(verifier, "_reconstruct_binding_inputs", reconstruct)

    # Then
    result = verify_r71b_preseal(target)
    assert result["package_digest"] == prepared.artifacts.final_package_digest

    # A self-consistent replacement of only the stored binding is not an input.
    _ = binding_path.write_bytes(prepared.artifacts.binding_inputs_bytes.replace(b'"r71"', b'"r72"'))
    with pytest.raises(R71bPresealVerificationError, match="reconstruction"):
        _ = verify_r71b_preseal(target)
