"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 17.11.20

"""
from django.contrib.auth.models import User
from django.contrib.gis.db import models
from django.db import transaction
from django.utils import timezone
from django.utils.timezone import now

from compensation.models import Payment, Compensation
from intervention.settings import INTERVENTION_IDENTIFIER_LENGTH, INTERVENTION_IDENTIFIER_TEMPLATE
from konova.models import BaseObject, Geometry
from konova.utils.generators import generate_random_string
from organisation.models import Organisation


class Intervention(BaseObject):
    """
    Interventions are e.g. construction sites where nature used to be.
    """
    registration_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True, related_name="+")
    registration_file_number = models.CharField(max_length=1000, blank=True, null=True)
    conservation_office = models.ForeignKey(Organisation, on_delete=models.SET_NULL, null=True, related_name="+")
    conservations_file_number = models.CharField(max_length=1000, blank=True, null=True)
    process_type = models.CharField(max_length=500, null=True, blank=True)
    law = models.CharField(max_length=500, null=True, blank=True)
    handler = models.CharField(max_length=500, null=True, blank=True)
    geometry = models.ForeignKey(Geometry, null=True, blank=True, on_delete=models.SET_NULL)
    documents = models.ManyToManyField("konova.Document", blank=True)

    # Refers to "zugelassen am"
    registration_date = models.DateField(null=True, blank=True)

    # Refers to "Bestandskraft am"
    binding_on = models.DateField(null=True, blank=True)

    # Refers to "verzeichnen"
    recorded_on = models.DateTimeField(default=None)
    recorded_by = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL)

    # Holds which intervention is simply a newer version of this dataset
    next_version = models.ForeignKey("Intervention", null=True, on_delete=models.DO_NOTHING)

    # Compensation or payments, one-directional
    payments = models.ManyToManyField(Payment, related_name="+")
    compensations = models.ManyToManyField(Compensation, related_name="+")

    def delete(self, *args, **kwargs):
        """ Custom delete functionality

        Does not delete from database but sets a timestamp for being deleted on and which user deleted the object

        Args:
            *args ():
            **kwargs ():

        Returns:

        """
        _now = timezone.now()
        _user = kwargs.get("user", None)

        with transaction.atomic():
            # "Delete" related compensations as well
            coms = self.compensations.all()
            for com in coms:
                com.deleted_on = _now
                com.deleted_by = _user
                com.save()

            self.deleted_on = _now
            self.deleted_by = _user
            self.save()

    @staticmethod
    def _generate_new_identifier() -> str:
        """ Generates a new identifier for the intervention object

        Returns:
            str
        """
        curr_month = str(now().month)
        curr_year = str(now().year)
        rand_str = generate_random_string(
            length=INTERVENTION_IDENTIFIER_LENGTH,
            only_numbers=True,
        )
        _str = "{}{}{}".format(curr_month, curr_year, rand_str)
        return INTERVENTION_IDENTIFIER_TEMPLATE.format(_str)

    def save(self, *args, **kwargs):
        if self.identifier is None or len(self.identifier) == 0:
            # Create new identifier
            new_id = self._generate_new_identifier()
            while Intervention.objects.filter(identifier=new_id).exists():
                new_id = self._generate_new_identifier()
            self.identifier = new_id
        super().save(*args, **kwargs)