from django.utils.functional import cached_property
from django.views.generic import DetailView, ListView

from servala.core.models import Service, ServiceOffering, ServiceOfferingControlPlane
from servala.frontend.forms.service import ControlPlaneSelectForm, ServiceFilterForm
from servala.frontend.views.mixins import HtmxViewMixin, OrganizationViewMixin


class ServiceListView(OrganizationViewMixin, ListView):
    """View to display all available services for an organization."""

    template_name = "frontend/organizations/services.html"
    context_object_name = "services"
    model = Service
    permission_type = "view"

    def get_queryset(self):
        """Return all services."""
        services = Service.objects.all().select_related("category")
        if self.filter_form.is_valid():
            services = self.filter_form.filter_queryset(services)
        return services

    @cached_property
    def filter_form(self):
        return ServiceFilterForm(data=self.request.GET or None)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["filter_form"] = self.filter_form
        return context


class ServiceDetailView(OrganizationViewMixin, DetailView):
    template_name = "frontend/organizations/service_detail.html"
    context_object_name = "service"
    model = Service
    permission_type = "view"

    def get_queryset(self):
        return Service.objects.select_related("category").prefetch_related(
            "offerings",
            "offerings__provider",
        )


class ServiceOfferingDetailView(OrganizationViewMixin, HtmxViewMixin, DetailView):
    template_name = "frontend/organizations/service_offering_detail.html"
    context_object_name = "offering"
    model = ServiceOffering
    permission_type = "view"
    fragments = ("service-form",)

    def has_permission(self):
        return self.has_organization_permission()

    def get_queryset(self):
        return ServiceOffering.objects.all().select_related(
            "service", "service__category", "provider"
        )

    @cached_property
    def planes(self):
        return self.object.control_planes.all()

    @cached_property
    def select_form(self):
        data = None
        if "control_plane" in self.request.GET:
            data = self.request.GET
        return ControlPlaneSelectForm(data=data, planes=self.planes)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["select_form"] = self.select_form
        if "control_plane" in self.request.GET:
            if self.select_form.is_valid():
                try:
                    so_cp = ServiceOfferingControlPlane.objects.filter(
                        control_plane=self.select_form.cleaned_data["control_plane"],
                        service_offering=self.object,
                    ).first()
                    if not so_cp:
                        context["form_error"] = True
                except Exception:
                    context["form_error"] = True
                else:
                    context["service_form"] = so_cp.model_form_class()
        return context
