from typing import Any

from crispy_forms.helper import FormHelper
from crispy_forms.layout import (
    Layout,
    Field,
)
from crispy_forms.bootstrap import StrictButton

from django import forms
from django.urls import reverse
from django.urls.exceptions import NoReverseMatch
from django.utils.translation import gettext_lazy as tr
from django.utils.text import format_lazy

from .fields import (
    LCChoiceField,
    DateRangeFilterField,
)
from .forms import LCFormBase

SearchButton = StrictButton(
    format_lazy(
        '<span class="fas fa-search" aria-hidden="true"></span>'
        '<span class="sr-only">{search}</span>',
        search=tr('Search'),
    ),
    type='submit',
    name="submit",
    value="submit",
    css_class="btn-sm btn-primary ml-2",
)


# -------------------------------------------------------------------------
class Select2FilterForm(LCFormBase):
    term = forms.CharField(widget=forms.TextInput, required=False, label='')

    def is_valid(self) -> bool:
        # convert "term" to "name" for use in queryset params
        valid = super().is_valid()
        if valid:
            self.cleaned_data['name'] = self.cleaned_data.pop('term')
        return valid


# -------------------------------------------------------------------------
class NameFilterForm(LCFormBase):
    STATUS = (
        ('active', tr('Active')),
        ('inactive', tr('Inactive')),
    )

    name = forms.CharField(widget=forms.TextInput, required=False, label='')
    status = LCChoiceField(
        choices=STATUS,
        required=False,
        label='',
        field_attrs={'data-placeholder': tr('Status')},
    )

    def insert_fields(self, field_list: list) -> None:
        """Insert fields at the beginning. Mostly for date fields"""
        for field in field_list:
            self.helper.layout[0].insert(0, field)

    def add_fields(self, field_list: list) -> None:
        """Pop buttons off the end of the list, extend new fields, and reinsert buttons"""
        if isinstance(self.helper.layout[0][-1], StrictButton):
            self.helper.layout[0].pop(-1)
        if self.show_buttons:
            field_list.extend([SearchButton])
        self.helper.layout[0].extend(field_list)

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        action = kwargs.pop('action', '')
        try:
            self.action = reverse(action)
        except NoReverseMatch:
            self.action = action
        self.show_buttons = kwargs.pop('show_buttons', True)
        self.hide_fields = kwargs.pop('hide_fields', ['status'])

        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_id = 'search_form'
        self.helper.form_class = 'form-inline'
        self.helper.form_method = 'get'
        self.helper.attrs = {'role': 'search'}
        self.helper.form_action = self.action
        self.helper.layout = Layout(
            Field(
                'name',
                placeholder=tr('Search by Name'),
                autocomplete='off',
                autofocus="autofocus",
                css_class='me-2',
            ),
            Field(
                'status',
                placeholder=tr('Status'),
                css_class='me-2',
            ),
        )
        for field in self.hide_fields:
            self.fields[field].widget = forms.HiddenInput()


# -------------------------------------------------------------------------
class DateFilterForm(NameFilterForm):
    date_range = DateRangeFilterField(required=False, label='')

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, **kwargs)
        self.insert_fields([
            Field(
                'date_range',
                placeholder=tr('Date Range'),
                css_class='me-2',
            ),
        ])


__all__ = (
    'DateFilterForm',
    'NameFilterForm',
    'SearchButton',
    'Select2FilterForm',
)
