import json
from typing import Any, Dict, List

from staff.lib.utils.ordered_tasks import OrderedTasks, DatetimeJSONEncoder

from staff.groups.models import ServiceUpdateTasksQueue


class ServiceUpdateTasks(OrderedTasks):
    max_retry_attempts = 3
    Model = ServiceUpdateTasksQueue
    identity_field = 'fake_identity'
    identity_value = 'fake_identity'

    @classmethod
    def schedule_services_update(cls, services_id: List[int], dry: bool = False, force: bool = False):
        from staff.groups.tasks import update_service_groups
        callable_name, callable_module = cls._get_name_and_module(update_service_groups)
        to_create = []
        for service_id in services_id:
            kwargs = cls._serialize({'service_id': service_id, 'dry': dry, 'force': force})
            to_create.append(ServiceUpdateTasksQueue(
                fake_identity=cls.identity_value,
                service_id=service_id,
                args=kwargs,
                callable=callable_name,
                module=callable_module,
            ))

        ServiceUpdateTasksQueue.objects.bulk_create(to_create)

    @classmethod
    def _kwargs_for_model_creation(
        cls,
        identity: Any,
        kwargs: Dict[str, Any],
        module: str,
        callable: str,
    ) -> Dict[str, Any]:
        return {
            cls.identity_field: identity,
            'args': json.dumps(kwargs, cls=DatetimeJSONEncoder),
            'service_id': kwargs['service_id'],
            'module': module,
            'callable': callable,
        }

    @classmethod
    def _execute_task(cls, task: Any, args: str):
        kwargs = cls._deserialize(args)
        # удаляем дубликаты из очереди, чтобы не запускаться на одном и том же несколько раз
        ServiceUpdateTasksQueue.objects.filter(service_id=kwargs['service_id']).delete()
        task(**kwargs)
