import logging

from collections import deque
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import F, Q
from django.http import HttpResponseRedirect, Http404
from django.shortcuts import render
from django.views.generic.edit import CreateView, UpdateView
from django.urls import reverse_lazy, reverse

from authentications.decorators import authenticated_user
from documents.api import get_pad_link
from documents.etherpadlib import add_ep_cookie
from fet2020.utils import add_log_action
from tasks.forms import InternTaskCreateForm
from tasks.models import Task
from .forms import (
    AttachmentCreateForm,
    AttachmentUpdateForm,
    EtherpadForm,
    FileUploadForm,
    TopicCreateForm,
    TopicUpdateForm,
)
from .models import TopicGroup, Topic, Attachment, Etherpad, FileUpload

logger = logging.getLogger(__name__)


@authenticated_user
def index(request):
    topic = Topic.objects.filter(archive=False).order_by(
        F("topic_group__order").asc(nulls_last=True), "topic_group", "title"
    )
    empty_topic_groups = TopicGroup.objects.filter(topic=None)
    archive_topic = Topic.objects.filter(archive=True)

    context = {
        "topic": topic,
        "empty_topic_groups": empty_topic_groups,
        "archive_topic": archive_topic,
    }

    return render(request, "intern/index.html", context)


@authenticated_user
def show_topic(request, slug=None):
    active_topic = Topic.objects.filter(slug=slug).first()
    if not active_topic:
        raise Http404("wrong topic")

    attachments = Attachment.objects.filter(topic__slug=slug).order_by("title")

    tasks = None
    if active_topic.task_list:
        tasks = deque(
            Task.taskmanager.get_tasks(
                user=request.user.id,
                completed=False,
                task_list=active_topic.task_list,
                all_tasks=True,
            )
        )

    context = {
        "active_topic": active_topic,
        "attachments": attachments,
        "tasks": tasks,
    }

    return render(request, "intern/topic.html", context)


@authenticated_user
def show_attachment(request, topic_slug=None, slug=None):
    attachment = Attachment.objects.filter(
        Q(topic__slug=topic_slug) & Q(slug=slug)
    ).first()
    if not attachment:
        raise Http404("wrong attachment")

    active_topic = Topic.objects.filter(slug=topic_slug).first()

    if request.method == "POST":
        if "btn_etherpad" in request.POST:
            form = EtherpadForm(request.POST)

            if form.is_valid():
                form.save()
                return HttpResponseRedirect(request.path)

            else:
                for elem in list(form.errors.values()):
                    messages.info(request, "; ".join(elem))

        if "btn_fileupload" in request.POST:
            form = FileUploadForm(request.POST, request.FILES)

            if form.is_valid():
                form.save()
                return HttpResponseRedirect(request.path)

            else:
                for elem in list(form.errors.values()):
                    messages.info(request, "; ".join(elem))

    initial = {
        "attachment": attachment,
    }

    form_add_etherpad = EtherpadForm(initial=initial)
    form_add_file = FileUploadForm(initial=initial)

    files = FileUpload.objects.filter(attachment=attachment)

    etherpads = Etherpad.objects.filter(attachment=attachment).order_by("-date")
    etherpad_list = deque([])

    # list of etherpad url-link of any etherpads
    for elem in etherpads:
        etherpad_list.append(
            {
                "title": elem.title,
                "date": elem.date,
                "etherpad_key": get_pad_link(elem.etherpad_key),
            }
        )

    context = {
        "form_add_etherpad": form_add_etherpad,
        "form_add_file": form_add_file,
        "active_topic": active_topic,
        "attachment": attachment,
        "etherpads": etherpad_list,
        "files": files,
    }

    response = render(request, "intern/attachment.html", context)

    try:
        response = add_ep_cookie(request, response)
    except Exception as e:
        logger.info("Etherpad Server doesn't work. Error: %s", e)

    return response


class TopicCreateView(LoginRequiredMixin, CreateView):
    model = Topic
    success_url = reverse_lazy("intern:index")
    template_name = "intern/topic/topic_create.html"
    form_class = TopicCreateForm

    slug = None

    def form_valid(self, form):
        form.instance.created_by = self.request.user
        add_log_action(self.request, form, "intern", "topic", True)
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["topic_group"] = TopicGroup.objects.get(slug=self.slug)

        return context

    def get_initial(self):
        self.slug = self.kwargs.get("topic_group")


class TopicUpdateView(LoginRequiredMixin, UpdateView):
    model = Topic
    template_name = "intern/topic/topic_update.html"
    form_class = TopicUpdateForm

    slug = None

    def form_valid(self, form):
        add_log_action(self.request, form, "intern", "topic", False)
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["slug"] = self.slug
        context["topic"] = Topic.objects.get(slug=self.slug)

        return context

    def get_initial(self):
        self.slug = self.kwargs.get("slug")

    def get_success_url(self):
        context = {
            "slug": self.slug,
        }

        return reverse("intern:topic", kwargs=context)


class AttachmentCreateView(LoginRequiredMixin, CreateView):
    model = Attachment
    template_name = "intern/attachment/attachment_create.html"
    form_class = AttachmentCreateForm

    slug = None

    def form_valid(self, form):
        form.instance.created_by = self.request.user
        add_log_action(self.request, form, "intern", "attachment", True)
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["slug"] = self.slug
        context["topic"] = Topic.objects.get(slug=self.slug)

        return context

    def get_initial(self):
        self.slug = self.kwargs.get("slug")

    def get_success_url(self):
        context = {
            "slug": self.slug,
        }

        return reverse("intern:topic", kwargs=context)


class AttachmentUpdateView(LoginRequiredMixin, UpdateView):
    model = Attachment
    template_name = "intern/attachment/attachment_update.html"
    form_class = AttachmentUpdateForm

    topic_slug = None
    slug = None

    def form_valid(self, form):
        add_log_action(self.request, form, "tasks", "attachment", False)
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["topic_slug"] = self.topic_slug
        context["slug"] = self.slug

        attachment = Attachment.objects.get(
            Q(slug=self.slug) & Q(topic__slug=self.topic_slug)
        )
        context["attachment"] = attachment
        return context

    def get_initial(self):
        self.topic_slug = self.kwargs.get("topic_slug")
        self.slug = self.kwargs.get("slug")

    def get_success_url(self):
        context = {
            "topic_slug": self.topic_slug,
            "slug": self.slug,
        }

        return reverse("intern:attachment", kwargs=context)


class EtherpadCreateView(LoginRequiredMixin, CreateView):
    model = Etherpad
    template_name = "intern/etherpad_create.html"
    form_class = EtherpadForm

    topic_slug = None
    slug = None

    def form_valid(self, form):
        form.instance.created_by = self.request.user
        add_log_action(self.request, form, "intern", "etherpad", True)
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["topic_slug"] = self.topic_slug
        context["slug"] = self.slug

        attachment = Attachment.objects.get(
            Q(slug=self.slug) & Q(topic__slug=self.topic_slug)
        )
        context["attachment"] = attachment

        return context

    def get_initial(self):
        self.topic_slug = self.kwargs.get("topic_slug")
        self.slug = self.kwargs.get("slug")

    def get_success_url(self):
        context = {
            "topic_slug": self.topic_slug,
            "slug": self.slug,
        }

        return reverse("intern:attachment", kwargs=context)


class FileUploadCreateView(LoginRequiredMixin, CreateView):
    model = FileUpload
    template_name = "intern/file_create.html"
    form_class = FileUploadForm

    topic_slug = None
    slug = None

    def form_valid(self, form):
        form.instance.created_by = self.request.user
        add_log_action(self.request, form, "intern", "fileupload", True)
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["topic_slug"] = self.topic_slug
        context["slug"] = self.slug

        attachment = Attachment.objects.get(
            Q(slug=self.slug) & Q(topic__slug=self.topic_slug)
        )
        context["attachment"] = attachment

        return context

    def get_initial(self):
        self.topic_slug = self.kwargs.get("topic_slug")
        self.slug = self.kwargs.get("slug")

    def get_success_url(self):
        context = {
            "topic_slug": self.topic_slug,
            "slug": self.slug,
        }

        return reverse("intern:attachment", kwargs=context)


class TaskCreateView(LoginRequiredMixin, CreateView):
    model = Task
    template_name = "intern/task_create.html"
    form_class = InternTaskCreateForm

    slug = None

    def form_valid(self, form):
        form.instance.created_by = self.request.user
        add_log_action(self.request, form, "tasks", "task", True)
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["slug"] = self.slug

        topic = Topic.objects.get(slug=self.slug)
        context["topic"] = topic
        context["task_list"] = topic.task_list

        return context

    def get_initial(self):
        self.slug = self.kwargs.get("slug")

    def get_success_url(self):
        context = {
            "slug": self.slug,
        }

        return reverse("intern:topic", kwargs=context)
