"""进程级托管资源的轻量调用门面。"""

from __future__ import annotations

import asyncio
import threading
from typing import Any, Optional, Protocol


MANAGED_RESOURCE_SYNC_KIND = "managed_resource.sync"
MANAGED_RESOURCE_ASYNC_KIND = "managed_resource.async"


class ManagedResourceRuntime(Protocol):
    """Managed Resource 门面依赖的最小 Capability Runtime 合同。"""

    @property
    def is_shutdown(self) -> bool:
        """返回 Runtime 是否已进入不可逆关闭态。"""

    def get_spec(self, capability_id: str) -> Any:
        """返回资源声明。"""

    def get_running(self, capability_id: str) -> Any:
        """只查询已发布实例。"""

    def snapshot(self, capability_id: str) -> Any:
        """返回资源状态快照。"""

    def observations(self, capability_id: Optional[str] = None) -> tuple[Any, ...]:
        """返回资源转换观测。"""

    def activate(self, capability_id: str, *, reason: str, retry: bool = False) -> Any:
        """通过同步 adapter 激活资源。"""

    async def activate_async(
        self,
        capability_id: str,
        *,
        reason: str,
        retry: bool = False,
    ) -> Any:
        """通过异步 adapter 激活资源。"""

    def stop(self, capability_id: str, *, reason: str) -> None:
        """通过同步 adapter 停止资源。"""

    async def stop_async(self, capability_id: str, *, reason: str) -> None:
        """通过异步 adapter 停止资源。"""

    async def shutdown_async(self, *, reason: str) -> None:
        """关闭混合同步和异步 adapter 的 Runtime。"""


_runtime_lock = threading.RLock()
_managed_resource_runtime: Optional[ManagedResourceRuntime] = None


def configure_managed_resource_runtime(runtime: ManagedResourceRuntime) -> None:
    """由启动组合层注入唯一的 Managed Resource Runtime。"""
    if runtime is None:
        raise ValueError("Managed Resource Runtime 不能为空")
    global _managed_resource_runtime
    with _runtime_lock:
        _managed_resource_runtime = runtime


def _runtime(*, required: bool) -> Optional[ManagedResourceRuntime]:
    """读取当前 Runtime；资源使用路径要求启动组合已经完成装配。"""
    with _runtime_lock:
        runtime = _managed_resource_runtime
    if runtime is None and required:
        raise RuntimeError("Managed Resource Runtime 尚未初始化")
    return runtime


def _resource_kind(runtime: ManagedResourceRuntime, capability_id: str) -> str:
    """返回声明的执行模式；未知资源继续沿用 Runtime 的领域错误。"""
    spec = runtime.get_spec(capability_id)
    if spec is None:
        runtime.get_running(capability_id)
        raise RuntimeError(f"未知 Managed Resource：{capability_id}")
    return str(spec.kind)


def acquire_managed_resource(
    capability_id: str,
    *,
    reason: str,
    retry: bool = True,
) -> Any:
    """同步激活一个声明为同步模式的托管资源。"""
    runtime = _runtime(required=True)
    kind = _resource_kind(runtime, capability_id)
    if kind != MANAGED_RESOURCE_SYNC_KIND:
        raise RuntimeError(f"异步 Managed Resource 不能通过同步入口激活：{capability_id}")
    return runtime.activate(capability_id, reason=reason, retry=retry)


async def acquire_managed_resource_async(
    capability_id: str,
    *,
    reason: str,
    retry: bool = True,
) -> Any:
    """异步激活资源；同步资源移交工作线程，避免阻塞事件循环。"""
    runtime = _runtime(required=True)
    kind = _resource_kind(runtime, capability_id)
    if kind == MANAGED_RESOURCE_ASYNC_KIND:
        return await runtime.activate_async(
            capability_id,
            reason=reason,
            retry=retry,
        )
    if kind == MANAGED_RESOURCE_SYNC_KIND:
        return await asyncio.to_thread(
            runtime.activate,
            capability_id,
            reason=reason,
            retry=retry,
        )
    raise RuntimeError(f"未知 Managed Resource kind：{kind}")


def get_running_managed_resource(capability_id: str) -> Any:
    """只查询已发布资源；Runtime 未配置时返回 None，不触发初始化。"""
    runtime = _runtime(required=False)
    if runtime is None:
        return None
    return runtime.get_running(capability_id)


def managed_resource_snapshot(capability_id: str) -> Any:
    """返回资源状态快照；Runtime 未配置时返回 None。"""
    runtime = _runtime(required=False)
    if runtime is None:
        return None
    return runtime.snapshot(capability_id)


def managed_resource_observations(
    capability_id: Optional[str] = None,
) -> tuple[Any, ...]:
    """返回资源转换观测；Runtime 未配置时返回空快照。"""
    runtime = _runtime(required=False)
    if runtime is None:
        return ()
    return runtime.observations(capability_id)


def stop_managed_resource(capability_id: str, *, reason: str) -> None:
    """同步停止资源；Runtime 未配置时保持幂等且不反向初始化。"""
    runtime = _runtime(required=False)
    if runtime is None:
        return
    kind = _resource_kind(runtime, capability_id)
    if kind != MANAGED_RESOURCE_SYNC_KIND:
        raise RuntimeError(f"异步 Managed Resource 不能通过同步入口停止：{capability_id}")
    runtime.stop(capability_id, reason=reason)


async def stop_managed_resource_async(capability_id: str, *, reason: str) -> None:
    """异步停止资源；同步资源移交工作线程。"""
    runtime = _runtime(required=False)
    if runtime is None:
        return
    kind = _resource_kind(runtime, capability_id)
    if kind == MANAGED_RESOURCE_ASYNC_KIND:
        await runtime.stop_async(capability_id, reason=reason)
        return
    if kind == MANAGED_RESOURCE_SYNC_KIND:
        await asyncio.to_thread(runtime.stop, capability_id, reason=reason)
        return
    raise RuntimeError(f"未知 Managed Resource kind：{kind}")


async def shutdown_managed_resource_runtime(*, reason: str) -> None:
    """关闭已配置 Runtime；未配置时直接返回，绝不因关闭而创建资源。"""
    runtime = _runtime(required=False)
    if runtime is None:
        return
    await runtime.shutdown_async(reason=reason)
