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

"""Signing task to generate a new key."""

from pathlib import Path

from debusine.artifacts import SigningKeyArtifact
from debusine.signing.db.models import Key
from debusine.signing.tasks import BaseSigningTask
from debusine.signing.tasks.models import GenerateKeyData
from debusine.tasks.models import BaseDynamicTaskData


class GenerateKey(BaseSigningTask[GenerateKeyData, BaseDynamicTaskData]):
    """Task that generates a new key."""

    _key: Key | None = None

    def run(self, execute_directory: Path) -> bool:  # noqa: U100
        """Execute the task."""
        assert self.work_request_id is not None
        assert self.debusine is not None

        with self.open_debug_log_file("cmd-output.log", mode="wb") as log_file:
            self._key = Key.objects.generate(
                Key.Purpose(self.data.purpose),
                self.data.description,
                self.work_request_id,
                log_file=log_file,
            )

        return True

    def upload_artifacts(
        self, execute_directory: Path, *, execution_success: bool  # noqa: U100
    ) -> None:
        """Upload signing key artifact."""
        assert self.debusine is not None
        # run() always either returns True or raises an exception; in the
        # latter case we won't get here.
        assert execution_success
        assert self._key is not None

        signing_key_artifact = SigningKeyArtifact.create(
            self.data.purpose, self._key.fingerprint, self._key.public_key
        )
        self.debusine.upload_artifact(
            signing_key_artifact,
            workspace=self.workspace_name,
            work_request=self.work_request_id,
        )

    def get_label(self) -> str:
        """Return the task label."""
        return f"generate {self.data.purpose} key"
