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

"""Unit tests for the create_child_workspace workflow."""

from typing import Any

import debusine.worker.tags as wtags
from debusine.db.models import TaskDatabase, WorkRequest, Workspace
from debusine.db.playground import scenarios
from debusine.server.workflows import CreateChildWorkspaceWorkflow
from debusine.server.workflows.base import orchestrate_workflow
from debusine.server.workflows.models import ChildWorkspaceData
from debusine.tasks.models import BaseDynamicTaskData
from debusine.test.django import TestCase


class CreateChildWorkspaceWorkflowTests(TestCase):
    """Unit tests for :py:class:`CreateChildWorkspaceWorkflow`."""

    scenario = scenarios.DefaultContext()

    def create_workflow(
        self, task_data: dict[str, Any]
    ) -> CreateChildWorkspaceWorkflow:
        """Create a child workspace workflow."""
        wr = self.playground.create_workflow(
            task_name="create_child_workspace", task_data=task_data
        )
        workflow = wr.get_task()
        assert isinstance(workflow, CreateChildWorkspaceWorkflow)
        return workflow

    def test_compute_system_required_tags(self) -> None:
        workflow = self.create_workflow({"suffix": "test"})
        self.assertCountEqual(
            workflow.compute_system_required_tags(),
            [wtags.WORKER_TYPE_NOT_ASSIGNABLE],
        )

    def test_compute_dynamic_data(self) -> None:
        workflow = self.create_workflow({"suffix": "test"})

        self.assertEqual(
            workflow.compute_dynamic_data(TaskDatabase(workflow.work_request)),
            BaseDynamicTaskData(subject="test", parameter_summary="test"),
        )

    def test_get_label_without_parameter_summary(self) -> None:
        """Test get_label."""
        workflow = self.create_workflow({"suffix": "test_1"})
        self.assertEqual(
            workflow.get_label(), "create_child_workspace-template"
        )

    def test_get_label_with_parameter_summary(self) -> None:
        """Test get_label."""
        root = self.orchestrate(task_data=ChildWorkspaceData(suffix="test_2"))

        self.assertEqual(
            root.get_label(), "create_child_workspace-template: test_2"
        )

    def test_create_orchestrator(self) -> None:
        """Workflow can be instantiated."""
        workflow = self.create_workflow({"suffix": "test"})
        self.assertIsNone(workflow.data.prefix)
        self.assertEqual(workflow.data.suffix, "test")
        self.assertTrue(workflow.data.public)
        self.assertIsNone(workflow.data.owner_group)
        self.assertEqual(workflow.data.workflow_template_names, [])
        self.assertEqual(workflow.data.expiration_delay, 60)

    def orchestrate(
        self,
        task_data: ChildWorkspaceData,
        *,
        workspace: Workspace | None = None,
    ) -> WorkRequest:
        """Create and orchestrate a CreateChildWorkspaceWorkflow."""
        template = self.playground.create_workflow_template(
            name="create_child_workspace-template",
            task_name="create_child_workspace",
            workspace=workspace,
        )
        root = self.playground.create_workflow(
            task_name="create_child_workspace",
            task_data=task_data.model_dump(mode="json"),
        )
        self.assertEqual(root.workspace, template.workspace)
        self.assertTrue(orchestrate_workflow(root))
        return root

    def test_populate(self) -> None:
        root = self.orchestrate(task_data=ChildWorkspaceData(suffix="test"))
        # There is only one child task
        create_child_workspace = root.children.get()
        self.assertEqual(
            create_child_workspace.task_name, "create_child_workspace"
        )
        self.assertEqual(
            create_child_workspace.task_data,
            {
                "prefix": root.workspace.name,
                "suffix": "test",
                "expiration_delay": 60,
                "owner_group": None,
                "public": True,
                "workflow_template_names": [],
            },
        )

    def test_populate_prefix(self) -> None:
        root = self.orchestrate(
            task_data=ChildWorkspaceData(prefix="namespace", suffix="test")
        )
        # There is only one child task
        create_child_workspace = root.children.get()
        self.assertEqual(
            create_child_workspace.task_name, "create_child_workspace"
        )
        self.assertEqual(
            create_child_workspace.task_data,
            {
                "prefix": "namespace",
                "suffix": "test",
                "expiration_delay": 60,
                "owner_group": None,
                "public": True,
                "workflow_template_names": [],
            },
        )
