from patch.include import *
from tqdm import tqdm


def _calc_perm_parent(self):
    perm_parent = None
    if self.tree_parent and not isinstance(self, (models.CmfComment, models.CmfTask)):
        perm_parent = self.tree_parent
    elif self.parent:
        perm_parent = self.parent
    self.perm_parent = perm_parent


@app_context(commit=True)
def patch():
    """
    Для тестирования патча: ( cd /opt/crm; python3 -m patch.202205230433_tree_parent_set )
    Здесь можно работать с моделями через models.CmfTask и т.д.
    Для прогрессбара используйте:
    for task in tqdm(models.CmfTask.list()):
        ...
    """
    # Считаем, что ACL в системе нет и надо только построить иерархию.
    total_count = 0
    total_all_count = 0
    for model_cls in cmf.models.CmfEntity.iter_subclasses():
        if model_cls.class_name in ('CmfAccessList', 'CmfAccessRule'):
            continue
        model_count = 0
        model_all_count = 0
        print(f'Patch {model_cls.class_name}')
        start = 0
        limit = 100
        while True:
            obj_list = model_cls.list(
                filter=[
                    [
                        'OR',
                        ['parent_id', '!=', None],
                        ['tree_parent_id', '!=', None],
                    ],
                    ['perm_parent_id', '=', None],
                ],
                fields=['parent', 'tree_parent', 'perm_parent'],
                slice=[start, start + limit]
            )
            start += limit
            if not obj_list:
                break
            for obj in tqdm(obj_list):
                model_all_count += 1
                # print(f'{obj}, {obj.parent}, {obj.tree_parent}, {obj.perm_parent}')
                if (obj.parent or obj.tree_parent) and not obj.perm_parent:
                    _calc_perm_parent(obj)
                    obj.save(only_data=True)
                    model_count += 1
                    if model_count % 1000 == 0:
                        commit_all_ds()  # большие транзакции замедляются
            # else:
            #     print('!else')
            commit_all_ds()
            print(f'  obj count {model_count}/{model_all_count}')
            total_count += model_count
            total_all_count += model_all_count
    print(f'Total count {total_count}/{total_all_count}')


if __name__ == "__main__":
    patch()
