from typing import Callable, List, Any, Optional, Self, Union, TypeVar, Generic, Awaitable

from NonameOrm.DB.DB import DB
from NonameOrm.DB.Generator import SqlGenerator
from NonameOrm.Model.DataModel import InstanceList, ModelInstance, DataModel
from NonameOrm.Model.ModelProperty import BaseProperty, FilterListCell

T = TypeVar('T')

class Warp(Generic[T]):

    a = T
    def findAnyMatch(self, instance: ModelInstance, limit=None, offset=0) -> List[T]: ...

    def findAllBy(self, Filter: Union[bool, FilterListCell]) -> List[T]: ...

class BaseModelExecutor(Generic[T]):
    sql: SqlGenerator
    model: T
    db: DB
    work: Any

    def __init__(self, model: T, work=None): ...

    def instanceToFilter(self, instance: ModelInstance): ...

    def reset(self) -> Self: ...

    def is_exists(self, query) -> Union[Awaitable[bool], bool]: ...

    @property
    def generator(self) -> SqlGenerator: ...

    def findAnyMatch(self, instance: ModelInstance, limit=None, offset=0) -> List[T]: ...

    def find(self, *cols: List[BaseProperty]): ...

    def save(self, instance: ModelInstance): ...

    def delete(self, instance: Optional[ModelInstance] = None, filter: Optional[Union[bool, FilterListCell]] = None): ...

    def update(self, instance: ModelInstance): ...

    def findOneBy(self, Filter: Union[bool, FilterListCell]) -> T: ...

    def findAllBy(self, Filter: Union[bool, FilterListCell]) -> List[T]: ...

    def editSql(self, callback: Callable[[SqlGenerator], None]) -> Self: ...

    def execute(self): ...

    def process(self, res): ...



class ModelExecutor(BaseModelExecutor, Generic[T]):

    def __init__(self, model: T, work=None):
        super().__init__(model, work)


class AsyncModelExecutor(BaseModelExecutor, Generic[T]):

    def __init__(self, model: T, work=None):
        super().__init__(model, work)

    async def findAnyMatch(self, instance: ModelInstance, limit=None, offset=0) -> List[T]: ...

    async def findAllBy(self, Filter: Union[bool, FilterListCell] = None) -> List[T]: ...

    def find(self, *cols: List[BaseProperty]) -> AsyncModelExecutor: ...

    async def By(self, Fileter: FilterListCell) -> ModelInstance: ...

    async def save(self, instance: ModelInstance) -> T: ...

    async def findOneBy(self, Filter: Union[bool, FilterListCell]) -> T: ...

    async def update(self, instance: ModelInstance): ...

    async def execute(self) -> ModelInstance: ...

    async def findForeignKey(self, instance, deep: Optional[bool] = False): ...

    async def findListForeignKey(self, instances: InstanceList, deep: Optional[bool] = False): ...
