from patch.include import *
from tqdm import tqdm
import os


@app_context(commit=True)
def patch():
    from cmf.system_data import scaffold_logic_type, scaffold_workflow, scaffold_scheme_wf
    scaffold_logic_type()
    scaffold_workflow()
    scaffold_scheme_wf()

    # Заполняем поле default_subproject_workflow у схем WF и заменяем default_epic_workflow с листа на тасковый
    for scheme in models.CmfSchemeWf.list(fields=['default_subproject_workflow', 'default_epic_workflow.code']):
        need_save = False
        if not scheme.default_subproject_workflow:
            need_save = True
            scheme.default_subproject_workflow = models.CmfWorkflow.get(code='task.subproject:default')
        if scheme.default_epic_workflow and \
                (scheme.default_epic_workflow.code.value.startswith('list') or scheme.default_epic_workflow.code == 'default.system:default'):
            need_save = True
            scheme.default_epic_workflow = models.CmfWorkflow.get(code='task.epic:default')
        if need_save:
            scheme.save(only_data=True)

    # Чистим устаревшие поля епиков в фильтрах
    for filter in models.CmfTaskFilter.list(fields=['ft_epics']):
        if filter.ft_epics:
            filter.ft_epics = []
            filter.save(only_data=True)

    # Сохраняем в задачах их прошлый список епиков, кроме main_list. Т.к. они удалятся
    for old_epic in tqdm(models.CmfList.list(filter=['OR', ['sys_type', '=', 'epic'], ['logic_prefix', '=', 'list.agile_epic']], fields=['*'])):
        for task in models.CmfTask.list(filter=[['main_list', '!=', old_epic], ['lists', 'IN', [old_epic.id.value]]], fields=['main_list', 'lists', 'text']):
            task.text = f'Патч 2022.11 задача удалена из эпика: {old_epic.id}:{old_epic.code}:{old_epic.name}\n{task.text}'
            task.save(only_data=True)

    # Конвертируем все old-style епики-списки в новые епики-таски
    # Если не main_list - не выставляем епик
    epic_logic_type = models.CmfLogicType.get(code='task.epic:default')
    for old_epic in tqdm(models.CmfList.list(filter=['OR', ['sys_type', '=', 'epic'], ['logic_prefix', '=', 'list.agile_epic']], fields=['***'])):
        print()
        print('Конвертируем Epic: ', old_epic)
        new_epic = models.CmfTask(logic_type=epic_logic_type)
        for field, value in old_epic.items(is_defined=True):
            if field in ['id', 'logic_type', 'cmf_modified_by', 'cmf_locked_at', 'cmf_created_at',
                         'cmf_modified_at', 'cmf_viewed_at', 'cmf_deleted', 'cmf_version', 'code',
                         'system', 'tasks', 'documents', 'comments', 'tree_nodes', 'has_tree_nodes',
                         'tree_node_is_branch', 'tree_hidden', 'perm_public', 'perm_has_acl', 'perm_parent',
                         'perm_parent_owner_id', 'perm_inherit_acl_id', 'perm_effective_acl_id',
                         'is_public', 'is_public_editable', 'is_public_comments', 'workflow',
                         'logic_prefix', 'parent_logic_prefix', 'status', 'status_modified_at',
                         'status_in_progress_start', 'status_in_progress_end', 'status_review_at',
                         'status_closed_at', 'company', 'sharelink_hash', 'list_type', 'sys_type',
                         'cache_status_type', 'cache_status_opt']:
                continue
            if field.endswith('_id'):
                continue
            setattr(new_epic, field, value)
        new_epic.logic_type = epic_logic_type

        # Бизнес-процесс по-умолчанию для задач -- есть у таски, Поле уже скопировано

        new_epic.workflow = models.CmfWorkflow.get(code='task.epic:default')
        # Тип по умолчанию для новых задач
        new_epic.save(only_data=True)

        for task in tqdm(models.CmfTask.list(filter=[['lists', 'IN', [old_epic.id.value]]], fields=['lists', 'main_list'])):
            # Если old_epic = main_list - перемещаем в новый епик
            # Если old_epic in lists - просто удаляем, не очищаем
            # В текст задачи ззаписать все эпики, в которых была задача, кроме main_list
            # name:id (чтобы можно было распарсить
            task.lists.remove(old_epic)
            if task.main_list == old_epic:
                task.main_list = None
                task.parent_task = new_epic
            task.save(only_data=True)
        old_epic.delete()

    # TODO0: нужно ли листы конвертить в епики, если name.startswith('EPIC' or 'Эпик' or 'Епик')
    # !!! Конвертить лишние плохо, т.к. если это многосписочность - мы их удалим у тасок
    # Пробелма, чтобы менеджеры в голове не считали их эпиками
    # Мб удалить в патче слово епик им? А что это: спринт, тег, категория?
    # TODO: просто вырезать слово епик из нейма и вместо него ставить Список
    # Исправляем имена списков, которые ранее по ошибке назвали Эпиками
    for not_epic_list in tqdm(models.CmfList.list(filter=['OR', ['name', 'ILIKE', 'epic%'],
                                                          ['name', 'ILIKE', 'эпик%'],
                                                          ['name', 'ILIKE', 'епик%']], fields=['*'])):
        if not_epic_list.sys_type == 'epic':
            continue
        if not_epic_list.logic_prefix == 'list.agile_epic':
            continue
        not_epic_list.name = 'Список' + not_epic_list.name[4:]
        not_epic_list.save(only_data=True)

    # Удаляем устаревший logic_type
    bad_lt = models.CmfLogicType.get(code='list.agile_epic:default')
    bad_lt.delete()


if __name__ == "__main__":
    os.environ["NO_CACHE"] = "1"
    patch()
