# import calendar
# import locale
import json
from datetime import datetime
from itertools import chain

from django.conf import settings
from django.db import models
from django.http import HttpResponseRedirect, JsonResponse
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.utils import timezone
from django.views.decorators.http import require_POST
from django_downloadview import ObjectDownloadView
from django_http_exceptions import HTTPExceptions
from guardian.shortcuts import get_objects_for_user

from .models import Lecture, LectureGroup, LectureMaterial


class LectureMaterialFileDownloadView(ObjectDownloadView):
    model = LectureMaterial
    file_field = "file"
    attachment = False

    def get_queryset(self, *args, **kwargs):
        queryset = (
            super()
            .get_queryset(*args, **kwargs)
            .filter(
                lecture__groups__in=(
                    get_objects_for_user(
                        self.current_user, "lectures.view_lecturegroup"
                    ).filter(
                        models.Q(user_groups__in=self.current_user.groups.all())
                        | models.Q(user_groups=None)
                    )
                )
            )
        )

        return queryset

    def get(self, request, *args, **kwargs):
        self.current_user = request.user

        return super().get(request, *args, **kwargs)


def get_base_context(request) -> dict:
    return {
        "site_url": settings.SITE_URL,
    }


def generate_auth_redirect(request) -> HttpResponseRedirect:
    return HttpResponseRedirect(
        request.build_absolute_uri(reverse("oidc_authentication_init"))
        + "?next="
        + request.path
    )


def get_lecture(request, id: int) -> tuple:
    lecture = (
        get_objects_for_user(request.user, "lectures.view_lecture")
        .filter(id=id)
        .first()
    )

    if lecture is None:
        raise HTTPExceptions.NOT_FOUND

    if not (
        get_objects_for_user(request.user, "lectures.view_lecturegroup")
        .filter(
            models.Q(id__in=lecture.groups.all())
            & (
                (
                    models.Q(user_groups__in=request.user.groups.all())
                    | models.Q(user_groups=None)
                )
                if not request.user.is_superuser
                else models.Q(id__isnull=False)  # Always True
            )
        )
        .distinct()
        .exists()
    ):  # User does not have access to related groups
        if request.user.is_authenticated:  # The user can log in
            raise HTTPExceptions.NOT_FOUND
        else:  # They can log in
            return False, generate_auth_redirect(request)

    return True, lecture


def view_groups(request):
    lecture_groups = (
        get_objects_for_user(request.user, "lectures.view_lecturegroup")
        .filter(
            (
                models.Q(user_groups__in=request.user.groups.all())
                | models.Q(user_groups=None)
            )
            if not request.user.is_superuser
            else models.Q(id__isnull=False)  # Always True
        )
        .distinct()
        .all()
    )

    return render(
        request,
        "lectures/view_groups.html",
        {
            **get_base_context(request),
            "title": "Výukové skupiny",
            "description": "Kurzy a školení zaměřené na politickou práci a organizaci kampaní.",
            "header_name": "Pirátský e-Learning",
            "lecture_groups": lecture_groups,
            "settings": Lecture.settings,
        },
    )


def view_group_lectures(request, group_id: int):
    group = get_objects_for_user(request.user, "lectures.view_lecturegroup").filter(
        id=group_id
    )

    group_id_exists = group.exists()

    if not request.user.is_superuser:
        group = group.filter(
            models.Q(user_groups__in=request.user.groups.all())
            | models.Q(user_groups=None)
        )

    if not group.exists():
        if not group_id_exists:  # Doesn't exist at all
            raise HTTPExceptions.NOT_FOUND
        elif group_id_exists:  # Exists without permissions checks
            if request.user_is_authenticated:  # The user is logged in
                raise HTTPExceptions.NOT_FOUND
            else:  # The user can log in
                return generate_auth_redirect(request)

    group = group.first()

    timestamp_starting_separator = timezone.now() - Lecture.is_current_starting_treshold
    timestamp_ending_separator = timezone.now() + Lecture.is_current_ending_treshold

    past_lectures = (
        get_objects_for_user(request.user, "lectures.view_lecture")
        .filter(
            groups=group,
            timestamp__lt=timestamp_starting_separator,
        )
        .all()
    )
    current_lectures = (
        get_objects_for_user(request.user, "lectures.view_lecture")
        .filter(
            groups=group,
            timestamp__gte=timestamp_starting_separator,
            timestamp__lte=timestamp_ending_separator,
        )
        .all()
    )

    calendar_data = []
    all_lectures = list(
        chain(
            past_lectures,
            current_lectures,
            (
                get_objects_for_user(request.user, "lectures.view_lecture")
                .filter(groups=group, timestamp__gte=timestamp_ending_separator)
                .all()
            ),
        )
    )

    per_month_lectures = {}

    MONTH_NAMES = {
        0: "",
        1: "Leden",
        2: "Únor",
        3: "Březen",
        4: "Duben",
        5: "Květen",
        6: "Červen",
        7: "Červenec",
        8: "Srpen",
        9: "Září",
        10: "Říjen",
        11: "Listopad",
        12: "Prosinec",
    }

    # locale.setlocale(
    # locale.LC_ALL,
    # "cs_CZ.UTF-8"
    # )

    current_year = datetime.today().year

    has_previous_timeline_years = False
    has_next_timeline_years = False

    for lecture in all_lectures:
        if not has_previous_timeline_years and lecture.timestamp.year < current_year:
            has_previous_timeline_years = True

        if not has_next_timeline_years and lecture.timestamp.year > current_year:
            has_next_timeline_years = True

        if lecture.timestamp.year not in per_month_lectures:
            per_month_lectures[lecture.timestamp.year] = {
                MONTH_NAMES[month]: [] for month in range(1, 12 + 1)
            }

        if current_year not in per_month_lectures:
            per_month_lectures[current_year] = {
                MONTH_NAMES[month]: [] for month in range(1, 12 + 1)
            }

        per_month_lectures[lecture.timestamp.year][
            MONTH_NAMES[lecture.timestamp.month]
        ].append(lecture)

    # locale.setlocale(
    #     locale.LC_ALL,
    #     ""
    # )

    return render(
        request,
        "lectures/view_group_lectures.html",
        {
            **get_base_context(request),
            "title": f"Výuka pro {group.name}",
            "description": f"e-Learningová výuka pro skupinu {group.name}.",
            "header_name": group.name,
            "group": group,
            "current_lectures": current_lectures,
            "past_lectures": past_lectures,
            "per_month_lectures": per_month_lectures,
            "current_year": current_year,
            "has_previous_timeline_years": has_previous_timeline_years,
            "has_next_timeline_years": has_next_timeline_years,
        },
    )


def view_lecture(request, lecture_id: int):
    is_successful, lecture = get_lecture(request, lecture_id)

    if not is_successful:
        return lecture

    related_group_id = request.GET.get("related_group_id")

    if related_group_id is not None and not (
        get_objects_for_user(request.user, "lectures.view_lecture")
        .filter(id=related_group_id)
        .exists()
    ):
        # Ignore the wrong part of the URL and move on, don't raise exceptions
        # just because of the related_group_id being wrong.
        related_group_id = None

    return render(
        request,
        "lectures/view_lecture.html",
        {
            **get_base_context(request),
            "title": f"{lecture.name}",
            "description": f"e-Learningové školení {lecture.name}.",
            "header_name": lecture.name,
            "lecture": lecture,
            "related_group_id": related_group_id,
        },
    )


@require_POST
def rsvp_lecture(request, lecture_id: int):
    is_successful, lecture = get_lecture(request, lecture_id)

    if not is_successful:
        return lecture

    is_registered = request.POST.get("register", "false") == "true"

    if is_registered is request.user.get_lecture_registered(
        lecture
    ):  # The RSVP state is the same
        return JsonResponse({"success": False})

    if is_registered:
        request.user.rsvp_lectures.add(lecture)
    else:
        request.user.rsvp_lectures.remove(lecture)

    request.user.save()

    return JsonResponse({"success": True})