# 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 package_publish workflow."""

from typing import Any

from debusine.client.models import model_to_json_serializable_dict
from debusine.db.models import TaskDatabase, WorkRequest, Workspace
from debusine.db.playground import scenarios
from debusine.server.workflows import CreateExperimentWorkspaceWorkflow
from debusine.server.workflows.base import orchestrate_workflow
from debusine.server.workflows.models import ExperimentWorkspaceData
from debusine.tasks.models import BaseDynamicTaskData
from debusine.test.django import TestCase


class CreateExperimentWorkspaceWorkflowTests(TestCase):
    """Unit tests for :py:class:`CreateExperimentWorkspaceWorkflow`."""

    scenario = scenarios.DefaultContext()

    def create_workflow(
        self, task_data: dict[str, Any]
    ) -> CreateExperimentWorkspaceWorkflow:
        """Create an experiment workspace workflow."""
        wr = self.playground.create_workflow(
            task_name="create_experiment_workspace", task_data=task_data
        )
        workflow = wr.get_task()
        assert isinstance(workflow, CreateExperimentWorkspaceWorkflow)
        return workflow

    def test_compute_dynamic_data(self) -> None:
        workflow = self.create_workflow({"experiment_name": "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({"experiment_name": "test_1"})
        self.assertEqual(
            workflow.get_label(), "create_experiment_workspace-template"
        )

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

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

    def test_create_orchestrator(self) -> None:
        """Workflow can be instantiated."""
        workflow = self.create_workflow({"experiment_name": "test"})
        self.assertEqual(workflow.data.experiment_name, "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: ExperimentWorkspaceData,
        *,
        workspace: Workspace | None = None,
    ) -> WorkRequest:
        """Create and orchestrate a CreateExperimentWorkspaceWorkflow."""
        template = self.playground.create_workflow_template(
            name="create_experiment_workspace-template",
            task_name="create_experiment_workspace",
            workspace=workspace,
        )
        root = self.playground.create_workflow(
            task_name="create_experiment_workspace",
            task_data=model_to_json_serializable_dict(task_data),
        )
        self.assertEqual(root.workspace, template.workspace)
        self.assertTrue(orchestrate_workflow(root))
        return root

    def test_populate(self) -> None:
        """Test population with both source and binary artifacts."""
        root = self.orchestrate(
            task_data=ExperimentWorkspaceData(experiment_name="test")
        )
        # There is only one child task
        create_experiment_workspace = root.children.get()
        self.assertEqual(
            create_experiment_workspace.task_name, "create_experiment_workspace"
        )
        self.assertEqual(
            create_experiment_workspace.task_data,
            {
                "experiment_name": "test",
                "expiration_delay": 60,
                "owner_group": None,
                "public": True,
                "workflow_template_names": [],
                "task_configuration": (
                    self.scenario.default_task_configuration_collection.pk
                ),
            },
        )
