# 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 task input fields."""

from typing import Any
from unittest import mock

from debusine.artifacts.models import CollectionCategory
from debusine.tasks.executors import ExecutorImageCategory, ExecutorInterface
from debusine.tasks.models import BackendType, LookupSingle
from debusine.tasks.tests.helper_mixin import FakeTaskDatabase
from debusine.test import TestCase


class TaskDatabaseInterfaceTests(TestCase):
    """Tests for :py:class:`TaskDatabaseInterface`."""

    def patch_executor(
        self, backend: BackendType, image_category: ExecutorImageCategory
    ) -> mock.MagicMock:
        """Patch executor for `backend` and return its mock."""
        executor = mock.MagicMock(spec=ExecutorInterface)
        executor.image_category = image_category
        self.enterContext(
            mock.patch.dict(
                "debusine.tasks.executors.base._backends", {backend: executor}
            )
        )
        return executor

    def assertLooksUp(
        self,
        lookup: LookupSingle,
        default_category: CollectionCategory | None,
        /,
        **kwargs: Any,
    ) -> None:
        task_db = FakeTaskDatabase()
        with mock.patch.object(
            task_db, "lookup_single_artifact", return_value="RETURN"
        ) as lookup_single_artifact:
            self.assertEqual(task_db.get_environment(**kwargs), "RETURN")

        lookup_single_artifact.assert_called_once_with(
            lookup, default_category=default_category
        )

    def test_get_environment_int(self) -> None:
        self.assertLooksUp(1, None, lookup=1)

    def test_get_environment_with_architecture_and_backend(self) -> None:
        self.assertLooksUp(
            "debian/match:codename=bookworm:format=tarball:backend=unshare",
            None,
            lookup="debian/match:codename=bookworm",
            backend=BackendType.UNSHARE,
        )

    def test_get_environment_with_architecture_from_worker(self) -> None:
        self.patch_executor(BackendType.UNSHARE, ExecutorImageCategory.IMAGE)
        self.assertLooksUp(
            "debian/match:codename=bookworm:architecture=amd64:"
            "format=image:backend=unshare:variant=",
            None,
            lookup="debian/match:codename=bookworm",
            architecture="amd64",
            backend=BackendType.UNSHARE,
            try_variant="",
        )

    def test_get_environment_with_architecture_missing(self) -> None:
        self.patch_executor(BackendType.UNSHARE, ExecutorImageCategory.IMAGE)
        self.assertLooksUp(
            "debian/match:codename=bookworm:format=image:"
            "backend=unshare:variant=",
            None,
            lookup="debian/match:codename=bookworm",
            backend=BackendType.UNSHARE,
            try_variant="",
        )

    def test_get_environment_tries_variant(self) -> None:
        self.patch_executor(BackendType.UNSHARE, ExecutorImageCategory.TARBALL)
        self.assertLooksUp(
            "debian/match:codename=bookworm:architecture=amd64:"
            "format=tarball:backend=unshare:"
            "variant=samplebasetaskwithexecutorandarchitecture",
            None,
            lookup="debian/match:codename=bookworm",
            architecture="amd64",
            backend=BackendType.UNSHARE,
            try_variant="samplebasetaskwithexecutorandarchitecture",
        )

    def test_get_environment_without_try_variant(self) -> None:
        self.patch_executor(BackendType.UNSHARE, ExecutorImageCategory.TARBALL)
        self.assertLooksUp(
            "debian/match:codename=bookworm:architecture=amd64:"
            "format=tarball:backend=unshare",
            None,
            lookup="debian/match:codename=bookworm",
            architecture="amd64",
            backend=BackendType.UNSHARE,
            try_variant=None,
        )
