from django.contrib import messages
from django.forms import ValidationError
from django.shortcuts import get_object_or_404
from django.urls import reverse_lazy
from django.utils.html import format_html
from django.utils.translation import gettext as _
from django.views.generic.edit import FormView
from main.views import (
    NummiCreateView,
    NummiDeleteView,
    NummiDetailView,
    NummiListView,
    NummiUpdateView,
)

from .forms import (
    InvoiceForm,
    MultipleInvoicesForm,
    TransactionFiltersForm,
    TransactionForm,
)
from .models import Invoice, Transaction


class TransactionCreateView(NummiCreateView):
    model = Transaction
    form_class = TransactionForm

    def get_initial(self):
        initial = super().get_initial()
        if "statement" in self.kwargs:
            initial["statement"] = get_object_or_404(
                self.request.user.statement_set, pk=self.kwargs["statement"]
            )
            if (
                last_transaction := initial["statement"]
                .transaction_set.order_by("-date")
                .first()
            ):
                initial["date"] = last_transaction.date

        return initial

    def get_form_kwargs(self):
        form_kwargs = super().get_form_kwargs()
        if "statement" in self.kwargs:
            form_kwargs["disable_statement"] = True

        form_kwargs["autocomplete"] = True
        return form_kwargs


class InvoiceCreateView(NummiCreateView):
    model = Invoice
    form_class = InvoiceForm

    def form_valid(self, form):
        form.instance.transaction = get_object_or_404(
            Transaction.objects.filter(user=self.request.user),
            pk=self.kwargs["transaction"],
        )
        return super().form_valid(form)

    def get_success_url(self):
        return reverse_lazy("transaction", args=(self.object.transaction.pk,))


class MultipleInvoiceCreateView(FormView):
    form_class = MultipleInvoicesForm

    def form_valid(self, form):
        transaction = get_object_or_404(
            self.request.user.transaction_set, pk=self.kwargs["transaction"]
        )

        for file in form.cleaned_data["invoices"]:
            invoice = Invoice(
                transaction=transaction,
                user=self.request.user,
                file=file,
                name=file.name.split(".", 1)[0],
            )
            try:
                invoice.full_clean()
                invoice.save()
            except ValidationError as err:
                for msg in err.messages:
                    messages.error(
                        self.request,
                        format_html(
                            "{msg} {file}. {err}",
                            msg=_("Error processing file"),
                            file=file.name,
                            err=msg,
                        ),
                    )

        return super().form_valid(form)

    def get_success_url(self):
        return reverse_lazy("transaction", args=(self.kwargs["transaction"],))


class TransactionUpdateView(NummiUpdateView):
    model = Transaction
    form_class = TransactionForm
    pk_url_kwarg = "transaction"


class TransactionDetailView(NummiDetailView):
    model = Transaction
    pk_url_kwarg = "transaction"
    context_object_name = "transaction"

    def get_context_data(self, **kwargs):
        data = super().get_context_data(**kwargs)
        data["invoices_form"] = MultipleInvoicesForm()
        return data


class InvoiceUpdateView(NummiUpdateView):
    model = Invoice
    form_class = InvoiceForm
    pk_url_kwarg = "invoice"

    def get_success_url(self):
        return reverse_lazy("transaction", args=(self.object.transaction.pk,))

    def get_queryset(self):
        return (
            super()
            .get_queryset()
            .filter(
                transaction=get_object_or_404(
                    Transaction, pk=self.kwargs["transaction"]
                )
            )
        )


class TransactionDeleteView(NummiDeleteView):
    model = Transaction
    pk_url_kwarg = "transaction"


class InvoiceDeleteView(NummiDeleteView):
    model = Invoice
    pk_url_kwarg = "invoice"

    def get_success_url(self):
        return reverse_lazy("transaction", args=(self.object.transaction.pk,))

    def get_queryset(self):
        return (
            super()
            .get_queryset()
            .filter(
                transaction=get_object_or_404(
                    Transaction, pk=self.kwargs["transaction"]
                )
            )
        )


class TransactionListView(NummiListView):
    model = Transaction
    context_object_name = "transactions"
    paginate_by = 32

    def get_queryset(self, **kwargs):
        queryset = super().get_queryset(**kwargs)

        if date := self.request.GET.get("start_date"):
            queryset = queryset.filter(date__gte=date)
        if date := self.request.GET.get("end_date"):
            queryset = queryset.filter(date__lte=date)
        if category := self.request.GET.get("category"):
            queryset = queryset.filter(category=category)
        if account := self.request.GET.get("account"):
            queryset = queryset.filter(statement__account=account)
            if statement := self.request.GET.get("statement"):
                queryset = queryset.filter(statement=statement)
        if search := self.request.GET.get("search"):
            queryset = queryset.search(search)
        if sort_by := self.request.GET.get("sort_by"):
            queryset = queryset.order_by(sort_by)

        return queryset

    def get_context_data(self, **kwargs):
        data = super().get_context_data(**kwargs)

        filters = self.request.GET.copy()
        filters.pop("page", None)
        if filters:
            data["filters"] = True
        data["filter_form"] = TransactionFiltersForm(
            initial=filters, user=self.request.user
        )
        return data
