import datetime

from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.utils import timezone
from django.views import generic
from scrobbles.models import Scrobble
from videos.models import Channel, Series, Video
from scrobbles.views import (
    ScrobbleableListView,
    ScrobbleableDetailView,
    ChartContextMixin,
)


class MovieListView(LoginRequiredMixin, generic.ListView):
    model = Video
    template_name = "videos/movie_list.html"

    def get_queryset(self):
        return Video.objects.filter(video_type=Video.VideoType.MOVIE)


class SeriesListView(LoginRequiredMixin, generic.ListView):
    model = Series


class SeriesDetailView(LoginRequiredMixin, ChartContextMixin, generic.DetailView):
    model = Series
    slug_field = "uuid"

    def get_context_data(self, **kwargs):
        user_id = self.request.user.id
        context_data = super().get_context_data(**kwargs)

        context_data["scrobbles"] = self.object.scrobbles_for_user(user_id)
        next_episode_id = ""
        if self.object.last_scrobbled_episode(user_id):
            next_episode_id = (
                self.object.last_scrobbled_episode(user_id).next_imdb_id or ""
            )
        if self.object.is_episode_playing(user_id):
            next_episode_id = ""
        if next_episode_id:
            context_data["next_episode_id"] = next_episode_id
        return context_data


class ChannelDetailView(LoginRequiredMixin, ChartContextMixin, generic.DetailView):
    model = Channel
    slug_field = "uuid"
    template_name = "videos/channel_detail.html"
    paginate_by = 50

    def get_context_data(self, **kwargs):
        user_id = self.request.user.id
        context_data = super().get_context_data(**kwargs)

        scrobbles = self.object.scrobbles_for_user(user_id)
        paginator = Paginator(scrobbles, self.paginate_by)
        page_number = self.request.GET.get("page")

        try:
            page_obj = paginator.page(page_number)
        except PageNotAnInteger:
            page_obj = paginator.page(1)
        except EmptyPage:
            page_obj = paginator.page(paginator.num_pages)

        context_data["page_obj"] = page_obj
        context_data["scrobbles"] = page_obj.object_list
        context_data["is_paginated"] = paginator.num_pages > 1

        return context_data


class VideoListView(ScrobbleableListView):
    model = Video

    def get_context_data(self, **kwargs):
        context_data = super().get_context_data(**kwargs)
        user = self.request.user
        now = timezone.now()
        start_day_of_week = now - datetime.timedelta(days=now.weekday())
        start_day_of_month = now.replace(day=1)

        movie_scrobbles = Scrobble.objects.filter(
            user=user,
            video__video_type=Video.VideoType.MOVIE,
            played_to_completion=True,
        )
        context_data["videos_this_week"] = movie_scrobbles.filter(
            timestamp__gte=start_day_of_week
        ).order_by("-timestamp")
        context_data["videos_this_month"] = movie_scrobbles.filter(
            timestamp__gte=start_day_of_month
        ).order_by("-timestamp")

        youtube_scrobbles_this_week = Scrobble.objects.filter(
            user=user,
            video__video_type=Video.VideoType.YOUTUBE,
            video__channel__isnull=False,
            timestamp__gte=start_day_of_week,
        ).select_related("video", "video__channel")

        youtube_scrobbles_this_month = Scrobble.objects.filter(
            user=user,
            video__video_type=Video.VideoType.YOUTUBE,
            video__channel__isnull=False,
            timestamp__gte=start_day_of_month,
        ).select_related("video", "video__channel")

        channels_this_week = {}
        for scrobble in youtube_scrobbles_this_week:
            channel = scrobble.video.channel
            if channel:
                channels_this_week[channel.id] = {
                    "channel": channel,
                    "count": channels_this_week.get(channel.id, {}).get("count", 0) + 1,
                }

        channels_this_month = {}
        for scrobble in youtube_scrobbles_this_month:
            channel = scrobble.video.channel
            if channel:
                channels_this_month[channel.id] = {
                    "channel": channel,
                    "count": channels_this_month.get(channel.id, {}).get("count", 0)
                    + 1,
                }

        context_data["channels_this_week"] = sorted(
            channels_this_week.values(), key=lambda x: x["count"], reverse=True
        )
        context_data["channels_this_month"] = sorted(
            channels_this_month.values(),
            key=lambda x: x["count"],
            reverse=True,
        )

        return context_data


class VideoDetailView(ScrobbleableDetailView):
    model = Video
