# 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.context import context
from debusine.db.models import Scope, 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, **kwargs: Any) -> dict[str, Any]:
        """Return context_data with work_request_list and workspace_list."""
        ctx = super().get_context_data(**kwargs)

        if self.request.user.is_authenticated:
            ctx["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
            ctx["workspace_list"] = Workspace.objects.order_by("name")
        else:
            # Only public workspaces listed for non-authenticated users
            ctx["workspace_list"] = Workspace.objects.filter(
                public=True
            ).order_by("name")
            ctx["work_request_list"] = None

        ctx["scopes"] = Scope.objects.can_display(context.user).order_by("name")

        return ctx


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_context_data(self, *args, **kwargs):
        """Return context_data with work_request_list and workspace_list."""
        context = super().get_context_data(**kwargs)
        context["scopes"] = Scope.objects.can_display(
            user=self.request.user
        ).order_by("name")
        return context

    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)
