"""One persistent policy process; no scheduler or agent loop."""
from __future__ import annotations

import importlib
import inspect
import sys
from pathlib import Path

# Load the SDK before adding editable behavior to the import path.
from klbr.hooks import (AttentionDecision, AttentionRequest, DeliveryDecision,
                        DeliveryRequest, HookContext)
from .release import fingerprint, manifest


class Policy:
    def __init__(self, root: Path, revision: str):
        if fingerprint(root) != revision:
            raise ValueError("behavior content does not match its revision fingerprint")
        registrations = manifest(root)
        sys.path.insert(0, str(root.resolve()))
        self.revision = revision
        self.handlers = {}
        for slot, entrypoint in registrations.items():
            module, name = entrypoint.split(":")
            handler = getattr(importlib.import_module(module), name)
            if not callable(handler):
                raise ValueError(f"not a callable: {entrypoint}")
            # Enforce the two-argument use site without evaluating the callback.
            inspect.signature(handler).bind(object(), object())
            self.handlers[slot] = handler

    async def invoke(self, slot: str, value: dict, context: HookContext) -> dict:
        match slot:
            case "delivery.review":
                request, expected = DeliveryRequest.parse(value), DeliveryDecision
            case "attention.plan":
                request, expected = AttentionRequest.parse(value), AttentionDecision
            case _:
                raise ValueError(f"unsupported hook slot: {slot}")
        result = self.handlers[slot](request, context)
        if inspect.isawaitable(result):
            result = await result
        if not isinstance(result, expected):
            raise TypeError(f"{slot} must return {expected.__name__}, not {type(result).__name__}")
        return result.to_wire()
