"""SQLAlchemy 请求级事务适配器与无会话 Oper 事务执行端口。"""

from collections.abc import Awaitable, Callable
from typing import Protocol, TypeVar

from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import Session


T = TypeVar("T")


class SyncTransactionRunner(Protocol):
    """为无显式 Session 的 Oper 入口提供独占同步事务。"""

    def __call__(self, operation: Callable[[Session], T]) -> T:
        """在一个独占会话中执行并提交操作。"""
        ...


class AsyncTransactionRunner(Protocol):
    """为无显式 Session 的 Oper 入口提供独占异步事务。"""

    def __call__(
        self,
        operation: Callable[[AsyncSession], Awaitable[T]],
    ) -> Awaitable[T]:
        """在一个独占异步会话中执行并提交操作。"""
        ...


_sync_transaction_runner: SyncTransactionRunner | None = None
_async_transaction_runner: AsyncTransactionRunner | None = None


def configure_transaction_runners(
    *,
    sync: SyncTransactionRunner,
    async_: AsyncTransactionRunner,
) -> None:
    """由组合根登记无会话 Oper 入口使用的显式事务执行器。"""
    global _sync_transaction_runner, _async_transaction_runner
    _sync_transaction_runner = sync
    _async_transaction_runner = async_


def run_sync_transaction(operation: Callable[[Session], T]) -> T:
    """委托组合根在独占同步事务中执行 Oper 操作。"""
    if _sync_transaction_runner is None:
        raise RuntimeError("同步事务执行器尚未配置")
    return _sync_transaction_runner(operation)


async def run_async_transaction(
    operation: Callable[[AsyncSession], Awaitable[T]],
) -> T:
    """委托组合根在独占异步事务中执行 Oper 操作。"""
    if _async_transaction_runner is None:
        raise RuntimeError("异步事务执行器尚未配置")
    return await _async_transaction_runner(operation)


class SqlAlchemyUnitOfWork:
    """把同步 Session 的提交与回滚能力适配为应用层事务端口。"""

    def __init__(self, session: Session) -> None:
        """保存由请求依赖提供的同步数据库会话。"""
        self._session = session

    def commit(self) -> None:
        """提交请求级事务。"""
        self._session.commit()

    def rollback(self) -> None:
        """回滚请求级事务。"""
        self._session.rollback()


class SqlAlchemyAsyncUnitOfWork:
    """把 AsyncSession 的提交与回滚能力适配为应用层事务端口。"""

    def __init__(self, session: AsyncSession) -> None:
        """保存由请求依赖提供的数据库会话。"""
        self._session = session

    async def commit(self) -> None:
        """提交请求级事务。"""
        await self._session.commit()

    async def rollback(self) -> None:
        """回滚请求级事务。"""
        await self._session.rollback()
