from django import forms
from django.core.exceptions import ValidationError
from django.forms.models import BaseInlineFormSet
from webpack_loader.loader import WebpackLoader

from .models import Contract, ContracteeSignature, SigneeSignature


class AtLeastOneRequiredInlineFormSet(BaseInlineFormSet):
    def clean(self):
        """Check that at least one item has been entered."""

        super().clean()

        if any(self.errors):
            return

        if not any(
            cleaned_data and not cleaned_data.get("DELETE", False)
            for cleaned_data in self.cleaned_data
        ):
            raise forms.ValidationError("Vyžadován aspoň jeden záznam.")


class ContractAdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        if "status" in self.fields:
            allowed_choices = []

            for choice_key, choice_label in Contract.StatusTypes.choices:
                # Not yet created
                if self.instance.id is None:
                    if choice_key in (
                        Contract.StatusTypes.WORK_IN_PROGRESS,
                        Contract.StatusTypes.TO_BE_APPROVED,
                    ):
                        allowed_choices.append(
                            (
                                choice_key,
                                choice_label,
                            )
                        )

                    continue

                if self.instance.status == choice_key:
                    allowed_choices.append(
                        (
                            choice_key,
                            choice_label,
                        )
                    )
                    continue

                if (
                    choice_key == Contract.StatusTypes.TO_BE_APPROVED
                    and self.instance.status != Contract.StatusTypes.APPROVED
                    and (
                        self.current_user == self.instance.created_by
                        or self.current_user.has_perm("contract.edit_others")
                    )
                ):
                    allowed_choices.append((choice_key, choice_label))

                if self.instance.status == Contract.StatusTypes.APPROVED:
                    if self.current_user.has_perm("contracts.approve"):
                        if choice_key == Contract.StatusTypes.WORK_IN_PROGRESS:
                            allowed_choices.append(
                                (
                                    choice_key,
                                    choice_label,
                                )
                            )
                            continue

                if self.instance.status == Contract.StatusTypes.TO_BE_APPROVED:
                    if self.current_user.has_perm("contracts.approve"):
                        if choice_key in (
                            Contract.StatusTypes.APPROVED,
                            Contract.StatusTypes.REJECTED,
                            Contract.StatusTypes.WORK_IN_PROGRESS,
                        ):
                            allowed_choices.append(
                                (
                                    choice_key,
                                    choice_label,
                                )
                            )
                            continue

                if self.instance.status == Contract.StatusTypes.REJECTED:
                    if choice_key in (
                        Contract.StatusTypes.WORK_IN_PROGRESS,
                        Contract.StatusTypes.TO_BE_APPROVED,
                    ):
                        allowed_choices.append(
                            (
                                choice_key,
                                choice_label,
                            )
                        )
                        continue

            self.fields["status"].widget = forms.Select(choices=allowed_choices)

    def clean(self):
        clean_data = super().clean()

        if (
            self.instance.status
            == clean_data.get("status")
            == self.instance.StatusTypes.REJECTED
        ):
            raise ValidationError(
                {"status": ("Smlouvu nelze upravovat, zatímco je zamítnutá.")}
            )

        if (
            not self.current_user.is_superuser
            and clean_data.get("status", self.instance.status)
            in (self.instance.StatusTypes.APPROVED, self.instance.StatusTypes.REJECTED)
            and self.instance.status != clean_data.get("status", self.instance.status)
            and self.current_user == self.instance.created_by
        ):
            raise ValidationError(
                {
                    "status": (
                        "Smlouva nemůže být schválena / zamítnuta uživatelem, který ji nahrál."
                    )
                }
            )

        return clean_data

    class Media:
        js = (
            "shared/runtime.js",
            "shared/shared.js",
            "shared/admin_contract_form.js",
        )

    class Meta:
        widgets = {
            "summary": forms.Textarea(attrs={"rows": 2}),
        }


class ContractFileAdminForm(forms.ModelForm):
    class Media:
        js = ("shared/admin_contract_file_form.js",)

    class Meta:
        widgets = {
            "name": forms.TextInput(attrs={"list": "file-types"}),
        }


class SigneeAdminForm(forms.ModelForm):
    class Media:
        js = (
            "shared/runtime.js",
            "shared/shared.js",
            "shared/admin_signee_form.js",
        )

    def clean(self):
        cleaned_data = super().clean()

        if cleaned_data.get("entity_type") == "natural_person":
            if cleaned_data.get("ico_number") is not None:
                raise ValidationError(
                    {"ico_number": "IČO nesmí být pro fyzické osoby definováno."}
                )

            if cleaned_data.get("department") is not None:
                raise ValidationError(
                    {
                        "department": "Organizační složka nesmí být pro fyzické osoby definována."
                    }
                )

            if cleaned_data.get("date_of_birth") is None:
                raise ValidationError(
                    {
                        "date_of_birth": "Datum narození musí pro fyzické osoby být definováno."
                    }
                )

        if cleaned_data.get("entity_type") == "business_natural_person":
            if cleaned_data.get("ico_number") is None:
                raise ValidationError(
                    {
                        "ico_number": "IČO musí být pro podnikající fyzické osoby definováno."
                    }
                )

            if cleaned_data.get("department") is not None:
                raise ValidationError(
                    {
                        "department": "Organizační složka nesmí být pro podnikající fyzické osoby definována."
                    }
                )

            if cleaned_data.get("date_of_birth") is not None:
                raise ValidationError(
                    {
                        "date_of_birth": "Datum narození nesmí pro podnikající fyzické osoby být definováno."
                    }
                )

        if cleaned_data.get("entity_type") == "legal_entity":
            if cleaned_data.get("ico_number") is None:
                raise ValidationError(
                    {"ico_number": "IČO musí být pro právnické osoby definováno."}
                )

            if cleaned_data.get("date_of_birth") is not None:
                raise ValidationError(
                    {
                        "date_of_birth": "Datum narození nesmí pro právnické osoby být definováno."
                    }
                )

        return cleaned_data