import dataset

from snek.system.service import BaseService


class DBService(BaseService):

    async def get_db(self, user_uid):

        home_folder = await self.app.services.user.get_home_folder(user_uid)
        home_folder.mkdir(parents=True, exist_ok=True)
        db_path = home_folder.joinpath("snek/user.db")
        db_path.parent.mkdir(parents=True, exist_ok=True)
        return dataset.connect("sqlite:///" + str(db_path))

    async def insert(self, user_uid, table_name, values):
        db = await self.get_db(user_uid)
        return db[table_name].insert(values)

    async def update(self, user_uid, table_name, values, filters):
        db = await self.get_db(user_uid)
        if not filters:
            filters = {}
        if not values:
            return False
        return db[table_name].update(values, filters)

    async def upsert(self, user_uid, table_name, values, keys):
        db = await self.get_db(user_uid)
        return db[table_name].upsert(values, keys)

    async def find(self, user_uid, table_name, kwargs):
        db = await self.get_db(user_uid)
        kwargs["_limit"] = kwargs.get("_limit", 30)
        return [dict(row) for row in db[table_name].find(**kwargs)]

    async def get(self, user_uid, table_name, filters):
        db = await self.get_db(user_uid)
        if not filters:
            filters = {}
        try:
            return dict(db[table_name].find_one(**filters))
        except ValueError:
            return None

    async def delete(self, user_uid, table_name, filters):
        db = await self.get_db(user_uid)
        if not filters:
            filters = {}
        return db[table_name].delete(**filters)

    async def query(self, sql, values):
        db = await self.app.db
        return [dict(row) for row in db.query(sql, values or {})]

    async def exists(self, user_uid, table_name, filters):
        db = await self.get_db(user_uid)
        if not filters:
            filters = {}
        return bool(db[table_name].find_one(**filters))

    async def count(self, user_uid, table_name, filters):
        db = await self.get_db(user_uid)
        if not filters:
            filters = {}
        return db[table_name].count(**filters)
