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

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: ...

    @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): ...
