"""Helper script to get the actual branch name, docker safe"""

import os
from json import dumps
from pathlib import Path
from sys import exit as sysexit
from time import time
from typing import Any


def authentik_version() -> str:
    init = Path(__file__).parent.parent.parent.parent / "authentik" / "__init__.py"
    with open(init) as f:
        content = f.read()
    locals: dict[str, Any] = {}
    exec(content, None, locals)  # nosec
    return str(locals["VERSION"])


def must_or_fail(input: str | None, error: str) -> str:
    if not input:
        print(f"::error::{error}")
        sysexit(1)
    return input


# Decide if we should push the image or not
should_push = True
if len(os.environ.get("DOCKER_USERNAME", "")) < 1:
    # Don't push if we don't have DOCKER_USERNAME, i.e. no secrets are available
    should_push = False
if (
    must_or_fail(os.environ.get("GITHUB_REPOSITORY"), "Repo required").lower()
    == "goauthentik/authentik-internal"
):
    # Don't push on the internal repo
    should_push = False

branch_name = os.environ["GITHUB_REF"]
if os.environ.get("GITHUB_HEAD_REF", "") != "":
    branch_name = os.environ["GITHUB_HEAD_REF"]
safe_branch_name = branch_name.replace("refs/heads/", "").replace("/", "-").replace("'", "-")

image_names = must_or_fail(os.getenv("IMAGE_NAME"), "Image name required").split(",")
image_arch = os.getenv("IMAGE_ARCH") or None

is_pull_request = bool(os.getenv("PR_HEAD_SHA"))
is_release = "dev" not in image_names[0]

sha = must_or_fail(
    os.environ["GITHUB_SHA"] if not is_pull_request else os.getenv("PR_HEAD_SHA"),
    "could not determine SHA",
)

# 2042.1.0 or 2042.1.0-rc1
version = authentik_version()
# 2042.1
version_family = ".".join(version.split("-", 1)[0].split(".")[:-1])
prerelease = "-" in version

image_tags = []
if is_release:
    for name in image_names:
        image_tags += [
            f"{name}:{version}",
        ]
        if not prerelease:
            image_tags += [
                f"{name}:{version_family}",
            ]
else:
    suffix = ""
    if image_arch:
        suffix = f"-{image_arch}"
    for name in image_names:
        image_tags += [
            f"{name}:gh-{sha}{suffix}",  # Used for ArgoCD and PR comments
            f"{name}:gh-{safe_branch_name}{suffix}",  # For convenience
            f"{name}:gh-{safe_branch_name}-{int(time())}-{sha[:7]}{suffix}",  # Use by FluxCD
        ]

image_main_tag = image_tags[0].split(":")[-1]


def get_attest_image_names(image_with_tags: list[str]) -> str:
    """Attestation only for GHCR"""
    image_tags = []
    for image_name in set(name.split(":")[0] for name in image_with_tags):
        if not image_name.startswith("ghcr.io"):
            continue
        image_tags.append(image_name)
    return ",".join(set(image_tags))


# Generate `cache-to` param
cache_to = ""
if should_push:
    _cache_tag = "buildcache"
    if image_arch:
        _cache_tag += f"-{image_arch}"
    cache_to = f"type=registry,ref={get_attest_image_names(image_tags)}:{_cache_tag},mode=max"


image_build_args = []
if os.getenv("RELEASE", "false").lower() == "true":
    image_build_args = [f"VERSION={os.getenv('REF')}"]
else:
    image_build_args = [f"GIT_BUILD_HASH={sha}"]
image_build_args_str = "\n".join(image_build_args)

with open(os.environ["GITHUB_OUTPUT"], "a+", encoding="utf-8") as _output:
    print(f"shouldPush={str(should_push).lower()}", file=_output)
    print(f"sha={sha}", file=_output)
    print(f"version={version}", file=_output)
    print(f"prerelease={prerelease}", file=_output)
    print(f"imageTags={','.join(image_tags)}", file=_output)
    print(f"imageTagsJSON={dumps(image_tags)}", file=_output)
    print(f"attestImageNames={get_attest_image_names(image_tags)}", file=_output)
    print(f"imageMainTag={image_main_tag}", file=_output)
    print(f"imageMainName={image_tags[0]}", file=_output)
    print(f"cacheTo={cache_to}", file=_output)
    print(f"imageBuildArgs={image_build_args_str}", file=_output)
