import json

from patch.include import *
from tqdm import tqdm


def convert_operator(operator):
    if operator in ('LIKE', 'ILIKE'):
        return '~'
    elif operator in ('NOT LIKE', 'NOT ILIKE'):
        return '!~'
    elif operator in ('MEMBER_OF'):
        return 'in'
    elif operator == '==':
        return '='
    else:
        return operator.lower()


def convert_bql(bql, depth=0):
    if not isinstance(bql, list):
        return None

    if len(bql) == 3 and isinstance(bql[0], str) and not bql[0] in ('OR', 'AND'):
        field = 'project' if bql[0] == 'parent' else bql[0]
        operator = bql[1]
        value = bql[2]

        if operator == 'EXISTS':
            return None

        operator = convert_operator(operator)

        if isinstance(value, list):
            values = ', '.join(f'"{v}"' for v in value)
            value = f'({values})'
        elif isinstance(value, str):
            value = value.replace('now()', '')
            value = value.strip()

        return f'{field} {operator} "{value}"'

    queryset = []
    operator = 'and'
    for item in bql:
        if item in ('OR', 'AND'):
            operator = item.lower()
            continue
        else:
            jql = convert_bql(item, depth + 1)
            if jql:
                queryset.append(jql)
    query = f' {operator} '.join(queryset)
    if query:
        return f'({query})' if depth > 0 else query


@app_context(commit=True)
def convert_bql_to_ubql2():
    """
    Для тестирования патча: ( cd /opt/eva-app; python3 -m patch.202401121453_convert_bql_to_ubql2 )
    Здесь можно работать с моделями через models.CmfTask и т.д.
    Для прогрессбара используйте:
    for task in tqdm(models.CmfTask.list()):
        ...
    """
    print('Запуск патча convert_bql_to_ubql2')
    count = 0

    with cmfutil.disable_acl(), cmfutil.disable_notify():
        task_filters = models.CmfTaskFilter.list(
            filter=[['bql', '!=', '[]'], ['OR', ['ubql2', '=', ''], ['ubql2', '=', None]]],
            fields=['bql']
        )
        for task_filter in tqdm(task_filters):
            if not task_filter.bql:
                continue

            count += 1

            bql = json.loads(str(task_filter.bql))
            task_filter.ubql2 = convert_bql(bql)
            task_filter.save(only_data=True, emit=False, notify=False)

            if count % 1000 == 0:
                commit_all_ds()


if __name__ == "__main__":
    convert_bql_to_ubql2()
