import typing as t

_ = t.Optional


class OrmMeta(t.Protocol):
    db_table: _[str]
    abstract: bool
    app_label: _[str]
    db_table_comment: _[str]
    default_order_by: _[list[str]]
    indexes: _[list[str]]
    unique_together: _[list[str]]

    def set_database(self, database) -> None: ...
    def set_model(self, model: t.Type["OrmModel"]) -> None: ...


class OrmQuerySet[Ins](t.Protocol):
    _using: str

    def __init__(self) -> None: ...
    def using(self, alias: str) -> t.Self: ...
    def filter(self, **kwargs) -> t.Self: ...
    def exclude(self, **kwargs) -> t.Self: ...
    async def all(self) -> t.List[Ins]: ...
    async def get(self, **kwargs) -> Ins: ...
    async def create(self, **kwargs) -> Ins: ...
    async def update(self, **kwargs) -> None: ...
    async def delete(self, **kwargs) -> None: ...
    async def bulk_create(self, **kwargs) -> None: ...
    async def get_or_create(self, **kwargs) -> t.Tuple[bool, Ins]: ...
    async def update_or_create(self, **kwargs) -> t.Tuple[bool, Ins]: ...


class OrmModel[Ins](t.Protocol):
    objects: OrmQuerySet
    meta: OrmMeta

    async def save(self) -> Ins: ...
    async def delete(self) -> None: ...
    async def load(self) -> Ins: ...


class OrmDataBase(t.Protocol):
    def __init__(self, *args, **kwargs) -> None: ...
    async def connect(self) -> None: ...
    async def disconnect(self) -> None: ...
    async def __aenter__(self) -> t.Self: ...
    async def __aexit__(self, *args: t.Any, **kwargs: t.Any) -> None: ...
    async def fetch_all(
        self, query: t.Any, values: t.Optional[dict] = None
    ) -> t.List[t.Any]: ...
    async def fetch_one(
        self, query: t.Any, values: t.Optional[dict] = None
    ) -> t.Optional[t.Any]: ...
    async def fetch_val(
        self, query: t.Any, values: t.Optional[dict] = None, column: t.Any = 0
    ) -> t.Any: ...
    async def execute(self, query: t.Any, values: t.Optional[dict] = None) -> t.Any: ...
    async def execute_many(self, query: t.Any, values: list) -> None: ...
    async def iterate(
        self, query: t.Any, values: t.Optional[dict] = None
    ) -> t.AsyncGenerator[t.Mapping, None]: ...
    def connection(self) -> t.Self: ...
    async def reset(self) -> None: ...
