#!/usr/bin/env bash
set -euo pipefail

script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

: "${MATRIX_DISTRO:?Missing MATRIX_DISTRO}"
IMAGE_ARCH="${IMAGE_ARCH:-$("${script_dir}/../meta/resolve/architecture.sh")}"
export INFINITO_DISTRO="${MATRIX_DISTRO}"

# shellcheck source=scripts/meta/env/load.sh
source "${script_dir}/../meta/env/load.sh"

INFINITO_PARENT_IMAGE="$("${script_dir}/../meta/resolve/image/parent.sh")"
export INFINITO_PARENT_IMAGE

: "${BUILD_CONTEXT_DIR:?Missing BUILD_CONTEXT_DIR}"
: "${IMAGE_DIGEST_DIR:?Missing IMAGE_DIGEST_DIR}"
: "${GITHUB_REPOSITORY:?Missing GITHUB_REPOSITORY}"
: "${USE_NIX_TOKEN:?Missing USE_NIX_TOKEN}"
: "${INFINITO_PARENT_IMAGE:?Missing INFINITO_PARENT_IMAGE; source scripts/meta/env/load.sh}"
: "${INFINITO_SRC_DIR:?Missing INFINITO_SRC_DIR; source scripts/meta/env/load.sh}"
: "${INFINITO_VENV_DIR:?Missing INFINITO_VENV_DIR; source scripts/meta/env/load.sh}"
ghcr_owner="$(scripts/meta/resolve/repository/owner.sh)"
repo_name="$("${script_dir}/../meta/resolve/repository/name.sh")"

image="ghcr.io/${ghcr_owner}/${repo_name}/${MATRIX_DISTRO}"
cache_ref="${image}:buildcache-${IMAGE_ARCH}"
metadata="$(mktemp)"

max_attempts="${MAX_ATTEMPTS:-7}"
retry_delay_seconds="${RETRY_DELAY_SECONDS:-20}"
attempt=1

nix_arg=()
if [[ "${USE_NIX_TOKEN}" == "true" ]]; then
	: "${NIX_GITHUB_TOKEN:?Missing NIX_GITHUB_TOKEN}"
	nix_arg=(--build-arg "NIX_CONFIG=access-tokens = github.com=${NIX_GITHUB_TOKEN}")
else
	echo "pull_request_target on fork detected: skipping NIX_CONFIG token build-arg."
fi

while true; do
	echo "=== Build & push attempt ${attempt}/${max_attempts} ==="

	if docker buildx build \
		--file "${BUILD_CONTEXT_DIR}/Dockerfile" \
		--platform "linux/${IMAGE_ARCH}" \
		--output "type=image,name=${image},push-by-digest=true,name-canonical=true,push=true" \
		--metadata-file "${metadata}" \
		--label "org.opencontainers.image.source=https://github.com/${GITHUB_REPOSITORY}" \
		--build-arg "INFINITO_PARENT_IMAGE=${INFINITO_PARENT_IMAGE}" \
		--build-arg "INFINITO_SRC_DIR=${INFINITO_SRC_DIR}" \
		--build-arg "INFINITO_VENV_DIR=${INFINITO_VENV_DIR}" \
		--build-arg "INFINITO_PACKAGE_INSTALL_SCRIPT=${INFINITO_PACKAGE_INSTALL_SCRIPT:?source scripts/meta/env/load.sh}" \
		--build-arg "INFINITO_PYTHON_INSTALL_SCRIPT=${INFINITO_PYTHON_INSTALL_SCRIPT:?source scripts/meta/env/load.sh}" \
		--build-arg "INFINITO_DOCKER_CLI_INSTALL_SCRIPT=${INFINITO_DOCKER_CLI_INSTALL_SCRIPT:?source scripts/meta/env/load.sh}" \
		"${nix_arg[@]}" \
		--cache-from "type=registry,ref=${cache_ref}" \
		--cache-to "type=registry,mode=max,ref=${cache_ref}" \
		"${BUILD_CONTEXT_DIR}"; then
		echo "Build & push succeeded on attempt ${attempt}/${max_attempts}."
		break
	fi

	if [[ "${attempt}" -ge "${max_attempts}" ]]; then
		echo "Build & push failed after ${max_attempts} attempts."
		exit 1
	fi

	echo "Attempt ${attempt} failed. Retrying in ${retry_delay_seconds}s..."
	sleep "${retry_delay_seconds}"
	attempt=$((attempt + 1))
done

mkdir -p "${IMAGE_DIGEST_DIR}"
jq -er '."containerimage.digest"' "${metadata}" >"${IMAGE_DIGEST_DIR}/${MATRIX_DISTRO}.${IMAGE_ARCH}"
rm -f "${metadata}"
echo "Pushed ${image}@$(cat "${IMAGE_DIGEST_DIR}/${MATRIX_DISTRO}.${IMAGE_ARCH}") for linux/${IMAGE_ARCH}."
