"""governed_function decorator — wraps async functions as FunctionPlugins."""
from __future__ import annotations

import functools
from typing import Any, Callable, Awaitable

from .base import FunctionContext, FunctionPlugin, FunctionResult


def governed_function(
    function_id: str,
    corpus_entry_cid: str,
    capability_mask: int = 1,
    trigger_events: list[str] | None = None,
    accord_template: str = "",
    gsap_required: bool = True,
    chronicle_enabled: bool = True,
    max_duration_seconds: int = 30,
    display_name: str = "",
    description: str = "",
    version: str = "0.1.0",
    registry: Any = None,
) -> Callable:
    """Decorator that wraps an async function as a governed FunctionPlugin.

    Usage::

        @governed_function(
            function_id="my-func",
            corpus_entry_cid="sha256:abc...",
        )
        async def my_func(event, context):
            return FunctionResult(success=True, data=event)
    """

    def decorator(
        fn: Callable[[dict[str, Any], FunctionContext], Awaitable[FunctionResult]],
    ) -> FunctionPlugin:

        class WrappedFunction(FunctionPlugin):
            pass

        instance = WrappedFunction.__new__(WrappedFunction)
        instance.function_id = function_id
        instance.corpus_entry_cid = corpus_entry_cid
        instance.capability_mask = capability_mask
        instance.trigger_events = trigger_events or []
        instance.accord_template = accord_template
        instance.gsap_required = gsap_required
        instance.chronicle_enabled = chronicle_enabled
        instance.max_duration_seconds = max_duration_seconds
        instance.display_name = display_name or function_id
        instance.description = description
        instance.version = version

        async def handle(event: dict[str, Any], context: FunctionContext) -> FunctionResult:
            return await fn(event, context)

        instance.handle = handle  # type: ignore[assignment]
        instance.health_check = lambda: True  # type: ignore[assignment]

        # Auto-register if a registry is provided
        if registry is not None:
            registry.register(instance)

        # Preserve original function metadata
        functools.update_wrapper(instance, fn)
        return instance

    return decorator
