from django.shortcuts import get_object_or_404
from django.views.generic import DetailView, ListView, TemplateView

from .models import INSTALLABLE_PLATFORM_SPECS, MainProduct, SubProduct


def _featured_version(qs):
    ordered = qs.order_by("order", "pk")
    cand = ordered.filter(is_featured_stable=True).first()
    return cand if cand else ordered.first()


def _install_specs_from_versions(version_list):
    present = set()
    for ver in version_list:
        for field_name, *_ in INSTALLABLE_PLATFORM_SPECS:
            if (getattr(ver, field_name) or "").strip():
                present.add(field_name)
    return tuple(s for s in INSTALLABLE_PLATFORM_SPECS if s[0] in present)


class ProductOverviewView(ListView):
    model = MainProduct
    template_name = "products/overview.html"
    context_object_name = "main_products"
    queryset = MainProduct.objects.filter(is_active=True).prefetch_related(
        "sub_products"
    )


class MainProductDetailView(DetailView):
    model = MainProduct
    template_name = "products/main_detail.html"
    context_object_name = "main_product"
    slug_url_kwarg = "main_slug"
    queryset = MainProduct.objects.filter(is_active=True).prefetch_related(
        "sub_products"
    )


class SubProductDetailView(TemplateView):
    template_name = "products/sub_detail.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        main_product = get_object_or_404(
            MainProduct,
            slug=self.kwargs["main_slug"],
            is_active=True,
        )
        sub_product = get_object_or_404(
            SubProduct,
            slug=self.kwargs["sub_slug"],
            main_product=main_product,
            is_active=True,
        )
        context["main_product"] = main_product
        context["sub_product"] = sub_product
        context["articles"] = sub_product.articles.prefetch_related("sections").all()
        context["siblings"] = (
            SubProduct.objects.filter(main_product=main_product, is_active=True)
            .exclude(pk=sub_product.pk)
            .order_by("order", "name")
        )

        active_versions = sub_product.versions.filter(is_active=True)

        context["distribution_installable"] = (
            sub_product.distribution == SubProduct.DISTRIBUTION_INSTALLABLE
        )
        context["distribution_package"] = (
            sub_product.distribution == SubProduct.DISTRIBUTION_PACKAGE
        )
        context["show_releases_section"] = False
        context["featured_version"] = None
        context["featured_install_cells"] = []
        context["show_older_versions_link"] = False
        context["package_versions"] = []

        if sub_product.distribution == SubProduct.DISTRIBUTION_INSTALLABLE:
            featured = _featured_version(active_versions)
            if (
                featured
                and not featured.has_any_install_asset()
                and not (featured.package_resource_url or "").strip()
            ):
                for cand in active_versions.exclude(pk=featured.pk).order_by("order", "pk"):
                    if cand.has_any_install_asset() or (cand.package_resource_url or "").strip():
                        featured = cand
                        break
            context["featured_version"] = featured
            if featured and (
                featured.has_any_install_asset()
                or (featured.package_resource_url or "").strip()
            ):
                if featured.has_any_install_asset():
                    specs = _install_specs_from_versions([featured])
                    context["featured_install_cells"] = featured.install_urls_for_specs(specs)
                context["show_releases_section"] = True
            older_list = list(
                active_versions.exclude(pk=featured.pk).order_by("order", "pk")
                if featured else active_versions.order_by("order", "pk")
            )
            context["show_older_versions_link"] = len(older_list) > 0

        elif sub_product.distribution == SubProduct.DISTRIBUTION_PACKAGE:
            pkg_versions = list(active_versions.order_by("order", "pk"))
            context["package_versions"] = pkg_versions
            context["show_releases_section"] = len(pkg_versions) > 0

        return context


class SubProductOlderVersionsView(TemplateView):
    template_name = "products/sub_versions.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        main_product = get_object_or_404(
            MainProduct,
            slug=self.kwargs["main_slug"],
            is_active=True,
        )
        sub_product = get_object_or_404(
            SubProduct,
            slug=self.kwargs["sub_slug"],
            main_product=main_product,
            is_active=True,
        )
        active_versions = sub_product.versions.filter(is_active=True)
        featured = _featured_version(active_versions)
        archive = list(
            active_versions.exclude(pk=featured.pk).order_by("order", "pk")
            if featured
            else active_versions.order_by("order", "pk")
        )
        context["main_product"] = main_product
        context["sub_product"] = sub_product
        context["featured_version"] = featured
        context["archive_versions"] = archive

        if sub_product.distribution == SubProduct.DISTRIBUTION_INSTALLABLE:
            specs = _install_specs_from_versions(archive)
            context["archive_specs"] = specs
            archive_rows_installable = []
            for ver in archive:
                cells = []
                for field_name, label, icon in specs:
                    u = getattr(ver, field_name, "") or ""
                    u = u.strip()
                    cells.append(
                        {"field": field_name, "label": label, "icon": icon, "url": u}
                    )
                archive_rows_installable.append(
                    {"version_obj": ver, "cells": cells}
                )
            context["archive_rows_installable"] = archive_rows_installable
            context["archive_rows_package"] = False
            context["distribution_installable"] = True
            context["distribution_package"] = False
        else:
            context["archive_specs"] = ()
            context["archive_rows_installable"] = []
            context["archive_rows_package"] = True
            context["distribution_installable"] = False
            context["distribution_package"] = True
        return context
