from django.forms import SelectMultiple, widgets
from django.urls import reverse
from django.utils.translation import gettext_lazy as _


class TomSelect(widgets.Select):
    def __init__(
        self,
        attrs=None,
        remove_button=False,
        remove_button_text=_("Remove"),
        create=False,
        create_text=_("Add"),
        clear_button=True,
        clear_text=_("Clear"),
        no_results_text=_("No results..."),
        checkboxes=False,
        group_by=None,
        *args,
        **kwargs,
    ):
        super().__init__(attrs, *args, **kwargs)
        self.remove_button = remove_button
        self.remove_button_text = remove_button_text
        self.clear_button = clear_button
        self.create = create
        self.create_text = create_text
        self.clear_text = clear_text
        self.no_results_text = no_results_text
        self.checkboxes = checkboxes
        self.group_by = group_by

    def build_attrs(self, base_attrs, extra_attrs=None):
        attrs = super().build_attrs(base_attrs, extra_attrs)

        attrs["data-txt-no-results"] = self.no_results_text

        if self.remove_button:
            attrs["data-remove-button"] = "true"
            attrs["data-txt-remove"] = self.remove_button_text

        if self.create:
            attrs["data-create"] = "true"
            attrs["data-txt-create"] = self.create_text

        if self.clear_button:
            attrs["data-clear-button"] = "true"
            attrs["data-txt-clear"] = self.clear_text

        if self.checkboxes:
            attrs["data-checkboxes"] = "true"

        return attrs

    def optgroups(self, name, value, attrs=None):
        if not self.group_by:
            # If no group_by is set, return all options as a single list without optgroups
            return [
                (
                    None,
                    [
                        self.create_option(
                            name,
                            option_value,
                            option_label,
                            (str(option_value) in value),
                            index,
                            subindex=None,
                            attrs=attrs,
                        )
                        for index, (option_value, option_label) in enumerate(
                            self.choices
                        )
                    ],
                    0,
                )
            ]

        groups = {}
        has_selected = False
        value = set(value) if value else set()

        for index, (option_value, option_label) in enumerate(self.choices):
            if option_value is None:
                option_value = ""

            # Determine the group key
            if hasattr(option_value, "instance") and hasattr(
                option_value.instance, self.group_by
            ):
                group_key = getattr(option_value.instance, self.group_by) or _(
                    "Ungrouped"
                )
            else:
                group_key = _("Ungrouped")

            group_name = str(group_key) if group_key is not None else None

            if isinstance(option_label, (list, tuple)):
                choices = option_label
            else:
                choices = [(option_value, option_label)]

            if group_name not in groups:
                groups[group_name] = []

            for subvalue, sublabel in choices:
                selected = (not has_selected or self.allow_multiple_selected) and str(
                    subvalue
                ) in value
                has_selected |= selected
                groups[group_name].append(
                    self.create_option(
                        name,
                        subvalue,
                        sublabel,
                        selected,
                        index,
                        subindex=None,
                        attrs=attrs,
                    )
                )

        optgroups = []
        for group_name, subgroup in groups.items():
            optgroups.append((group_name, subgroup, 0))

        return optgroups


class TomSelectMultiple(SelectMultiple, TomSelect):
    pass


class TransactionSelect(TomSelect):
    def __init__(self, income: bool = True, expense: bool = True, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.load_income = income
        self.load_expense = expense
        self.create = False

    def build_attrs(self, base_attrs, extra_attrs=None):
        attrs = super().build_attrs(base_attrs, extra_attrs)

        if self.load_income and self.load_expense:
            attrs["data-load"] = reverse("transactions_search")
        elif self.load_income and not self.load_expense:
            attrs["data-load"] = reverse(
                "transactions_search", kwargs={"filter_type": "income"}
            )
        elif self.load_expense and not self.load_income:
            attrs["data-load"] = reverse(
                "transactions_search", kwargs={"filter_type": "expenses"}
            )

        return attrs
