import typing as t
import collections.abc as c

from skoll.application.types import *
from skoll.domain import EntityState


__all__ = ["DB", "Repository"]


# class Broker(t.Protocol):

#     async def stop(self) -> None: ...
#     async def publish(self, msg: Message | RawMessage) -> None: ...
#     async def request(self, msg: Message | RawMessage) -> Result[t.Any]: ...
#     async def connect(self, *subscribers: list[Subscriber]) -> None: ...


# class Authz(t.Protocol):

#     async def check(self, tuple: str, cxt: dict[str, t.Any] | None = None) -> None: ...
#     async def write(
#         self, changes: list[AuthzWriteChange], preconditions: list[AuthzPrecondition] | None = None
#     ) -> str: ...
#     async def lookup(
#         self, filter: str, cxt: dict[str, t.Any] | None = None, limit: int | None = None, cursor: str | None = None
#     ) -> AuthzLookupResult: ...


class Repository[T: EntityState](t.Protocol):

    async def save(self, state: T) -> None: ...
    async def delete(self, criteria: Criteria) -> None: ...
    async def exist(self, criteria: Criteria) -> bool: ...
    async def get(self, criteria: Criteria) -> T | None: ...
    async def list(self, criteria: ListCriteria) -> ListPage[T]: ...


class DB[T = t.Any](t.Protocol):

    async def close(self) -> None: ...
    async def connect(self) -> None: ...
    def session(self) -> c.AsyncGenerator[T]: ...
    def transaction(self) -> c.AsyncGenerator[T]: ...
