import logging
from typing import List, Tuple
from uuid import uuid1

from django.core.serializers.json import Serializer as JsonSerializer
from django.db import models

from staff.departments.models import DepartmentChain
from staff.emission.logbroker.models import LogbrokerLog, NotSent, Sent


logger = logging.getLogger(__name__)


class Serializer(JsonSerializer):
    def handle_field(self, obj, field):
        if field.model == DepartmentChain and field.name in ['chiefs', 'hr_partners']:
            self._current[field.name] = field.value_from_object(obj)
        else:
            return super().handle_field(obj, field)

    def handle_fk_field(self, obj, field):
        self._current[field.name] = field.value_from_object(obj)

    def handle_m2m_field(self, obj, field):
        pass


class LogbrokerOrmStorage:
    id_field = 'id'
    model_class = LogbrokerLog

    def __init__(self, transaction_wait_delta):
        self.transaction_wait_delta = transaction_wait_delta

    @property
    def values_args(self):
        return self.id_field, 'data', 'action', 'creation_time'

    def get_unsent_queryset(self) -> models.QuerySet:
        return LogbrokerLog.objects.exclude(notsent=None).order_by('id').values(*self.values_args)

    def mark_sent(self, qs: models.QuerySet):
        messages_ids = list(qs.values_list('id', flat=True))
        NotSent.objects.filter(entry_id__in=messages_ids).delete()

        to_create = []
        for master_log_item_id in messages_ids:
            to_create.append(Sent(entry_id=master_log_item_id))

        logger.info('Move %s messages to sent', len(to_create))
        Sent.objects.bulk_create(to_create)

    def serialize_objects(self, objs):
        """Serialize a data object to add the message"""
        return Serializer().serialize(objs)

    def bulk_create(self, objects_data: List[Tuple[str, str]]):
        batch_id = uuid1()
        self.model_class.objects.bulk_create([
            self.model_class(data=data, action=action, batch_id=batch_id) for data, action in objects_data
        ])

        ids = self.model_class.objects.filter(batch_id=batch_id).values_list('id', flat=True)
        NotSent.objects.bulk_create([NotSent(entry_id=single_id) for single_id in ids])
