# Copyright 2022 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 migrations."""

from django.contrib.auth import get_user_model
from django.db import connection
from django.db.migrations.executor import MigrationExecutor
from django.test import TestCase

from debusine.db.models import (
    DEFAULT_WORKSPACE_NAME,
    FileStore,
    default_file_store,
    default_workspace,
)


class MigrationTests(TestCase):
    """Test migrations."""

    def test_default_store_created(self):
        """Assert Default FileStore has been created."""
        default_file_store = FileStore.default()

        self.assertEqual(
            default_file_store.backend, FileStore.BackendChoices.LOCAL
        )

        self.assertEqual(default_file_store.configuration, {})

    def test_system_workspace_created(self):
        """Assert System Workspace has been created."""
        workspace = default_workspace()
        self.assertEqual(workspace.default_file_store, default_file_store())

    def test_artifact_underscore_names(self):
        """Artifacts have their data migrated to new names."""
        migrate_from = [("db", "0013_expiration_delay")]
        migrate_to = [("db", "0014_artifact_underscore_names")]

        # Several of the category/data combinations here wouldn't appear in
        # practice, but are here to ensure full coverage of the data
        # migration code.
        old_artifacts = [
            ("debusine:work-request-debug-logs", {}),
            ("debian:package-build-log", {"source": "hello"}),
            ("debian:upload", {"type": "dpkg"}),
            (
                "debian:upload",
                {"type": "dpkg", "changes-fields": {"Source": "hello"}},
            ),
            (
                "debian:upload",
                {"type": "dpkg", "changes-fields": {"Source": "coreutils"}},
            ),
            (
                "debian:source-package",
                {
                    "name": "hello",
                    "version": "1",
                    "type": "dpkg",
                    "dsc-fields": {"Source": "hello"},
                },
            ),
            ("debian:binary-package", {"srcpkg-name": "hello"}),
            (
                "debian:binary-package",
                {
                    "srcpkg-name": "hello",
                    "srcpkg-version": "1",
                    "deb-fields": {"Package": "hello"},
                    "deb-control-files": ["control"],
                },
            ),
            (
                "debian:binary-packages",
                {
                    "srcpkg-name": "hello",
                    "srcpkg-version": "1",
                    "version": "1",
                    "architecture": "amd64",
                    "packages": ["hello"],
                },
            ),
        ]
        new_artifacts = [
            ("debusine:work-request-debug-logs", {}),
            ("debian:package-build-log", {"source": "hello"}),
            ("debian:upload", {"type": "dpkg"}),
            (
                "debian:upload",
                {"type": "dpkg", "changes_fields": {"Source": "hello"}},
            ),
            (
                "debian:upload",
                {"type": "dpkg", "changes_fields": {"Source": "coreutils"}},
            ),
            (
                "debian:source-package",
                {
                    "name": "hello",
                    "version": "1",
                    "type": "dpkg",
                    "dsc_fields": {"Source": "hello"},
                },
            ),
            ("debian:binary-package", {"srcpkg_name": "hello"}),
            (
                "debian:binary-package",
                {
                    "srcpkg_name": "hello",
                    "srcpkg_version": "1",
                    "deb_fields": {"Package": "hello"},
                    "deb_control_files": ["control"],
                },
            ),
            (
                "debian:binary-packages",
                {
                    "srcpkg_name": "hello",
                    "srcpkg_version": "1",
                    "version": "1",
                    "architecture": "amd64",
                    "packages": ["hello"],
                },
            ),
        ]

        executor = MigrationExecutor(connection)
        executor.migrate(migrate_from)
        old_apps = executor.loader.project_state(migrate_from).apps
        workspace = old_apps.get_model("db", "Workspace").objects.get(
            name=DEFAULT_WORKSPACE_NAME
        )
        for category, data in old_artifacts:
            old_apps.get_model("db", "Artifact").objects.create(
                category=category, workspace=workspace, data=data
            )

        executor.loader.build_graph()
        executor.migrate(migrate_to)
        new_apps = executor.loader.project_state(migrate_to).apps

        self.assertCountEqual(
            [
                (artifact.category, artifact.data)
                for artifact in new_apps.get_model(
                    "db", "Artifact"
                ).objects.all()
            ],
            new_artifacts,
        )

        executor.loader.build_graph()
        executor.migrate(migrate_from)

        self.assertCountEqual(
            [
                (artifact.category, artifact.data)
                for artifact in old_apps.get_model(
                    "db", "Artifact"
                ).objects.all()
            ],
            old_artifacts,
        )

    def test_autopkgtest_work_request_architecture_rename(self):
        """Work requests for autopkgtest rename their architecture field."""
        migrate_from = [("db", "0018_workrequest_worker_blank")]
        migrate_to = [("db", "0019_autopkgtest_task_data")]

        old_work_requests = [
            ("foo", {"architecture": "amd64"}),
            ("autopkgtest", {"architecture": "amd64"}),
        ]
        new_work_requests = [
            ("foo", {"architecture": "amd64"}),
            ("autopkgtest", {"host_architecture": "amd64"}),
        ]

        user = get_user_model().objects.create(username="testuser")

        executor = MigrationExecutor(connection)
        executor.migrate(migrate_from)
        old_apps = executor.loader.project_state(migrate_from).apps
        workspace = old_apps.get_model("db", "Workspace").objects.get(
            name=DEFAULT_WORKSPACE_NAME
        )
        for task_name, task_data in old_work_requests:
            old_apps.get_model("db", "WorkRequest").objects.create(
                created_by_id=user.id,
                task_name=task_name,
                workspace=workspace,
                task_data=task_data,
            )

        executor.loader.build_graph()
        executor.migrate(migrate_to)
        new_apps = executor.loader.project_state(migrate_to).apps

        self.assertCountEqual(
            [
                (request.task_name, request.task_data)
                for request in new_apps.get_model(
                    "db", "WorkRequest"
                ).objects.all()
            ],
            new_work_requests,
        )

        executor.loader.build_graph()
        executor.migrate(migrate_from)

        self.assertCountEqual(
            [
                (request.task_name, request.task_data)
                for request in old_apps.get_model(
                    "db", "WorkRequest"
                ).objects.all()
            ],
            old_work_requests,
        )
