# Copyright 2024 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.

"""Tests for the collections views."""

from typing import ClassVar

from django.test import TestCase
from django.urls import reverse

from rest_framework import status

from debusine.artifacts.models import CollectionCategory
from debusine.db.models import Collection, Workspace
from debusine.test import TestHelpersMixin
from debusine.web.views.tests.utils import ViewTestMixin


class CollectionViewsTests(ViewTestMixin, TestHelpersMixin, TestCase):
    """Tests for Collection views."""

    workspace_public: ClassVar[Workspace]
    workspace_private: ClassVar[Workspace]
    collection_public: ClassVar[Collection]
    collection_private: ClassVar[Collection]

    @classmethod
    def setUpTestData(cls):
        """Set up a database layout for views."""
        cls.workspace_public = cls.create_workspace(name="Public", public=True)
        cls.workspace_private = cls.create_workspace(name="Private")
        cls.collection_public = cls.create_collection(
            "public",
            CollectionCategory.WORKFLOW_INTERNAL,
            workspace=cls.workspace_public,
        )
        cls.collection_private = cls.create_collection(
            "private",
            CollectionCategory.WORKFLOW_INTERNAL,
            workspace=cls.workspace_private,
        )

    def test_list_permissions(self):
        """Test permissions on the collection list view."""
        response = self.client.get(
            reverse("workspaces:collections:list", kwargs={"wname": "Public"})
        )
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response = self.client.get(
            reverse("workspaces:collections:list", kwargs={"wname": "Private"})
        )
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

        response = self.client.get(
            reverse(
                "workspaces:collections:list",
                kwargs={"wname": "does-not-exist"},
            )
        )
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

        self.client.force_login(self.get_test_user())
        response = self.client.get(
            reverse("workspaces:collections:list", kwargs={"wname": "Private"})
        )
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_list(self):
        """Test collection list view."""
        response = self.client.get(
            reverse("workspaces:collections:list", kwargs={"wname": "Public"})
        )
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        tree = self.assertHTMLValid(response)
        rows = self.collection_list_table_rows(tree)
        self.assertEqual(rows[0].find("td").find("a").text, "public")
        self.assertEqual(len(rows), 1)

    def assertCollectionDetailViewPermissions(self, url_name: str) -> None:
        """Test permission on views that show a collection."""
        response = self.client.get(
            reverse(
                url_name,
                kwargs={
                    "wname": "Public",
                    "ccat": CollectionCategory.WORKFLOW_INTERNAL,
                    "cname": "public",
                },
            )
        )
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response = self.client.get(
            reverse(
                url_name,
                kwargs={
                    "wname": "Private",
                    "ccat": CollectionCategory.WORKFLOW_INTERNAL,
                    "cname": "private",
                },
            )
        )
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

        response = self.client.get(
            reverse(
                url_name,
                kwargs={
                    "wname": "does-not-exist",
                    "ccat": CollectionCategory.WORKFLOW_INTERNAL,
                    "cname": "public",
                },
            )
        )
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

        response = self.client.get(
            reverse(
                url_name,
                kwargs={
                    "wname": "Public",
                    "ccat": CollectionCategory.WORKFLOW_INTERNAL,
                    "cname": "does-not-exist",
                },
            )
        )
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

        response = self.client.get(
            reverse(
                url_name,
                kwargs={
                    "wname": "Public",
                    "ccat": "debusine:does-not-exist",
                    "cname": "public",
                },
            )
        )
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

        self.client.force_login(self.get_test_user())
        response = self.client.get(
            reverse(
                url_name,
                kwargs={
                    "wname": "Private",
                    "ccat": CollectionCategory.WORKFLOW_INTERNAL,
                    "cname": "private",
                },
            )
        )
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_detail_permissions(self):
        """Test permissions on the collection details view."""
        self.assertCollectionDetailViewPermissions(
            "workspaces:collections:detail"
        )

    def test_detail(self):
        """Test collection detail view."""
        response = self.client.get(
            reverse(
                "workspaces:collections:detail",
                kwargs={
                    "wname": "Public",
                    "ccat": CollectionCategory.WORKFLOW_INTERNAL,
                    "cname": "public",
                },
            )
        )
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertHTMLValid(response)

    def test_search_permissions(self):
        """Test permissions on the collection search view."""
        self.assertCollectionDetailViewPermissions(
            "workspaces:collections:search"
        )

    def test_search(self):
        """Test collection search view."""
        response = self.client.get(
            reverse(
                "workspaces:collections:search",
                kwargs={
                    "wname": "Public",
                    "ccat": CollectionCategory.WORKFLOW_INTERNAL,
                    "cname": "public",
                },
            )
        )
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertHTMLValid(response)
        # TODO: add more functional view tests here once the actual UI
        # interaction gets validated
