from django.forms.renderers import TemplatesSetting
from django.forms.widgets import Textarea


def inject_class(f, class_name):
    def inner(*args, **kwargs):
        result = f(*args, **kwargs)
        class_list = result.get("class", "")
        class_list = f"{class_list} {class_name}".strip()
        result["class"] = class_list
        return result

    return inner


class VerticalFormRenderer(TemplatesSetting):
    form_template_name = "frontend/forms/form.html"
    field_template_name = "frontend/forms/vertical_field.html"

    def get_class_names(self, field):
        input_type = self.get_field_input_type(field)
        errors = "is-invalid " if field.errors else ""
        if input_type == "radio":
            return f"{errors}form-check-input"
        if input_type == "checkbox":
            return f"{errors}form-check-input"
        return f"{errors}form-control"

    def get_widget_input_type(self, widget):
        if isinstance(widget, Textarea):
            return "textarea"
        return getattr(widget, "input_type", None)

    def get_field_input_type(self, field):
        widget = field.field.widget
        if inner_widget := getattr(widget, "widget", None):
            widget = inner_widget
        return self.get_widget_input_type(widget)

    def render(self, template_name, context, request=None):
        if field := context.get("field"):
            field.build_widget_attrs = inject_class(
                field.build_widget_attrs, self.get_class_names(field)
            )
        return super().render(template_name, context, request)


class InlineFormRenderer(VerticalFormRenderer):
    form_template_name = "frontend/forms/form.html"
    field_template_name = "frontend/forms/inline_field.html"
