import random

from django.contrib.auth.mixins import UserPassesTestMixin
from django.urls import reverse

from aircox.forms import ProgramForm
from aircox.models import Article, Episode, Page, Program, StaticPage
from .mixins import ParentMixin
from .page import PageDetailView, PageListView, PageUpdateView

__all__ = ["ProgramPageDetailView", "ProgramDetailView", "ProgramPageListView"]


class BaseProgramMixin:
    def get_program(self):
        return self.object

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


class ProgramDetailView(BaseProgramMixin, PageDetailView):
    model = Program

    def get_related_queryset(self):
        queryset = (
            self.get_queryset()
            .filter(category_id=self.object.category_id)
            .exclude(pk=self.object.pk)
            .published()
            .order_by("-pub_date")[:50]
        )
        return random.sample(list(queryset), min(len(queryset), self.related_count))

    def get_related_url(self):
        return reverse("program-list") + f"?category__id={self.object.category_id}"

    def get_context_data(self, **kwargs):
        episodes = Episode.objects.program(self.object).published().order_by("-pub_date")
        podcasts = episodes.with_podcasts()
        articles = Article.objects.parent(self.object).published().order_by("-pub_date")
        return super().get_context_data(
            articles=articles[: self.related_count],
            episodes=episodes[: self.related_count],
            podcasts=podcasts[: self.related_count],
            **kwargs,
        )

    def get_template_names(self):
        return super().get_template_names() + ["aircox/program_detail.html"]


class ProgramUpdateView(UserPassesTestMixin, BaseProgramMixin, PageUpdateView):
    model = Program
    form_class = ProgramForm

    def test_func(self):
        program = self.get_object()
        return self.request.user.has_perm("aircox.%s" % program.change_permission_codename)

    def get_success_url(self):
        return reverse("program-detail", kwargs={"slug": self.get_object().slug})


class ProgramListView(PageListView):
    model = Program
    attach_to_value = StaticPage.Target.PROGRAMS

    def get_queryset(self):
        return super().get_queryset().order_by("title")


# FIXME: not used
class ProgramPageDetailView(BaseProgramMixin, ParentMixin, PageDetailView):
    """Base view class for a page that is displayed as a program's child
    page."""

    parent_model = Program

    def get_program(self):
        self.parent = self.object.program
        return self.object.program


class ProgramPageListView(BaseProgramMixin, PageListView):
    model = Page
    parent_model = Program
    queryset = Page.objects.select_subclasses()

    def get_program(self):
        return self.parent
