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

"""Input fields for server tasks."""

from typing import override

from debusine.client.models import LookupChildType, LookupResultType
from debusine.db.tasks.inputs import CollectionInput
from debusine.db.tasks.models import DBInputLookupResult
from debusine.db.tasks.resolver import DBFieldResolver
from debusine.server.tasks.inputs.models import CopyCollectionItemsCopiesInfo
from debusine.server.tasks.models import CopyCollectionItemsCopies
from debusine.tasks import TaskConfigError
from debusine.tasks.inputs import FieldResolver, serializers
from debusine.tasks.inputs.inputs import DataFieldInput


class CopyCollectionItemsCopiesInput(
    DataFieldInput[
        list[CopyCollectionItemsCopies], list[CopyCollectionItemsCopiesInfo]
    ]
):
    """A set of copies for the CopyCollectionItems task."""

    serializer = serializers.PydanticListSerializer(
        CopyCollectionItemsCopiesInfo
    )

    @override
    def resolve(
        self, resolver: FieldResolver
    ) -> list[CopyCollectionItemsCopiesInfo]:
        assert isinstance(resolver, DBFieldResolver)
        all_copies = resolver.get_field(self)
        assert all_copies is not None
        info: list[CopyCollectionItemsCopiesInfo] = []
        for i, copies in enumerate(all_copies):
            field_prefix = f"{self.field}[{i}]"
            source_items_field_name = f"{field_prefix}.source_items"
            try:
                source_items_results = resolver.work_request.lookup_multiple(
                    lookup=copies.source_items, expect_type=LookupChildType.ANY
                )
            except LookupError as e:
                raise TaskConfigError(
                    f"Lookup for field '{source_items_field_name}' in"
                    f" {resolver.work_request.workspace} failed: {e}"
                ) from e
            source_items: list[DBInputLookupResult] = []
            for result in source_items_results:
                if result.result_type == LookupResultType.COLLECTION:
                    raise TaskConfigError(
                        f"Bad lookup result from field"
                        f" '{source_items_field_name}' in"
                        f" {resolver.work_request.workspace}:"
                        f" Cannot copy entire collections"
                    )
                source_items.append(
                    DBInputLookupResult.from_lookup_result(
                        result, label=source_items_field_name
                    )
                )
            target_collection_field = CollectionInput(
                field=f"{field_prefix}.target_collection"
            )
            target_collection_field.getter = lambda _: copies.target_collection
            info.append(
                CopyCollectionItemsCopiesInfo(
                    label=field_prefix,
                    source_items=source_items,
                    target_collection=target_collection_field.resolve(resolver),
                    unembargo=copies.unembargo,
                    replace=copies.replace,
                    name_template=copies.name_template,
                    variables=copies.variables,
                )
            )

        return info

    @override
    def get_artifact_ids(
        self, value: list[CopyCollectionItemsCopiesInfo]
    ) -> list[int]:
        ids: list[int] = []
        for copies in value:
            ids += [
                item.result.artifact.id
                for item in copies.source_items
                if item.result.artifact is not None
            ]
        return ids
