# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import json

import click

from idf_ci.cli._options import option_modified_files, option_paths
from idf_ci.idf_gitlab import ArtifactManager, create_s3_client
from idf_ci.idf_gitlab import build_child_pipeline as build_child_pipeline_cmd
from idf_ci.idf_gitlab import dynamic_pipeline_variables as dynamic_pipeline_variables_cmd
from idf_ci.idf_gitlab import test_child_pipeline as test_child_pipeline_cmd
from idf_ci.settings import CiSettings


@click.group()
def gitlab():
    """Group of gitlab related commands"""
    pass


@gitlab.command()
def dynamic_pipeline_variables():
    """Output dynamic pipeline variables.

    Analyzes the current GitLab pipeline environment and determines what variables to
    set for controlling pipeline behavior. Outputs variables in the format KEY="VALUE"
    for each determined variable, which can be used with GitLab's `export` feature.

    As for the generated variables, please refer to the following link:

    https://docs.espressif.com/projects/idf-ci/en/latest/references/api/idf_ci.idf_gitlab.html#idf_ci.idf_gitlab.dynamic_pipeline_variables
    """
    for k, v in dynamic_pipeline_variables_cmd().items():
        click.echo(f'{k}="{v}"')


@gitlab.command()
@option_paths
@option_modified_files
@click.option(
    '--compare-manifest-sha-filepath',
    default='.manifest_sha',
    help='Path to the recorded manifest sha file generated by `idf-build-apps dump-manifest-sha`',
)
@click.argument('yaml_output', required=False)
def build_child_pipeline(paths, modified_files, compare_manifest_sha_filepath, yaml_output):
    """Generate build child pipeline yaml file."""
    build_child_pipeline_cmd(
        paths=paths,
        modified_files=modified_files,
        compare_manifest_sha_filepath=compare_manifest_sha_filepath,
        yaml_output=yaml_output,
    )


@gitlab.command()
@click.argument('yaml_output', required=False)
def test_child_pipeline(yaml_output):
    """Generate test child pipeline yaml file."""
    test_child_pipeline_cmd(yaml_output)


@gitlab.command()
@click.option(
    '--type',
    'artifact_type',
    type=click.Choice(CiSettings().gitlab.artifacts.available_s3_types),
    help='Type of artifacts to download. If not specified, downloads all types.',
)
@click.option('--commit-sha', help='Commit SHA to download artifacts from.')
@click.option('--branch', help='Git branch to get the latest pipeline from.')
@click.argument('folder', required=False)
def download_artifacts(artifact_type, commit_sha, branch, folder):
    """Download artifacts from a GitLab pipeline.

    This command downloads artifacts from either GitLab's built-in storage or S3
    storage, depending on the configuration. The artifacts are downloaded to the
    specified folder (or current directory if not specified).
    """
    manager = ArtifactManager()
    manager.download_artifacts(
        commit_sha=commit_sha,
        branch=branch,
        artifact_type=artifact_type,
        folder=folder,
    )


@gitlab.command()
@click.option(
    '--type',
    'artifact_type',
    type=click.Choice(CiSettings().gitlab.artifacts.available_s3_types),
    help='Type of artifacts to upload',
)
@click.option(
    '--commit-sha',
    required=True,
    help='Commit SHA to upload artifacts to. Required for S3 storage.',
)
@click.argument('folder', required=False)
def upload_artifacts(artifact_type, commit_sha, folder):
    """Upload artifacts to S3 storage.

    This command uploads artifacts to S3 storage only. GitLab's built-in storage is not
    supported. The commit SHA is required to identify where to store the artifacts.

    :param commit_sha: Commit SHA to upload artifacts to
    :param artifact_type: Type of artifacts to upload (debug, flash, metrics)
    :param folder: Directory containing artifacts to upload
    """
    manager = ArtifactManager()
    manager.upload_artifacts(
        commit_sha=commit_sha,
        artifact_type=artifact_type,
        folder=folder,
    )


@gitlab.command()
@click.option(
    '--commit-sha',
    required=True,
    help='Commit SHA to generate presigned URLs for. Required for S3 storage.',
)
@click.option(
    '--type',
    'artifact_type',
    type=click.Choice(CiSettings().gitlab.artifacts.available_s3_types),
    help='Type of artifacts to generate presigned URLs for',
)
@click.option(
    '--expire-in-days',
    type=int,
    default=4,
    help='Expiration time in days for the presigned URLs (default: 4 days)',
)
@click.argument('folder', required=False)
def generate_presigned_json(commit_sha, artifact_type, expire_in_days, folder):
    """Generate presigned URLs for artifacts in S3 storage.

    This command generates presigned URLs for artifacts that would be uploaded to S3
    storage. The URLs can be used to download the artifacts directly from S3.

    :param commit_sha: Commit SHA to generate presigned URLs for
    :param artifact_type: Type of artifacts to generate URLs for (debug, flash, metrics)
    :param expire_in_days: Expiration time in days for the presigned URLs (default: 4
        days)
    :param folder: Base folder to generate relative paths from
    """
    manager = ArtifactManager()
    presigned_urls = manager.generate_presigned_json(
        commit_sha=commit_sha,
        artifact_type=artifact_type,
        folder=folder,
        expire_in_days=expire_in_days,
    )
    click.echo(json.dumps(presigned_urls))


@gitlab.command()
@click.argument('filename', required=True)
def download_known_failure_cases_file(filename):
    """Download known failure cases file from S3 storage."""
    s3_client = create_s3_client()

    settings = CiSettings()
    if s3_client:
        s3_client.fget_object(
            settings.gitlab.known_failure_cases_bucket_name,
            filename,
            filename,
        )
    else:
        raise ValueError('Configure S3 storage to download artifacts')
