import json

from account.forms import AccountSelect
from category.forms import CategorySelect
from django import forms
from django.utils.translation import gettext_lazy as _
from main.forms import DatalistInput, NummiFileInput, NummiForm
from statement.forms import StatementSelect

from .models import Invoice, Transaction
from .utils import get_datalist


class TransactionForm(NummiForm):
    class Meta:
        model = Transaction
        fields = [
            "statement",
            "name",
            "value",
            "date",
            "real_date",
            "category",
            "trader",
            "payment",
            "description",
        ]
        widgets = {
            "statement": StatementSelect(),
            "category": CategorySelect(),
            "name": DatalistInput(),
            "trader": DatalistInput(),
            "payment": DatalistInput(),
        }

    meta_fieldsets = [
        [
            ["statement"],
            ["name"],
            ["value"],
            [
                "date",
                "real_date",
            ],
            ["category"],
            ["trader", "payment"],
        ],
        [["description"]],
    ]

    def __init__(self, *args, **kwargs):
        _user = kwargs.pop("user")
        _disable_statement = kwargs.pop("disable_statement", False)
        _autocomplete = kwargs.pop("autocomplete", False)
        super().__init__(*args, **kwargs)

        self.fields["category"].queryset = self.fields["category"].queryset.filter(
            user=_user
        )
        self.fields["statement"].queryset = self.fields["statement"].queryset.filter(
            user=_user
        )

        self.fields["name"].widget.options = get_datalist(_user, "name")
        self.fields["trader"].widget.options = get_datalist(_user, "trader")
        self.fields["payment"].widget.options = get_datalist(_user, "payment")

        self.fields["category"].widget.attrs |= {
            "class": "category",
            "data-icons": json.dumps(
                {
                    str(cat.id): cat.icon
                    for cat in self.fields["category"].queryset.only("id", "icon")
                }
            ),
        }

        if _autocomplete:
            self.autocomplete = {
                "field": "name",
                "data": {
                    t.name: [
                        {
                            "field": "value",
                            "value": t.value,
                        },
                        {
                            "field": "category",
                            "value": t.category.id if t.category else "",
                        },
                        {
                            "field": "trader",
                            "value": t.trader,
                        },
                        {
                            "field": "payment",
                            "value": t.payment,
                        },
                    ]
                    for t in _user.transaction_set.order_by("name", "-date").distinct(
                        "name"
                    )
                },
            }

        if _disable_statement:
            self.fields["statement"].disabled = True
            self.fields["statement"].widget.attrs["hidden"] = True


class InvoiceForm(NummiForm):
    prefix = "invoice"

    class Meta:
        model = Invoice
        fields = [
            "name",
            "file",
        ]
        widgets = {
            "file": NummiFileInput,
        }


class MultipleFileInput(forms.ClearableFileInput):
    allow_multiple_selected = True


class MultipleFileField(forms.FileField):
    def __init__(self, *args, **kwargs):
        kwargs.setdefault("widget", MultipleFileInput())
        super().__init__(*args, **kwargs)

    def clean(self, data, initial=None):
        single_file_clean = super().clean
        if isinstance(data, (list, tuple)):
            result = [single_file_clean(d, initial) for d in data]
        else:
            result = single_file_clean(data, initial)
        return result


class MultipleInvoicesForm(forms.Form):
    prefix = "invoices"
    invoices = MultipleFileField()


class DateInput(forms.DateInput):
    input_type = "date"

    def __init__(self, attrs=None):
        super().__init__(attrs)
        self.format = "%Y-%m-%d"


class DateField(forms.DateField):
    def __init__(self, *args, **kwargs):
        kwargs.setdefault("widget", DateInput())
        super().__init__(*args, **kwargs)


class TransactionFiltersForm(forms.Form):
    start_date = DateField(required=False)
    end_date = DateField(required=False)
    category = forms.ModelChoiceField(
        queryset=None, required=False, widget=CategorySelect()
    )
    account = forms.ModelChoiceField(
        queryset=None, required=False, widget=AccountSelect()
    )
    statement = forms.ModelChoiceField(queryset=None, required=False)
    search = forms.CharField(label=_("Search"), required=False)
    sort_by = forms.ChoiceField(
        label=_("Sort by"),
        choices=[
            ("", _("Default")),
            ("date", _("Date +")),
            ("-date", _("Date -")),
            ("value", _("Value +")),
            ("-value", _("Value -")),
        ],
        required=False,
    )

    def __init__(self, *args, **kwargs):
        _user = kwargs.pop("user")
        super().__init__(*args, **kwargs)

        self.fields["category"].queryset = _user.category_set
        self.fields["account"].queryset = _user.account_set

        if acc_id := kwargs.get("initial", {}).get("account"):
            self.fields["statement"].queryset = (
                self.fields["account"].queryset.get(id=acc_id).statement_set
            )
        else:
            self.fields["statement"].queryset = _user.statement_set.none()
            self.fields["statement"].disabled = True

        self.fields["category"].widget.attrs |= {
            "class": "category",
            "data-icons": json.dumps(
                {
                    str(cat.id): cat.icon
                    for cat in self.fields["category"].queryset.only("id", "icon")
                }
            ),
        }
        self.fields["account"].widget.attrs |= {
            "class": "account",
            "data-icons": json.dumps(
                {
                    str(acc.id): acc.icon
                    for acc in self.fields["account"].queryset.only("id", "icon")
                }
            ),
        }
