"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: ksp-servicestelle@sgdnord.rlp.de
Created on: 18.08.22

"""
from django import forms
from django.db import transaction
from django.urls import reverse, reverse_lazy
from django.utils.translation import gettext_lazy as _
from compensation.forms.compensation import AbstractCompensationForm
from compensation.forms.mixins import CompensationResponsibleFormMixin, PikCompensationFormMixin
from compensation.models import EcoAccount
from intervention.models import Handler, Responsibility, Legal
from konova.forms import SimpleGeomForm
from konova.forms.modals import RemoveModalForm
from user.models import User, UserActionLogEntry


class NewEcoAccountForm(AbstractCompensationForm, CompensationResponsibleFormMixin, PikCompensationFormMixin):
    """ Form for creating eco accounts

    Inherits from basic AbstractCompensationForm and further form fields from CompensationResponsibleFormMixin

    """
    surface = forms.DecimalField(
        min_value=0.00,
        decimal_places=2,
        label=_("Available Surface"),
        label_suffix="",
        required=False,
        help_text=_("The amount that can be used for deductions"),
        widget=forms.NumberInput(
            attrs={
                "class": "form-control",
                "placeholder": "0,00"
            }
        )
    )
    registration_date = forms.DateField(
        label=_("Agreement date"),
        label_suffix="",
        help_text=_("When did the parties agree on this?"),
        required=False,
        widget=forms.DateInput(
            attrs={
                "type": "date",
                "class": "form-control",
            },
            format="%d.%m.%Y"
        )
    )

    field_order = [
        "identifier",
        "title",
        "conservation_office",
        "registration_date",
        "surface",
        "conservation_file_number",
        "is_pik",
        "handler_type",
        "handler_detail",
        "comment",
    ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.form_title = _("New Eco-Account")

        self.action_url = reverse("compensation:acc:new")
        self.cancel_redirect = reverse("compensation:acc:index")

        tmp = EcoAccount()
        identifier = tmp.generate_new_identifier()
        self.initialize_form_field("identifier", identifier)
        self.fields["identifier"].widget.attrs["url"] = reverse_lazy("compensation:acc:new-id")
        self.fields["title"].widget.attrs["placeholder"] = _("Eco-Account XY; Location ABC")

    def save(self, user: User, geom_form: SimpleGeomForm):
        with transaction.atomic():
            # Fetch data from cleaned POST values
            identifier = self.cleaned_data.get("identifier", None)
            title = self.cleaned_data.get("title", None)
            registration_date = self.cleaned_data.get("registration_date", None)
            handler_type = self.cleaned_data.get("handler_type", None)
            handler_detail = self.cleaned_data.get("handler_detail", None)
            surface = self.cleaned_data.get("surface", None)
            conservation_office = self.cleaned_data.get("conservation_office", None)
            conservation_file_number = self.cleaned_data.get("conservation_file_number", None)
            is_pik = self.cleaned_data.get("is_pik", None)
            comment = self.cleaned_data.get("comment", None)

            # Create log entry
            action = UserActionLogEntry.get_created_action(user)

            handler = Handler.objects.create(
                type=handler_type,
                detail=handler_detail,
            )

            responsible = Responsibility.objects.create(
                handler=handler,
                conservation_file_number=conservation_file_number,
                conservation_office=conservation_office,
            )

            legal = Legal.objects.create(
                registration_date=registration_date
            )

            # Finally create main object
            acc = EcoAccount.objects.create(
                identifier=identifier,
                title=title,
                responsible=responsible,
                deductable_surface=surface,
                created=action,
                modified=action,
                comment=comment,
                is_pik=is_pik,
                legal=legal
            )
            acc.share_with_user(user)

            # Add the log entry to the main objects log list
            acc.log.add(action)

        # Process the geometry form
        geometry = geom_form.save(action)
        acc.geometry = geometry
        acc.save()
        acc.update_deductable_rest()
        return acc


class EditEcoAccountForm(NewEcoAccountForm):
    """ Form for editing eco accounts

    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.form_title = _("Edit Eco-Account")

        self.action_url = reverse("compensation:acc:edit", args=(self.instance.id,))
        self.cancel_redirect = reverse("compensation:acc:detail", args=(self.instance.id,))

        # Initialize form data
        reg_date = self.instance.legal.registration_date
        if reg_date is not None:
            reg_date = reg_date.isoformat()

        form_data = {
            "identifier": self.instance.identifier,
            "title": self.instance.title,
            "surface": self.instance.deductable_surface,
            "handler_type": self.instance.responsible.handler.type,
            "handler_detail": self.instance.responsible.handler.detail,
            "registration_date": reg_date,
            "conservation_office": self.instance.responsible.conservation_office,
            "conservation_file_number": self.instance.responsible.conservation_file_number,
            "is_pik": self.instance.is_pik,
            "comment": self.instance.comment,
        }
        disabled_fields = []
        self.load_initial_data(
            form_data,
            disabled_fields
        )

    def save(self, user: User, geom_form: SimpleGeomForm):
        with transaction.atomic():
            # Fetch data from cleaned POST values
            identifier = self.cleaned_data.get("identifier", None)
            title = self.cleaned_data.get("title", None)
            registration_date = self.cleaned_data.get("registration_date", None)
            handler_type = self.cleaned_data.get("handler_type", None)
            handler_detail = self.cleaned_data.get("handler_detail", None)
            surface = self.cleaned_data.get("surface", None)
            conservation_office = self.cleaned_data.get("conservation_office", None)
            conservation_file_number = self.cleaned_data.get("conservation_file_number", None)
            comment = self.cleaned_data.get("comment", None)
            is_pik = self.cleaned_data.get("is_pik", None)

            # Create log entry
            action = UserActionLogEntry.get_edited_action(user)

            # Update responsible data
            self.instance.responsible.handler.type = handler_type
            self.instance.responsible.handler.detail = handler_detail
            self.instance.responsible.handler.save()
            self.instance.responsible.conservation_office = conservation_office
            self.instance.responsible.conservation_file_number = conservation_file_number
            self.instance.responsible.save()

            # Update legal data
            self.instance.legal.registration_date = registration_date
            self.instance.legal.save()

            # Update main oject data
            self.instance.identifier = identifier
            self.instance.title = title
            self.instance.deductable_surface = surface
            self.instance.comment = comment
            self.instance.is_pik = is_pik
            self.instance.modified = action
            self.instance.save()

            # Add the log entry to the main objects log list
            self.instance.log.add(action)

        # Process the geometry form (NOT ATOMIC TRANSACTION DUE TO CELERY!)
        geometry = geom_form.save(action)
        self.instance.geometry = geometry
        self.instance.save()
        self.instance.update_deductable_rest()
        return self.instance


class RemoveEcoAccountModalForm(RemoveModalForm):

    def is_valid(self):
        super_valid = super().is_valid()
        has_deductions = self.instance.deductions.exists()
        if has_deductions:
            self.add_error(
                "confirm",
                _("The account can not be removed, since there are still deductions.")
            )
        return super_valid and not has_deductions