# Copyright 2022 The Debusine Developers
# See the AUTHORS file at the top-level directory of this distribution
#
# This file is part of Debusine. It is subject to the license terms
# in the LICENSE file found in the top-level directory of this
# distribution. No part of Debusine, including this file, may be copied,
# modified, propagated, or distributed except according to the terms
# contained in the LICENSE file.

"""debusine views."""

from typing import Any

from django.contrib.auth import views as auth_views
from django.template.response import TemplateResponse
from django.urls import reverse_lazy
from django.views.generic import TemplateView

from debusine.db.models import (
    Token,
    WorkRequest,
    Workspace,
)
from debusine.server.signon.views import SignonLogoutMixin
from debusine.server.views import (
    IsUserAuthenticated,
    ValidatePermissionsMixin,
)
from debusine.tasks.models import TaskTypes
from debusine.web.forms import TokenForm
from debusine.web.views.base import (
    CreateViewBase,
    DeleteViewBase,
    ListViewBase,
    UpdateViewBase,
)


class HomepageView(TemplateView):
    """Class for the homepage view."""

    template_name = "web/homepage.html"

    def get_context_data(self, *args, **kwargs):
        """Return context_data with work_request_list and workspace_list."""
        context = super().get_context_data(**kwargs)

        if self.request.user.is_authenticated:
            context["work_request_list"] = (
                WorkRequest.objects.filter(created_by=self.request.user)
                .exclude(task_type=TaskTypes.INTERNAL)
                .order_by("-created_at")[0:5]
            )

            # Access to public and not public workspaces
            context["workspace_list"] = Workspace.objects.order_by("name")
        else:
            # Only public workspaces listed for non-authenticated users
            context["workspace_list"] = Workspace.objects.filter(
                public=True
            ).order_by("name")
            context["work_request_list"] = None

        return context


class LogoutView(SignonLogoutMixin, auth_views.LogoutView):
    """Class for the logout view."""


class UserTokenListView(ValidatePermissionsMixin, ListViewBase[Token]):
    """List tokens for the user."""

    model = Token
    template_name = "web/user_token-list.html"
    context_object_name = "token_list"
    ordering = "name"

    permission_denied_message = "You need to be authenticated to list tokens"
    permission_classes = [IsUserAuthenticated]

    def get_queryset(self):
        """All tokens for the authenticated user."""
        return Token.objects.filter(user=self.request.user).order_by(
            'created_at'
        )


class UserTokenCreateView(
    ValidatePermissionsMixin, CreateViewBase[Token, TokenForm]
):
    """Form view for creating tokens."""

    template_name = "web/user_token-form.html"
    form_class = TokenForm

    permission_denied_message = "You need to be authenticated to create a token"
    permission_classes = [IsUserAuthenticated]

    def get_form_kwargs(self) -> dict[str, Any]:
        """Extend the default kwarg arguments: add "user"."""
        kwargs = super().get_form_kwargs()
        kwargs["user"] = self.request.user
        return kwargs

    def get_context_data(self, **kwargs):
        """Extend the default context: add action."""
        context = super().get_context_data(**kwargs)
        context['action'] = 'Create'
        return context

    def form_valid(self, form):
        """Validate form and return token created page."""
        form.instance.user = self.request.user
        token = form.save()

        return TemplateResponse(
            self.request, "web/user_token-created.html", {"token": token}
        )


class UserTokenUpdateView(
    ValidatePermissionsMixin, UpdateViewBase[Token, TokenForm]
):
    """Form view for creating tokens."""

    model = Token
    template_name = "web/user_token-form.html"
    form_class = TokenForm
    success_url = reverse_lazy("user:token-list")

    permission_denied_message = "You need to be authenticated to edit tokens"
    permission_classes = [IsUserAuthenticated]

    def get_form_kwargs(self) -> dict[str, Any]:
        """Extend the default kwarg arguments: add "user"."""
        kwargs = super().get_form_kwargs()
        kwargs["user"] = self.request.user
        return kwargs

    def get_queryset(self):
        """Only include tokens for the current user."""
        return super().get_queryset().filter(user=self.request.user)

    def get_context_data(self, **kwargs):
        """Extend the default context: add action."""
        context = super().get_context_data(**kwargs)
        context['action'] = 'Edit'
        return context


class UserTokenDeleteView(
    ValidatePermissionsMixin, DeleteViewBase[Token, TokenForm]
):
    """View for deleting tokens."""

    object: Token  # https://github.com/typeddjango/django-stubs/issues/1227
    model = Token
    template_name = "web/user_token-confirm_delete.html"
    success_url = reverse_lazy("user:token-list")

    permission_denied_message = "You need to be authenticated to delete tokens"
    permission_classes = [IsUserAuthenticated]

    def get_queryset(self):
        """Only include tokens for the current user."""
        return super().get_queryset().filter(user=self.request.user)
