#!/usr/bin/env python
"""
Helper script to upload release assets and create a release for the Rarian project.
"""
import re
import os.path
import logging

import click
import requests

PROJECT = "rarian"
PROJECT_ID = 18722
GITLAB = "https://gitlab.freedesktop.org"
PROJECT_URL = f"{GITLAB}/rarian/rarian"
PROJECT_API_URL = f"{GITLAB}/api/v4/projects/{PROJECT_ID}"

logger = logging.getLogger("create-release")


def upload_assets(session, version, assets):
    """Uploads the files given in assets to GitLab as assets."""
    asset_info = {}
    base_url = f"{PROJECT_API_URL}/packages/generic/{PROJECT}/{version}/"
    try:
        for asset in assets:
            filename = os.path.basename(asset)
            with open(asset, "rb") as fp:
                logger.info("Uploading %s", asset)
                asset_url = base_url + filename
                rsp = session.put(asset_url, data=fp, params={"select": "package_file"})
                rsp.raise_for_status()
                asset_info[asset] = rsp.json()
                asset_info[asset]["permalink"] = asset_url
    except requests.HTTPError as e:
        logger.exception("Failed to upload assets: %s\n%s", e, e.response.content)
        raise

    return asset_info


def make_release(session, version, asset_info):
    """
    Creates a GitLab release using the given version, and attaching links to the given
    assets.
    """
    body = {"name": f"Release {version}", "tag_name": version, "assets": {"links": []}}
    for asset in asset_info.values():
        body["assets"]["links"].append(
            {
                "name": asset["file_name"],
                "url": asset["permalink"],
                "filepath": "/assets/" + asset["file_name"]
            }
        )
    logger.info("Creating release for version %s", version)
    rsp = session.post(f"{PROJECT_API_URL}/releases", json=body)
    rsp.raise_for_status()
    return version


def validate_version(ctx, param, value):
    if not re.fullmatch(r"[0-9]+\.[0-9]+\.[0-9]+", value):
        raise click.BadParameter("Invalid version")
    return value


@click.command()
@click.argument("version", callback=validate_version)
@click.argument("files", nargs=-1)
@click.option("--api-token", envvar="GITLAB_API_TOKEN")
def create_release(version, files, api_token):
    """Create a new GitLab release for the given version, with an optional set of additional files."""
    api_token = api_token.strip()
    session = requests.Session()
    session.headers.update({"Authorization": "Bearer " + api_token})
    asset_info = upload_assets(session, version, files)
    result = make_release(session, version, asset_info)

    print(f"Created release for {result}")


if __name__ == "__main__":
    logging.basicConfig()
    create_release()
