
from management.management.utils.utils import create_audit_log
from management.models.flussi import Flusso
from management.models.pratica import Pratica
from management.repositories.base import BaseRepository
from django.db import transaction

from management.serializers.flusso_serializer import FlussoSerializer
from django.db.models import F

class FlussoRepository(BaseRepository):
    entity=Flusso


    @transaction.atomic
    def save(self, dto, user_id=None) -> tuple:
        flow_id = dto.get("id")
        plan_id = dto.get("plan")
        new_pos = int(dto.get("codice_attivita", 0))
        dto['group'] = int(dto.pop("gruppo"))
        old_values = {}
        instance = None

        if flow_id:
            try:
                instance = Flusso.objects.get(id=flow_id)

                old_pos = instance.codice_attivita
                old_group = instance.group_id

                if old_group == dto['group']:

                    if new_pos > old_pos:
                        Flusso.objects.filter(
                            group_id=dto['group'],
                            codice_attivita__gt=old_pos,
                            codice_attivita__lte=new_pos
                        ).update(
                            codice_attivita=F('codice_attivita') - 1
                        )

                    elif new_pos < old_pos:
                        Flusso.objects.filter(
                            group_id=dto['group'],
                            codice_attivita__gte=new_pos,
                            codice_attivita__lt=old_pos
                        ).update(
                            codice_attivita=F('codice_attivita') + 1
                        )

                else:
                    Flusso.objects.filter(
                        group_id=old_group,
                        codice_attivita__gt=old_pos
                    ).update(
                        codice_attivita=F('codice_attivita') - 1
                    )

                    Flusso.objects.filter(
                        group_id=dto['group'],
                        codice_attivita__gte=new_pos
                    ).update(
                        codice_attivita=F('codice_attivita') + 1
                    )

                serializer = FlussoSerializer(
                    instance,
                    data=dto,
                    partial=True
                )

            except Flusso.DoesNotExist:
                return False, {"detail": "Flow not found"}, None
            old_values = FlussoSerializer(instance).data
        else:
            Flusso.objects.filter(
                group_id=dto['group'],
                codice_attivita__gte=new_pos
            ).update(
                codice_attivita=F('codice_attivita') + 1
            )

            serializer = FlussoSerializer(data=dto)

        if serializer.is_valid():
            flow = serializer.save()
            new_data = FlussoSerializer(flow).data
            new_values = {}

            for field in serializer.fields.keys():

                if field in ["id", "plan", "attachments", "allegati", 
                             "data_creazione", "pratica", "random_code", "stato"]:
                    continue

                old_value = old_values.get(field, "") if instance else ""
                new_value = new_data.get(field)

                # UPDATE -> solo campi modificati
                if instance:
                    if old_value != new_value:
                        new_values[field] = {
                            "old": old_value,
                            "new": new_value
                        }

                # CREATE -> tutti i campi
                else:
                    new_values[field] = {
                        "old": "",
                        "new": new_value
                    }

            activity_type = (
                "MODIFICA FLUSSO"
                if instance
                else "CREAZIONE FLUSSO"
            )

            create_audit_log(
                user=user_id,
                activity_type=activity_type,
                entity=flow,
                entity_name='Flusso',
                entity_id=plan_id,
                old_values=old_values if instance else None,
                new_values=new_values
            )

            return True, {}, flow

        return False, serializer.errors, None

    def delete(self, flow_id, user_id=None):
        instance = Flusso.objects.get(id=flow_id)
        group_id = instance.group_id
        old_pos = instance.codice_attivita
        
        with transaction.atomic():
            old_values = FlussoSerializer(instance).data
            instance.delete()
            Flusso.objects.filter(
                group_id=group_id,
                codice_attivita__gt=old_pos
            ).update(codice_attivita=F('codice_attivita') - 1)

            create_audit_log(
                user=user_id,
                activity_type="ELIMINAZIONE FLUSSO",
                entity=None,
                entity_name="Flusso",
                entity_id=flow_id,
                old_values=old_values,
                new_values=None
            )