from patch.include import *
from tqdm import tqdm


@app_context(commit=True)
def migrate_custom_fields():
    """
    Для тестирования патча: ( cd /opt/eva-app; python3 -m patch.202402120841_migrate_custom_fields )
    Здесь можно работать с моделями через models.CmfTask и т.д.
    Для прогрессбара используйте:
    for task in tqdm(models.CmfTask.list()):
        ...
    """
    from cmf.system_data import scaffold_cust_field_config_schemes
    print('Запуск патча migrate_custom_fields')
    scaffold_cust_field_config_schemes()
    for project in tqdm(models.CmfProject.list(filter=[['cust_field_conf_scheme', '==', None],
                                                       ['logic_prefix', '!=', None]], fields=['logic_prefix'])):
        project._calc_cust_field_conf_scheme()
        project.save(only_data=True)
    commit_with_event()
    ui_form_custom_fields = dict()
    ui_form_names = dict()
    # соберем все кастомизации полей из экранов
    for ui_form in tqdm(models.CmfUiForm.list(fields=['*'], filter=[['cmf_model_name', '==', 'CmfTask'], ['ui_form_json', '!=', None],
                                                                    ['code', 'NOT LIKE', '%default%']], include_deleted=True)):
        ui_form_names[ui_form.id.value] = ui_form.name.value
        # ui_form.ui_form_json.get('ui_fields', {}) не работает
        for ui_field in ui_form.ui_form_json.value.get('ui_fields', {}):
            # Это системная настройка по умолчанию
            # Она не настраивается из веб пользователем
            if ui_form.ui_form_json['ui_fields'][ui_field] == {'visible_filter': {'parent_logic_prefix': ['project.agile']}}:
                continue
            if ui_field not in models.CmfTask.fields:
                print(f'Изменено поле не принадлежащее Задаче {ui_field}, в {ui_form.id}')
                continue
            # Это кастомное поле
            if ui_field.startswith('cf_'):
                cust_field = models.CmfCustField.get(name=ui_field)
                if not cust_field:
                    widget=ui_form.ui_form_json['ui_fields'][ui_field].get('widget')
                    field_type=ui_form.ui_form_json['ui_fields'][ui_field]['field_type']
                    if not widget:
                        # Иногда в json виджет пустой
                        widget = field_type
                    choices = ui_form.ui_form_json['ui_fields'][ui_field].get('choices')
                    # Актуальный список choices берем прямо в custom-модели, т.к. в экране может попасться не актуальный список
                    if hasattr(getattr(models.CmfTask, ui_field), 'choices'):
                        _ch = getattr(models.CmfTask, ui_field).choices
                        if _ch:
                            choices = _ch
                    cust_field = models.CmfCustField(name=ui_field,
                                                     caption=ui_form.ui_form_json['ui_fields'][ui_field]['caption'],
                                                     field_type=field_type,
                                                     comment=ui_form.ui_form_json['ui_fields'][ui_field].get('comment', ''),
                                                     choices=choices,
                                                     field_custom_type=0,
                                                     cmf_model_name='CmfTask',
                                                     left=ui_form.ui_form_json['ui_fields'][ui_field].get('left', False),
                                                     right=ui_form.ui_form_json['ui_fields'][ui_field].get('right', False),
                                                     model=ui_form.ui_form_json['ui_fields'][ui_field].get('model'),
                                                     models=ui_form.ui_form_json['ui_fields'][ui_field].get('models'),
                                                     widget=widget,
                                                     dirty=True)
                    # Кривые данные правим
                    if cust_field.field_type == 'CmfM2M' and cust_field.model.is_null:
                        cust_field.model = 'CUSTOM_CHOICE_MODEL'
                    cust_field.save(only_data=True)
                    continue
                for attr_name, val in ui_form.ui_form_json['ui_fields'][ui_field].items():
                    if attr_name in ('class_name', 'custom', 'widget', 'model'):
                         continue
                    #Изменили кастомное поле, сохраняем в конфигурацию
                    if (hasattr(cust_field, attr_name) or attr_name == 'required_change') and getattr(cust_field, attr_name) != val:
                        if ui_form.id.value not in ui_form_custom_fields:
                            ui_form_custom_fields[ui_form.id.value] = dict()
                        if ui_field not in ui_form_custom_fields[ui_form.id.value]:
                            ui_form_custom_fields[ui_form.id.value][ui_field] = dict()
                        ui_form_custom_fields[ui_form.id.value][ui_field][attr_name] = val
                continue
            # проверим не поменяли ли системное поле
            for attr_name, val in ui_form.ui_form_json['ui_fields'][ui_field].items():
                if attr_name in ('class_name', 'custom', 'widget', 'model'):
                    continue
                if (hasattr(models.CmfTask.fields[ui_field], attr_name) or attr_name == 'required_change'):
                    attr_val = getattr(models.CmfTask.fields[ui_field], attr_name)
                    if attr_name == 'caption' and attr_val == 'Логический тип' and val == 'Тип':
                        continue
                    if attr_val != val:
                        if ui_form.id.value not in ui_form_custom_fields:
                            ui_form_custom_fields[ui_form.id.value] = dict()
                        if ui_field not in ui_form_custom_fields[ui_form.id.value]:
                            ui_form_custom_fields[ui_form.id.value][ui_field] = dict()
                        ui_form_custom_fields[ui_form.id.value][ui_field][attr_name] = val
                        if attr_name == 'caption':
                            ui_form_custom_fields[ui_form.id.value][ui_field]['orig_caption'] = attr_val
    print('Найдены кастомизации полей')
    print(ui_form_custom_fields)
    for ui_form_id in ui_form_custom_fields:
        cust_conf = models.CmfCustFieldConf.get(ext_id=ui_form_id)
        if not cust_conf:
            cust_conf = models.CmfCustFieldConf(ext_id=ui_form_id)
            cust_conf.name = f'Конфигурация от экрана {ui_form_names[ui_form_id]}'
            cust_conf.save(only_data=True)
        for field_name in ui_form_custom_fields[ui_form_id]:
            if field_name.startswith('cf_'):
                cust_field = models.CmfCustField.get(name=field_name)
            else:
                cust_field = None
            field_conf = models.CmfCustFieldConfField.get(name=field_name, parent=cust_conf)
            if not field_conf:
                field_conf = models.CmfCustFieldConfField(name=field_name, parent=cust_conf, cust_field=cust_field)
            for attname, attval in ui_form_custom_fields[ui_form_id][field_name].items():
                setattr(field_conf, attname, attval)
            field_conf.save(only_data=True)
        for ui_form_s_rule in models.CmfUiFormSchemeRule.list(filter=['target', '==', ui_form_id], fields=['ui_form_scheme.projects'], order_by=['-orderno']):
            cust_field_conf_scheme = models.CmfCustFieldConfScheme.get(ext_id=ui_form_s_rule.ui_form_scheme.id)
            if not cust_field_conf_scheme:
                cust_field_conf_scheme = models.CmfCustFieldConfScheme(ext_id=ui_form_s_rule.ui_form_scheme.id)
                cust_field_conf_scheme.name = f"Схема из схемы экранов {ui_form_s_rule.ui_form_scheme.code}"
                cust_field_conf_scheme.save(only_data=True)
            # Привяжем проекты к новой схеме полей
            for project in ui_form_s_rule.ui_form_scheme.projects:
                project.cust_field_conf_scheme = cust_field_conf_scheme
                project.save(only_data=True)
            # Переносим рулезы 1к1
            cust_field_rule = models.CmfCustFieldConfSchemeRule.get(ext_id=ui_form_s_rule.id)
            if not cust_field_rule:
                cust_field_rule = models.CmfCustFieldConfSchemeRule(parent=cust_field_conf_scheme, 
                                                                    cust_field_conf=cust_conf, ext_id=ui_form_s_rule.id)
                for logic_type in ui_form_s_rule.logic_types:
                    cust_field_rule.logic_types.append(logic_type)
                cust_field_rule.save(only_data=True)
    models.CmfTask.custom_field_sync()
            


if __name__ == "__main__":
    migrate_custom_fields()
