from snek.mapper import get_mapper
from snek.model.user import UserModel
from snek.system.mapper import BaseMapper


class BaseService:

    mapper_name: BaseMapper = None

    @property
    def services(self):
        return self.app.services

    def __init__(self, app):
        self.app = app
        self.cache = app.cache
        if self.mapper_name:
            self.mapper = get_mapper(self.mapper_name, app=self.app)
        else:
            self.mapper = None

    async def exists(self, uid=None, **kwargs):
        if uid:
            if not kwargs and await self.cache.get(uid):
                return True
            kwargs["uid"] = uid
        return await self.count(**kwargs) > 0

    async def count(self, **kwargs):
        return await self.mapper.count(**kwargs)

    async def new(self, **kwargs):
        return await self.mapper.new()

    async def query(self, sql, *args):
        for record in self.app.db.query(sql, *args):
            yield record

    async def get(self, uid=None, **kwargs):
        if uid:
            if not kwargs:
                result = await self.cache.get(uid)
                if False and result and result.__class__ == self.mapper.model_class:
                    return result
            kwargs["uid"] = uid

        result = await self.mapper.get(**kwargs)
        if result:
            await self.cache.set(result["uid"], result)
        return result

    async def save(self, model: UserModel):
        # if model.is_valid: You Know why not
        if await self.mapper.save(model):
            await self.cache.set(model["uid"], model)
            return True
        errors = await model.errors
        raise Exception(f"Couldn't save model. Errors: f{errors}")

    async def find(self, **kwargs):
        if not "_limit" in kwargs or int(kwargs.get("_limit")) > 30:
            kwargs["_limit"] = 60
        async for model in self.mapper.find(**kwargs):
            yield model

    async def delete(self, **kwargs):
        return await self.mapper.delete(**kwargs)
