"""
dynamic_fields/forms.py
"""

from django import forms
from django.utils.translation import gettext_lazy as _

from base.forms import ModelForm
from dynamic_fields import models
from dynamic_fields.df_not_allowed_models import DF_NOT_ALLOWED_MODELS
from dynamic_fields.models import DynamicField
from horilla.horilla_middlewares import _thread_locals


class DynamicFieldForm(ModelForm):
    """
    DynamicFieldForm
    """

    display_title = _("Add Field")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.instance.pk:
            self.fields = {
                "verbose_name": self.fields["verbose_name"],
                "is_required": self.fields["is_required"],
            }

    class Meta:
        """
        Meta class for additional options
        """

        model = models.DynamicField
        fields = "__all__"
        exclude = [
            "model",
            "remove_column",
            "choices",
        ]


class ChoiceForm(ModelForm):
    """
    ChoiceForm
    """

    class Meta:
        """
        Meta class for additional option
        """

        model = models.Choice
        fields = "__all__"


og_init = forms.ModelForm.__init__
og_get_item = forms.ModelForm.__getitem__


class AddFieldWidget(forms.Widget):
    """
    Widget to add DynamicFields
    """

    template_name = "dynamic_fields/add_df.html"

    def __init__(self, attrs=None, form=None):
        self.form = form
        super().__init__(attrs)

    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        context["form"] = self.form
        return context


class DFWidget(forms.Widget):
    """
    DFWidget
    """

    template_name = "dynamic_fields/df.html"

    def __init__(self, attrs=None, form=None):
        self.form = form
        super().__init__(attrs)

    def get_context(self, name, value, attrs):
        context = super().get_context(name, value, attrs)
        context["form"] = self.form
        return context


def get_item_override(self: forms.ModelForm, name):
    """Return a custom BoundField."""
    if name not in self.removed_hdf:
        result = og_get_item(self, name)
        return result


def init_override(self: forms.ModelForm, *args, **kwargs):
    """
    Method to override the ModelForm actual __init__ method
    """
    model: models.Model = self._meta.model
    model_path = f"{model.__module__}.{model.__name__}"
    removed_fields = DynamicField.objects.filter(
        model=model_path, remove_column=True
    ).values_list("field_name", flat=True)
    self.removed_hdf = removed_fields
    og_init(self, *args, **kwargs)
    for df in removed_fields:
        if df in self.fields.keys():
            del self.fields[df]
    other_df = DynamicField.objects.filter(model=model_path, remove_column=False)
    for df in other_df:
        if df not in self.fields:
            form_field = df.get_field().formfield()
            form_field.widget = DFWidget(attrs=form_field.widget.attrs, form=self)
            attrs = form_field.widget.attrs
            attrs["pk"] = df.pk
            attrs["class"] = attrs.get("class", "") + "oh-input w-100"
            if df.type == "2":
                attrs["type"] = "number"
            elif df.type == "3":
                attrs["type"] = "text_area"
                attrs["cols"] = "40"
                attrs["rows"] = "2"
            elif df.type == "4":
                attrs["type"] = "date"
            elif df.type == "5":
                attrs["type"] = "file"
            self.fields[df.field_name] = form_field
            if self._meta.fields is not None:
                self._meta.fields.append(df.field_name)

    request = getattr(_thread_locals, "request")
    if (
        # self._meta.model in DF_ALLOWED_MODELS and
        self._meta.model not in DF_NOT_ALLOWED_MODELS
        and request.user.has_perm("dynamic_fields.add_dynamicfield")
    ):
        self.df_user_has_change_perm = request.user.has_perm(
            "dynamic_fields.change_dynamicfield"
        )
        self.df_user_has_delete_perm = request.user.has_perm(
            "dynamic_fields.delete_dynamicfield"
        )
        self.fields["add_df"] = forms.CharField(
            label="Add field",
            widget=AddFieldWidget(
                form=self,
            ),
            required=False,
        )
        self.df_form_model_path = model_path


forms.ModelForm.__init__ = init_override
forms.ModelForm.__getitem__ = get_item_override
