from django.shortcuts import redirect
from django.views.generic.base import TemplateView
from django.shortcuts import get_object_or_404
from oscar.core.loading import get_model, get_class

from ocyan.core.fender import config
from ocyan.plugin.oscar.pipeline import PIPELINE_STATUS_PAID, PIPELINE_STATUS_CANCELLED, PIPELINE_STATUS_PENDING_PAYMENT
from ocyan.plugin.oscar.utils import create_payment_events, create_or_record_payment_events, record_payment_events
from ocyan.plugin.payment_invoice.constants import APP_CODE


Order = get_model("order", "Order")
EventHandler = get_class("order.processing", "EventHandler")
PaymentEvent = get_model("order", "PaymentEvent")
PaymentEventType = get_model("order", "PaymentEventType")
Source = get_model("payment", "Source")
SourceType = get_model("payment", "SourceType")


class InvoicePaymentView(TemplateView):
    method = None

    def get_template_names(self):
        return ["oscar/payment/invoice/%s.html" % self.method]

    def get_context_data(self, **kwargs):
        return {
            "help_text": config.get("ocyan_invoice_payment_plugin", "help_text", ""),
            "order": get_object_or_404(
                Order, pk=self.request.session.get("checkout_order_id")
            ),
        }

    def get(self, request, *args, **kwargs):
        order = get_object_or_404(
            Order, pk=self.request.session.get("checkout_order_id")
        )
        create_or_record_payment_events(
            order=order,
            event_type=PIPELINE_STATUS_PENDING_PAYMENT,
            description="invoice payment",
            reference="invoice payment"
        )

        if config.get("ocyan_invoice_payment_plugin", "skip_confirmation_view", False):
            return self.post(request)
        else:
            return super().get(request, args, kwargs)

    def post(self, request):
        order = get_object_or_404(
            Order, pk=self.request.session.get("checkout_order_id")
        )
        if request.POST.get("_try-again"):
            create_payment_events(
                order=order,
                event_type=PIPELINE_STATUS_CANCELLED,
                reference="invoice payment"
            )
            return redirect("checkout:try-again")

        reference = order.number
        source_type = SourceType.objects.get(code="%s:%s" % (APP_CODE, self.method))
        source, _ = Source.objects.get_or_create(
            order=order,
            source_type=source_type,
            reference=reference,
            defaults={"amount_allocated": order.total_incl_tax},
        )
        # declare source to be paid in full immediately
        source.debit(reference=reference, status=PIPELINE_STATUS_PAID)

        record_payment_events(
            order=order,
            order_status=PIPELINE_STATUS_PAID,
            payment_status=PIPELINE_STATUS_PAID,
            description="invoice payment",
            reference="invoice payment"
        )
        return redirect("checkout:thank-you")
