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

"""Tests for the database aware task input value models."""

from typing import ClassVar, override

from debusine.artifacts.models import CollectionCategory
from debusine.db.models import Artifact, Collection
from debusine.db.tasks.models import (
    DBArtifactInfo,
    DBBaseTaskInputArtifact,
    DBInputCollectionSingle,
)
from debusine.test.django import TestCase


class DBBaseTaskInputArtifactTests(TestCase):
    """Tests for :py:class:`DBBaseTaskInputArtifact`."""

    artifact: ClassVar[Artifact]

    @override
    @classmethod
    def setUpTestData(cls) -> None:
        super().setUpTestData()
        cls.artifact = cls.playground.create_minimal_source_package_artifact()

    def test_from_artifact(self) -> None:
        value = DBBaseTaskInputArtifact.from_artifact(self.artifact)
        self.assertEqual(value.artifact_id, self.artifact.id)
        self.assertEqual(value.category, self.artifact.category)
        self.assertEqual(value.data, self.artifact.create_data())
        self.assertIsNotNone(value._artifact)
        with self.assertNumQueries(0):
            self.assertEqual(value.artifact, self.artifact)

    def test_cache_miss(self) -> None:
        value = DBBaseTaskInputArtifact.from_artifact(self.artifact)
        value._artifact = None
        with self.assertNumQueries(1):
            self.assertEqual(value.artifact, self.artifact)


class DBArtifactInfoTests(TestCase):
    """Tests for :py:class:`DBArtifactInfo`."""

    artifact: ClassVar[Artifact]

    @override
    @classmethod
    def setUpTestData(cls) -> None:
        super().setUpTestData()
        cls.artifact = cls.playground.create_minimal_source_package_artifact()

    def test_from_artifact(self) -> None:
        value = DBArtifactInfo.from_artifact(
            self.artifact, label="label", lookup="lookup"
        )
        self.assertEqual(value.label, "label")
        self.assertEqual(value.lookup, "lookup")
        self.assertEqual(value.artifact_id, self.artifact.id)
        self.assertEqual(value.category, self.artifact.category)
        self.assertEqual(value.data, self.artifact.create_data())
        self.assertIsNotNone(value._artifact)
        with self.assertNumQueries(0):
            self.assertEqual(value.artifact, self.artifact)

    def test_cache_miss(self) -> None:
        value = DBArtifactInfo.from_artifact(
            self.artifact, label="label", lookup="lookup"
        )
        value._artifact = None
        with self.assertNumQueries(1):
            self.assertEqual(value.artifact, self.artifact)


class DBInputCollectionSingleTests(TestCase):
    """Tests for :py:class:`DBInputCollectionSingle`."""

    collection: ClassVar[Collection]

    @override
    @classmethod
    def setUpTestData(cls) -> None:
        super().setUpTestData()
        cls.collection = cls.playground.create_collection(
            "test", CollectionCategory.TEST
        )

    def test_from_collection(self) -> None:
        value = DBInputCollectionSingle.from_collection(
            self.collection, label="label", lookup="lookup"
        )
        self.assertEqual(value.label, "label")
        self.assertEqual(value.lookup, "lookup")
        self.assertEqual(value.collection_id, self.collection.id)
        self.assertEqual(value.scope_name, self.collection.workspace.scope.name)
        self.assertEqual(value.workspace_name, self.collection.workspace.name)
        self.assertEqual(value.category, self.collection.category)
        self.assertEqual(value.name, self.collection.name)
        self.assertEqual(value.data, self.collection.data)
        self.assertIsNotNone(value._collection)
        with self.assertNumQueries(0):
            self.assertEqual(value.collection, self.collection)

    def test_cache_miss(self) -> None:
        value = DBInputCollectionSingle.from_collection(
            self.collection, label="label", lookup="lookup"
        )
        value._collection = None
        with self.assertNumQueries(1):
            self.assertEqual(value.collection, self.collection)
