from sqlite3 import connect, Error

from .Logger import logger


class DBReader:

    def __init__(self, guildid: int = None):
        self._guildid = guildid
        self.list = self._read_db(self._guildid)
        self._current_index = 0

    def __str__(self) -> str:
        return str(self._guildid)

    @classmethod
    def _read_db(cls, guildid: int) -> list:
        try:
            sql_con = connect("user.db")
            cursor = sql_con.cursor()
            cursor.execute("""SELECT * FROM "(guildid)" """,
                           {'guildid': guildid})
            record = cursor.fetchall()
            return record
        except Error as _e:
            logger.info(f'Error reading DB\n{_e}')

    def __iter__(self):
        return _ListGenerationIter(self)


class _DBAttrs:
    def __init__(self,
                 userid: int,
                 username: str,
                 nick: str,
                 isbot: bool,
                 defaulttracks: None or list,
                 usertracks: None or list):
        self.userid = userid
        self.username = username
        self.nick = nick
        self.isbot = isbot
        self.defaulttracks = defaulttracks
        self.usertracks = usertracks

    def __str__(self):
        return self.username

    def __repr__(self):
        return f'<File attrs userid={self.userid} username={self.username} nick={self.nick} ' \
               f'isbot={self.isbot} defaulttracks={self.defaulttracks} usertracks={self.usertracks}>'


class _ListGenerationIter:
    def __init__(self, user_class):
        self._current_index = 0
        self._list = user_class.list

        self._size = len(self._list)

    def __iter__(self):
        return self

    def __next__(self):
        if self._current_index < self._size:
            _userid = self._list[self._current_index][0]
            _username = self._list[self._current_index][1]
            _nick = self._list[self._current_index][2]
            _isbot = bool(self._list[self._current_index][3])
            _defaulttracks = self._list[self._current_index][4]
            _usertracks = self._list[self._current_index][5]

            self._current_index += 1
            memb = _DBAttrs(_userid,
                            _username,
                            _nick,
                            _isbot,
                            _defaulttracks,
                            _usertracks)
            return memb
        raise StopIteration


async def prepare_db(guild: int):
    try:
        _connect = connect('user.db')
        cursor = _connect.cursor()
        cursor.execute(f'''CREATE TABLE IF NOT EXISTS "{guild}"
        ([userid] INTEGER PRIMARY KEY, [username] TEXT,
        [nick] TEXT, [isbot] BOOL, [defaulttracks] TEXT, [usertracks] TEXT)''')
        cursor.close()
    except Error as _error:
        logger.info(_error)


async def work_with_db(db_func: str, data_turple: tuple):
    """
    Writing to db per server userinfo
    :param db_func:
    :param data_turple:
    """
    try:
        _connect = connect('user.db')
        cursor = _connect.cursor()
        cursor.execute(db_func, data_turple)
        _connect.commit()
        cursor.close()
    except Error as _error:
        logger.critical(_error)


async def fill_bd(name: str, userid: int, isbot: bool, nick: str, guild: int):
    sqlite_insert_with_param = (f"""INSERT OR IGNORE INTO "{guild}"
                          (username, userid, nick, isbot) 
                          VALUES (?, ?, ?, ?)""")
    data_tuple: tuple[str, int, str, bool] = (name, userid, nick, isbot)
    await work_with_db(sqlite_insert_with_param, data_tuple)


async def read_db(guild: int, user: int, column: str):
    _col_dict = {'userid': 0,
                 'username': 1,
                 'nick': 2,
                 'isbot': 3,
                 'defaulttracks': 4,
                 'usertracks': 5}
    try:
        sql_con = connect("user.db")
        cursor = sql_con.cursor()
        cursor.execute(f"""SELECT * FROM "{guild}" where userid = {user}""")
        record = cursor.fetchone()
        return record[_col_dict[column]]
    except Error as _error:
        logger.critical(_error)
