from patch.include import *

from cmf.system_data import scaffold_status_codes
from tqdm import tqdm

from transliterate import translit
import re

from common.models.cmf_active_entity import CmfActiveEntity


# ??? Если клиенты пользовались кодами типа STS-001005 - они пропадут
# https://bcrm.carbonsoft.ru/project/Document/DOC-007557


# def calc_status_type(name: str) -> str:
#     mapping = {
#         "OPEN": ["открыт", "open", "к выполнению", 'todo', 'new'],
#         "IN_PROGRESS": ["работ", "progress", 'indeterminate', 'active'],
#         "IN_REVIEW": ["review", "ревью"],
#         "CLOSED": ["close", "закрыт", "готов", 'done', 'archived'],
#     }
#     return "OPEN"

def rename_status_types():
    for i in models.CmfNotify.list(include_deleted=True, fields=['obj_cache_status_type']):
        if i.obj_cache_status_type:
            i.obj_cache_status_type = i.obj_cache_status_type.value.upper()
            i.save(only_data=True, emit=False, notify=False)
    for i in models.CmfStatus.list(include_deleted=True, fields=['status_type']):
        if i.status_type:
            i.status_type = i.status_type.value.upper()
            i.save(only_data=True, emit=False, notify=False)
    for i in models.CmfStatusCode.list(include_deleted=True, fields=['status_type']):
        if i.status_type:
            i.status_type = i.status_type.value.upper()
            i.save(only_data=True, emit=False, notify=False)
    for i in models.CmfTaskFilter.list(include_deleted=True, fields=['ft_status_type']):
        if i.ft_status_type:
            i.ft_status_type = i.ft_status_type.value.upper()
            i.save(only_data=True, emit=False, notify=False)
    for i in models.CmfCard.list(include_deleted=True, fields=['obj_status_type']):
        if i.obj_status_type:
            i.obj_status_type = i.obj_status_type.value.upper()
            i.save(only_data=True, emit=False, notify=False)
    for model_cls in CmfActiveEntity.iter_subclasses():
        for obj in model_cls.list(include_deleted=True, fields=['cache_status_type']):
            if obj.cache_status_type:
                obj.cache_status_type = obj.cache_status_type.value.upper()
                obj.save(only_data=True, emit=False, notify=False)


@app_context(commit=True)
def patch():
    with cmfutil.disable_acl(), cmfutil.disable_notify():
        scaffold_status_codes()
        rename_status_types()
        # Нужно заполнить таблицу StatusCode
        for workflow in models.CmfWorkflow.list():
            # У каждого wf находим 3 статуса основных, остальным пытаемся создать или найти другой statusCode
            status_list = models.CmfStatus.list(workflow=workflow)

            # Уже созданные StatusType
            status_list = list(status_list)
            status_to_process = []
            for status in status_list:
                if not status.status_code:
                    if not status.name:
                        status.name = 'EMPTY'
                    if not status.status_type:
                        status.status_type = 'IN_PROGRESS'
                    status_to_process.append(status)
                    continue

            # Пробуем найти по коду
            status_list = status_to_process
            status_to_process = []
            for status in status_list:
                status_code = models.CmfStatusCode.get(code=status.code, fields=['code'])
                if not status_code:
                    status_code = models.CmfStatusCode.get(filter=[['name', 'ILIKE', status.name],
                                                                   ['status_type', '=', status.status_type]],
                                                           fields=['code'])
                    if not status_code:
                        status_to_process.append(status)
                        continue
                status.status_code = status_code
                status.code = status_code.code
                status.save(only_data=True, emit=False, notify=False)

            # Другие сопоставления...
            status_list = status_to_process
            status_to_process = []
            for status in status_list:
                status_code = None
                if status.name.value.lower().strip() in ['решена', 'закрыта', 'completed']:
                    status_code = models.CmfStatusCode.get(code='closed', fields=['code'])
                # ??? Доп.статус новый
                if status.name.value.lower().strip() in ['отклонена', 'отменена', 'canceled']:
                    # ??? Нужен ли отдельный статус-код?
                    status_code = models.CmfStatusCode.get(code='closed', fields=['code'])
                if status.name.value.lower().strip() in ['в работе', 'work in progress']:
                    status_code = models.CmfStatusCode.get(code='in_progress', fields=['code'])
                if status.name.value.lower().strip() in ['in review', 'in_review', 'check']:
                    status_code = models.CmfStatusCode.get(code='in_review', fields=['code'])
                if status.name.value.lower().strip() in ['приостановлена']:
                    status_code = models.CmfStatusCode.get(code='pause', fields=['code'])


                if not status_code:
                    status_to_process.append(status)
                    continue
                status.status_code = status_code
                status.code = status_code.code
                status.save(only_data=True, emit=False, notify=False)

            # Создаем status_code
            status_list = status_to_process
            status_to_process = []
            for status in status_list:
                code = status.name.value.strip().lower()
                if not code:
                    code = 'unknown'
                code = translit(code, language_code="ru", reversed=True)
                code = re.sub(r'[^a-z0-9_]+', '_', code)
                status_code = models.CmfStatusCode.get(code=code, fields=['code'])
                if not status_code:
                    print(f"Создадим StatusCode code={code} для статуса {status} (код статуса={status.code})")
                    status_code = models.CmfStatusCode(code=code, name=status.name, status_type=status.status_type)
                    status_code.save(emit=False, notify=False)
                status.status_code = status_code
                status.code = status_code.code
                status.save(only_data=True, emit=False, notify=False)

            # Проверяем что все главные статусы существуют
            if not models.CmfStatus.list(workflow=workflow, status_type='OPEN'):
                print(f'Создаем статус open для WF: {workflow}')
                status_code = models.CmfStatusCode.get(code='open')
                status = models.CmfStatus(status_code=status_code, name='Open',
                                          workflow=workflow, status_type='OPEN', code='open')
                status.save(only_data=True, emit=False, notify=False)
            if not models.CmfStatus.list(workflow=workflow, status_type='IN_PROGRESS'):
                print(f'Создаем статус in_progress для WF: {workflow}')
                status_code = models.CmfStatusCode.get(code='in_progress')
                status = models.CmfStatus(status_code=status_code, name='In progress',
                                          workflow=workflow, status_type='IN_PROGRESS', code='in_progress')
                status.save(only_data=True, emit=False, notify=False)
            if not models.CmfStatus.list(workflow=workflow, status_type='CLOSED'):
                print(f'Создаем статус closed для WF: {workflow}')
                status_code = models.CmfStatusCode.get(code='closed')
                status = models.CmfStatus(status_code=status_code, name='Closed',
                                          workflow=workflow, status_type='CLOSED', code='closed')
                status.save(only_data=True, emit=False, notify=False)


if __name__ == "__main__":
    patch()
