# 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 management command delete_workspace."""

import io

from django.core.management import CommandError
from django.test import TestCase

from debusine.artifacts.models import ArtifactCategory, CollectionCategory
from debusine.db.models import (
    ArtifactRelation,
    WorkflowTemplate,
    Workspace,
    default_workspace,
)
from debusine.server.management.commands.tests import call_command
from debusine.test import TestHelpersMixin


class DeleteWorkspaceCommandTests(TestHelpersMixin, TestCase):
    """Tests for the delete_workspace command."""

    def create_test_workspace(self):
        """Create a test workspace."""
        workspace = Workspace.objects.create_with_name(name="Test")
        work_request = self.create_work_request(workspace=workspace)
        collection = self.create_collection(
            "test", CollectionCategory.WORKFLOW_INTERNAL, workspace=workspace
        )
        artifact_hello, _ = self.create_artifact(
            category=ArtifactCategory.SOURCE_PACKAGE,
            data={
                "name": "hello",
                "version": "1.0-1",
                "type": "dpkg",
                "dsc_fields": {},
            },
            paths=[
                "hello_1.0-1.dsc",
                "hello_1.0-1.debian.tar.xz",
                "hello_1.0.orig.tar.xz",
            ],
            workspace=workspace,
            create_files=True,
            skip_add_files_in_store=True,
        )
        artifact_hello.created_by_work_request = work_request
        artifact_hello.save()

        artifact_hello_traditional, _ = self.create_artifact(
            category=ArtifactCategory.SOURCE_PACKAGE,
            data={
                "name": "hello-traditional",
                "version": "1.0-1",
                "type": "dpkg",
                "dsc_fields": {},
            },
            paths=[
                "hello-traditional.0-1.dsc",
                "hello-traditional.0-1.debian.tar.xz",
                "hello-traditional.0.orig.tar.xz",
            ],
            workspace=workspace,
            create_files=True,
            skip_add_files_in_store=True,
        )
        self.create_artifact_relation(
            artifact_hello_traditional,
            artifact_hello,
            ArtifactRelation.Relations.RELATES_TO,
        )
        collection.manager.add_artifact(
            artifact_hello, user=self.get_test_user(), name="hello"
        )
        collection.manager.add_artifact(
            artifact_hello_traditional,
            user=self.get_test_user(),
            name="hello-traditional",
        )
        WorkflowTemplate.objects.create(
            name="test", workspace=workspace, task_name="noop"
        )
        # TODO: add more kinds of elements to the workspace, to make
        # sure deletion catches them
        return workspace

    def test_delete_missing_workspace(self):
        """Workspace does not exist."""
        with self.assertRaisesRegex(
            CommandError, r"^Workspace Test does not exist$"
        ) as exc:
            call_command(
                'delete_workspace',
                'Test',
            )
        self.assertEqual(exc.exception.returncode, 3)

        with self.assertRaisesRegex(
            CommandError, r"^Workspace Test does not exist$"
        ) as exc:
            call_command(
                'delete_workspace',
                '--yes',
                'Test',
            )
        self.assertEqual(exc.exception.returncode, 3)

        stdout, stderr, _ = call_command(
            'delete_workspace',
            '--force',
            'Test',
        )
        self.assertEqual('', stdout)

        stdout, stderr, _ = call_command(
            'delete_workspace',
            '--force',
            "--yes",
            'Test',
        )
        self.assertEqual('', stdout)

    def test_delete_workspace(self):
        """Delete an existing workspace."""
        workspace = self.create_test_workspace()

        stdout, stderr, _ = call_command(
            'delete_workspace',
            "--yes",
            'Test',
        )
        self.assertEqual('', stdout)

        with self.assertRaises(Workspace.DoesNotExist):
            Workspace.objects.get(id=workspace.id)

        with self.assertRaises(Workspace.DoesNotExist):
            Workspace.objects.get(name="Test")

    def test_delete_workspace_confirmation(self):
        """delete_workspace doesn't delete (user does not confirm)."""
        workspace = self.create_test_workspace()

        call_command("delete_workspace", "Test", stdin=io.StringIO("N\n"))
        self.assertQuerysetEqual(
            Workspace.objects.filter(name="Test"), [workspace]
        )

        call_command("delete_workspace", "Test", stdin=io.StringIO("\n"))
        self.assertQuerysetEqual(
            Workspace.objects.filter(name="Test"), [workspace]
        )

    def test_delete_default_workspace(self):
        """Default workspace does not get deleted."""
        workspace = default_workspace()
        with self.assertRaisesRegex(
            CommandError,
            fr"^Workspace {workspace.name} cannot be deleted$",
        ) as exc:
            call_command(
                "delete_workspace",
                workspace.name,
                "--yes",
                "--force",
            )
        self.assertEqual(exc.exception.returncode, 3)
