from django.contrib import messages
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.db.models import OuterRef, Subquery
from django.http import HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, UpdateView, DeleteView

from . import PaginatorFilter
from ..celery import (
    run_all_recurrent_imports,
    run_all_recurrent_imports_canceled,
    run_all_recurrent_imports_failed,
    run_recurrent_import,
)
from ..filters import RecurrentImportFilter
from ..forms import RecurrentImportForm
from ..models import BatchImportation, RecurrentImport


@login_required(login_url="/accounts/login/")
@permission_required("agenda_culturel.view_recurrentimport")
def recurrent_imports(request, status=None):
    newest = BatchImportation.objects.filter(recurrentImport=OuterRef("pk")).order_by(
        "-created_date"
    )

    qs = (
        RecurrentImport.objects.all()
        .annotate(last_run_status=Subquery(newest.values("status")[:1]))
        .order_by("-pk")
    )

    nb_failed = qs.filter(last_run_status=BatchImportation.STATUS.FAILED).count()
    nb_canceled = qs.filter(last_run_status=BatchImportation.STATUS.CANCELED).count()
    nb_running = qs.filter(last_run_status=BatchImportation.STATUS.RUNNING).count()
    nb_all = qs.count()

    if status is not None:
        qs = qs.filter(last_run_status=status)

    filter = RecurrentImportFilter(request.GET, queryset=qs)

    paginator = PaginatorFilter(filter, 20, request)

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

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

    return render(
        request,
        "agenda_culturel/rimports.html",
        {
            "paginator_filter": response,
            "filter": filter,
            "nb_all": nb_all,
            "nb_failed": nb_failed,
            "nb_canceled": nb_canceled,
            "nb_running": nb_running,
            "status": status,
        },
    )


class RecurrentImportCreateView(
    LoginRequiredMixin, PermissionRequiredMixin, CreateView
):
    model = RecurrentImport
    permission_required = "agenda_culturel.add_recurrentimport"
    success_url = reverse_lazy("recurrent_imports")
    form_class = RecurrentImportForm


class RecurrentImportUpdateView(
    SuccessMessageMixin,
    PermissionRequiredMixin,
    LoginRequiredMixin,
    UpdateView,
):
    model = RecurrentImport
    permission_required = "agenda_culturel.change_recurrentimport"
    form_class = RecurrentImportForm
    success_message = _("The recurrent import has been successfully modified.")


class RecurrentImportDeleteView(
    SuccessMessageMixin,
    PermissionRequiredMixin,
    LoginRequiredMixin,
    DeleteView,
):
    model = RecurrentImport
    permission_required = "agenda_culturel.delete_recurrentimport"
    success_url = reverse_lazy("recurrent_imports")
    success_message = _("The recurrent import has been successfully deleted.")


@login_required(login_url="/accounts/login/")
@permission_required(
    [
        "agenda_culturel.view_recurrentimport",
        "agenda_culturel.view_batchimportation",
    ]
)
def view_rimport(request, pk):
    obj = get_object_or_404(RecurrentImport, pk=pk)
    paginator = Paginator(
        BatchImportation.objects.filter(recurrentImport=pk).order_by("-created_date"),
        10,
    )
    page = request.GET.get("page")

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

    return render(
        request,
        "agenda_culturel/page-rimport.html",
        {"paginator_filter": response, "object": obj},
    )


@login_required(login_url="/accounts/login/")
@permission_required(
    [
        "agenda_culturel.view_recurrentimport",
        "agenda_culturel.run_recurrentimport",
    ]
)
def run_rimport(request, pk):
    rimport = get_object_or_404(RecurrentImport, pk=pk)

    if request.method == "POST":
        # run recurrent import
        run_recurrent_import.delay(pk)

        messages.success(request, _("The import has been launched."))
        return HttpResponseRedirect(reverse_lazy("view_rimport", args=[pk]))
    else:
        return render(
            request,
            "agenda_culturel/run_rimport_confirm.html",
            {"object": rimport},
        )


@login_required(login_url="/accounts/login/")
@permission_required(
    [
        "agenda_culturel.view_recurrentimport",
        "agenda_culturel.run_recurrentimport",
    ]
)
def run_all_rimports(request, status=None):
    if request.method == "POST":
        # run recurrent import
        if status == BatchImportation.STATUS.FAILED:
            run_all_recurrent_imports_failed.delay()
        elif status == BatchImportation.STATUS.CANCELED:
            run_all_recurrent_imports_canceled.delay()
        else:
            run_all_recurrent_imports.delay()

        messages.success(request, _("Imports has been launched."))
        return HttpResponseRedirect(reverse_lazy("recurrent_imports"))
    else:
        if status == BatchImportation.STATUS.FAILED:
            return render(request, "agenda_culturel/run_failed_rimports_confirm.html")
        elif status == BatchImportation.STATUS.CANCELED:
            return render(request, "agenda_culturel/run_canceled_rimports_confirm.html")
        else:
            return render(request, "agenda_culturel/run_all_rimports_confirm.html")


@login_required(login_url="/accounts/login/")
@permission_required(
    [
        "agenda_culturel.view_recurrentimport",
        "agenda_culturel.run_recurrentimport",
    ]
)
def run_all_fb_rimports(request, status=None):
    if request.method == "POST":
        run_all_recurrent_imports.delay(True)

        messages.success(request, _("Facebook imports has been launched."))
        return HttpResponseRedirect(reverse_lazy("recurrent_imports"))
    else:
        return render(request, "agenda_culturel/run_all_fb_rimports_confirm.html")
