from collections import namedtuple

__all__ = 'HandlerUser', 'UserAct'

UserAct = namedtuple('User', ['obj', 'msg'])


class HandlerUser:
    tb = 'user'
    user_key = '#account_id'

    def __init__(self, db_client, db_name):
        self.users = dict()
        self.db_client = db_client
        self.receive_data = []
        self.db_name = db_name

    def execute(self):
        account_ids = set(item.msg.get('#account_id') for item in self.receive_data) - set(self.users)
        if not account_ids:
            return
        self.get_users(account_ids)
        for item in self.receive_data:
            item.obj(item.msg)
        self.receive_data.clear()

    def get_users(self, account_ids: set):
        where = f'`#account_id` in {tuple(account_ids)}'
        res = self.db_client.get_all(self.db_name, 'user_view', where)
        if res is None:
            print('ck查询出错了')
            return
        for item in res.values():
            self.users[item['#account_id']] = item

    def get_user(self, account_id, data=None):
        user = self.users.get(account_id)
        if user:
            return user

        # user = self.db_client.get_one(self.db_name, f'{self.tb}_view', **{'#account_id': account_id})
        # if user:
        #     self.users[account_id] = user
        #     return user
        if not isinstance(data, dict):
            return
        user = dict()
        data['#reg_time'] = data['#time']
        self.merge(user, data)
        self.users[account_id] = user
        return user

    def merge(self, a: dict, b: dict):
        """
        将b 合并到 a
        :param a:
        :param b:
        :return:
        """
        for k, v in b.items():
            if isinstance(v, dict):
                self.merge(a, v)
            else:
                a[k] = v

    def merge_once(self, a: dict, b: dict):
        """
        a 存在的字段不接受b的合并
        :param a:
        :param b:
        :return:
        """
        for k, v in b.items():
            if isinstance(v, dict):
                self.merge_once(a, v)
            else:
                a[k] = v if a.get(k) is None else a[k]

    def merge_add(self, a: dict, b: dict):
        """
        b 的properties 属性累加到a
        :param a:
        :param b:
        :return:
        """
        if 'properties' not in b or not isinstance(b['properties'], dict):
            return
        for k, v in b['properties'].items():
            if not isinstance(v, int):
                raise ValueError('需要提供数值类型累加')
            a[k] = a.setdefault(k, 0) + v

    def merge_unset(self, a: dict, b: dict):
        """
        清除 a 中  b的properties
        :param db:
        :param data:
        :return:
        """
        if 'properties' not in b or not isinstance(b['properties'], list):
            return
        for k in b['properties']:
            if k in a:
                del a[k]

    def user_set(self, data: dict):
        """
        注意
        data 结构包含 properties
        user 为一层 k v
        将data 合并到 user
        :param db:
        :param data:
        :return:
        """
        account_id = data[self.user_key]
        user = self.get_user(account_id, data)
        self.merge(user, data)

    def user_setOnce(self, data: dict):
        account_id = data[self.user_key]
        user = self.get_user(account_id, data)
        self.merge_once(user, data)

    def user_add(self, data: dict):
        account_id = data[self.user_key]
        user = self.get_user(account_id, data)
        self.merge_add(user, data)

    def user_unset(self, data: dict):
        account_id = data[self.user_key]
        user = self.get_user(account_id)
        self.merge_unset(user, data)

    def user_append(self, data: dict):
        pass

    def user_del(self, data: dict):
        pass

    @property
    def buffer_pool(self):
        return self.tb, self.users
