"""Executable permission contract for the v1.1 parallel deployment."""

from __future__ import annotations

import hashlib
import json
from dataclasses import dataclass
from pathlib import Path

from first_customer_invite_contract import (
    CANDIDATE,
    HERMES_WHEEL,
    HERMES_WHEEL_SHA256,
    MODULE_SHA256,
    PROFILE_WHEEL,
    PROFILE_WHEEL_SHA256,
    ControllerError,
    json_object,
    require_private_file,
    require_service_stopped,
    sha256_file,
)


@dataclass(frozen=True, slots=True)
class DeploymentPermission:
    profile: Path
    service: str
    installer_python: Path
    wheelhouse: Path
    wheelhouse_count: int
    wheelhouse_inventory_sha256: str
    target_runtime: Path
    unit_path: Path
    baseline_unit_sha256: str
    expected_unit_path: Path
    expected_unit_sha256: str
    snapshot_root: Path
    preflight_receipt_path: Path
    install_receipt_path: Path
    provider_receipt_path: Path
    start_receipt_path: Path
    allowed_modes: frozenset[str]


def _wheelhouse_digest(root: Path) -> tuple[int, str]:
    wheels = sorted(root.glob("*.whl"))
    rows = [
        {"name": path.name, "sha256": sha256_file(path), "size": path.stat().st_size}
        for path in wheels
    ]
    raw = json.dumps(rows, sort_keys=True, separators=(",", ":")).encode()
    return len(wheels), hashlib.sha256(raw).hexdigest()


def _load(path: Path) -> tuple[DeploymentPermission, dict[str, object]]:
    require_private_file(path)
    value = json_object(path)
    modes = value.get("allowed_modes")
    count = value.get("wheelhouse_count")
    if (
        not isinstance(modes, list)
        or any(not isinstance(item, str) for item in modes)
        or type(count) is not int
    ):
        raise ControllerError("deployment permission is malformed")
    try:
        permission = DeploymentPermission(
            profile=Path(str(value["profile"])).resolve(),
            service=str(value["service"]),
            installer_python=Path(str(value["installer_python"])).resolve(),
            wheelhouse=Path(str(value["wheelhouse"])).resolve(),
            wheelhouse_count=count,
            wheelhouse_inventory_sha256=str(
                value["wheelhouse_inventory_sha256"]
            ),
            target_runtime=Path(str(value["target_runtime"])).resolve(),
            unit_path=Path(str(value["unit_path"])).resolve(),
            baseline_unit_sha256=str(value["baseline_unit_sha256"]),
            expected_unit_path=Path(str(value["expected_unit_path"])).resolve(),
            expected_unit_sha256=str(value["expected_unit_sha256"]),
            snapshot_root=Path(str(value["snapshot_root"])).resolve(),
            preflight_receipt_path=Path(
                str(value["preflight_receipt_path"])
            ).resolve(),
            install_receipt_path=Path(str(value["install_receipt_path"])).resolve(),
            provider_receipt_path=Path(
                str(value["provider_receipt_path"])
            ).resolve(),
            start_receipt_path=Path(str(value["start_receipt_path"])).resolve(),
            allowed_modes=frozenset(
                item for item in modes if isinstance(item, str)
            ),
        )
    except KeyError as exc:
        raise ControllerError("deployment permission is malformed") from exc
    return permission, {key: item for key, item in value.items()}


def verify_deployment_permission(
    mode: str,
    profile: Path,
    permission_path: Path,
    receipt_path: Path,
    controller_path: Path,
    operations_path: Path,
    permission_module_path: Path,
) -> DeploymentPermission:
    permission, raw = _load(permission_path)
    expected_receipt = {
        "preflight": permission.preflight_receipt_path,
        "install": permission.install_receipt_path,
        "provider-check": permission.provider_receipt_path,
        "start": permission.start_receipt_path,
    }[mode]
    code_hashes = (
        raw.get("controller_sha256") == sha256_file(controller_path)
        and raw.get("operations_sha256") == sha256_file(operations_path)
        and raw.get("permission_module_sha256")
        == sha256_file(permission_module_path)
    )
    approval_path = Path(str(raw.get("approval_event_path"))).resolve()
    authorization_path = Path(str(raw.get("launch_authorization_path"))).resolve()
    authorization = json_object(authorization_path)
    artifact_binding = (
        raw.get("schema")
        == "dualcoach-first-customer-deployment-permission-v1"
        and raw.get("candidate_digest") == CANDIDATE
        and raw.get("hermes_wheel_sha256") == HERMES_WHEEL_SHA256
        and raw.get("profile_wheel_sha256") == PROFILE_WHEEL_SHA256
        and raw.get("installer_python_sha256")
        == sha256_file(permission.installer_python)
        and raw.get("approval_event_sha256") == sha256_file(approval_path)
        and raw.get("launch_authorization_sha256")
        == sha256_file(authorization_path)
        and authorization.get("status") == "AUTHORIZED_ONE_FIRST_CUSTOMER_LINK"
        and authorization.get("candidate_digest") == CANDIDATE
        and authorization.get("approval_event_sha256")
        == raw.get("approval_event_sha256")
        and sha256_file(HERMES_WHEEL) == HERMES_WHEEL_SHA256
        and sha256_file(PROFILE_WHEEL) == PROFILE_WHEEL_SHA256
    )
    count, digest = _wheelhouse_digest(permission.wheelhouse)
    if not (
        code_hashes
        and artifact_binding
        and permission.profile == profile.resolve()
        and permission.installer_python.is_file()
        and permission.expected_unit_sha256
        == sha256_file(permission.expected_unit_path)
        and count == permission.wheelhouse_count
        and digest == permission.wheelhouse_inventory_sha256
        and mode in permission.allowed_modes
        and receipt_path.resolve() == expected_receipt
        and not receipt_path.exists()
    ):
        raise ControllerError("deployment permission binding mismatch")
    if mode in {"preflight", "install"}:
        require_service_stopped(permission.service)
        if (
            sha256_file(permission.unit_path) != permission.baseline_unit_sha256
            or permission.target_runtime.exists()
            or permission.snapshot_root.exists()
        ):
            raise ControllerError("deployment stopped-boundary mismatch")
    if mode == "install":
        preflight = json_object(permission.preflight_receipt_path)
        if (
            preflight.get("schema")
            != "dualcoach-first-customer-deployment-preflight-v1"
            or preflight.get("status") != "PASS_READY"
            or preflight.get("candidate_digest") != CANDIDATE
            or preflight.get("profile") != str(permission.profile)
            or preflight.get("baseline_unit_sha256")
            != permission.baseline_unit_sha256
        ):
            raise ControllerError("deployment preflight authority is unavailable")
    if mode in {"provider-check", "start"}:
        if (
            sha256_file(permission.unit_path) != permission.expected_unit_sha256
            or not (permission.target_runtime / "venv/bin/python").is_file()
            or not permission.install_receipt_path.is_file()
        ):
            raise ControllerError("installed deployment authority is unavailable")
        installed = json_object(permission.install_receipt_path)
        installed_count = installed.get("installed_regular_file_count")
        if (
            installed.get("schema")
            != "dualcoach-first-customer-install-receipt-v1"
            or installed.get("status") != "PASS_INSTALLED"
            or installed.get("candidate_digest") != CANDIDATE
            or installed.get("bootstrap_module_sha256") != MODULE_SHA256
            or installed.get("invite_ttl_seconds") != 86_400
            or installed.get("venv_mode") != "0700"
            or installed.get("link_mode") != "copy"
            or installed.get("installer") != "pip"
            or type(installed_count) is not int
            or installed_count <= 0
            or installed.get("unit_sha256")
            != sha256_file(permission.unit_path)
        ):
            raise ControllerError("installed receipt authority is invalid")
    if mode == "start":
        provider = json_object(permission.provider_receipt_path)
        if (
            provider.get("schema")
            != "dualcoach-first-customer-provider-receipt-v1"
            or provider.get("status") != "PASS_PROVIDER_READY"
            or provider.get("candidate_digest") != CANDIDATE
            or provider.get("install_receipt_sha256")
            != sha256_file(permission.install_receipt_path)
            or provider.get("unit_sha256") != sha256_file(permission.unit_path)
        ):
            raise ControllerError("provider readiness authority is unavailable")
    return permission
