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

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"

IMAGE_TAG="${IMAGE_TAG:-ours-rp-runtime-arm64:dev}"
BUILDER_IMAGE="${BUILDER_IMAGE:-ours-rp-base-rust-amd64:1-bookworm}"
RUNTIME_IMAGE="${RUNTIME_IMAGE:-ours-rp-base-debian-arm64:bookworm-slim}"
OUT_DIR="${OUT_DIR:-$REPO_ROOT/target/arm64-docker}"
DOCKERFILE="${DOCKERFILE:-$REPO_ROOT/docker/ours-rp-runtime.Dockerfile}"
BUILDER_NAME="${BUILDER_NAME:-default}"
INSTALL_BINFMT="${INSTALL_BINFMT:-1}"
SAVE_IMAGE="${SAVE_IMAGE:-1}"
LOAD_IMAGE="${LOAD_IMAGE:-1}"

usage() {
  cat <<'USAGE'
Usage:
  scripts/docker/build_arm64_runtime_image.sh [options]

Options:
  --image <tag>       Docker image tag (default: ours-rp-runtime-arm64:dev)
  --out-dir <path>    Directory for docker save tar.gz (default: target/arm64-docker)
  --dockerfile <path> Dockerfile path
  --builder <name>    buildx builder name
  --no-binfmt         Do not install binfmt/qemu
  --no-save           Build image but do not docker save it
  --no-load           Use buildx output tar instead of --load
  -h, --help          Show this help
USAGE
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --image)
      IMAGE_TAG="$2"
      shift 2
      ;;
    --out-dir)
      OUT_DIR="$2"
      shift 2
      ;;
    --dockerfile)
      DOCKERFILE="$2"
      shift 2
      ;;
    --builder)
      BUILDER_NAME="$2"
      shift 2
      ;;
    --no-binfmt)
      INSTALL_BINFMT=0
      shift
      ;;
    --no-save)
      SAVE_IMAGE=0
      shift
      ;;
    --no-load)
      LOAD_IMAGE=0
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "unknown option: $1" >&2
      usage >&2
      exit 2
      ;;
  esac
done

require_command() {
  command -v "$1" >/dev/null 2>&1 || {
    echo "missing required command: $1" >&2
    exit 2
  }
}

safe_tag_name() {
  printf '%s' "$1" | tr '/:' '--'
}

require_command docker
mkdir -p "$OUT_DIR"

require_docker_image() {
  local image="$1"
  if ! docker image inspect "$image" >/dev/null 2>&1; then
    cat >&2 <<EOF
missing required local Docker image: $image

This script intentionally builds with local base image tags to avoid
multi-architecture tag ambiguity during cross builds.

Prepare the default base tags with:
  docker pull --platform linux/amd64 rust:1-bookworm
  docker tag rust:1-bookworm ours-rp-base-rust-amd64:1-bookworm
  docker pull --platform linux/arm64 debian:bookworm-slim
  docker tag debian:bookworm-slim ours-rp-base-debian-arm64:bookworm-slim
EOF
    exit 2
  fi
}

require_docker_image "$BUILDER_IMAGE"
require_docker_image "$RUNTIME_IMAGE"

if [[ "$INSTALL_BINFMT" == "1" ]]; then
  echo "installing binfmt/qemu for arm64"
  docker run --rm --privileged tonistiigi/binfmt --install arm64
fi

if [[ "$BUILDER_NAME" != "default" ]] && ! docker buildx inspect "$BUILDER_NAME" >/dev/null 2>&1; then
  docker buildx create --name "$BUILDER_NAME" --driver docker-container --use >/dev/null
else
  docker buildx use "$BUILDER_NAME" >/dev/null
fi
docker buildx inspect --bootstrap >/dev/null

metadata_path="$OUT_DIR/$(safe_tag_name "$IMAGE_TAG").build-metadata.json"
tar_path="$OUT_DIR/$(safe_tag_name "$IMAGE_TAG").tar.gz"
build_log="$OUT_DIR/$(safe_tag_name "$IMAGE_TAG").build.log"

echo "building linux/arm64 image: $IMAGE_TAG"
echo "repo: $REPO_ROOT"
echo "dockerfile: $DOCKERFILE"
echo "builder_image: $BUILDER_IMAGE"
echo "runtime_image: $RUNTIME_IMAGE"
start_epoch="$(date +%s)"

if [[ "$LOAD_IMAGE" == "1" ]]; then
  docker buildx build \
    --platform linux/arm64 \
    --builder "$BUILDER_NAME" \
    --load \
    --build-arg BUILDKIT_INLINE_CACHE=1 \
    --build-arg "BUILDER_IMAGE=$BUILDER_IMAGE" \
    --build-arg "RUNTIME_IMAGE=$RUNTIME_IMAGE" \
    --metadata-file "$metadata_path" \
    -t "$IMAGE_TAG" \
    -f "$DOCKERFILE" \
    "$REPO_ROOT" 2>&1 | tee "$build_log"
else
  raw_tar_path="$OUT_DIR/$(safe_tag_name "$IMAGE_TAG").tar"
  docker buildx build \
    --platform linux/arm64 \
    --builder "$BUILDER_NAME" \
    --output "type=docker,dest=$raw_tar_path" \
    --build-arg BUILDKIT_INLINE_CACHE=1 \
    --build-arg "BUILDER_IMAGE=$BUILDER_IMAGE" \
    --build-arg "RUNTIME_IMAGE=$RUNTIME_IMAGE" \
    --metadata-file "$metadata_path" \
    -t "$IMAGE_TAG" \
    -f "$DOCKERFILE" \
    "$REPO_ROOT" 2>&1 | tee "$build_log"
  gzip -f "$raw_tar_path"
  tar_path="${raw_tar_path}.gz"
fi

elapsed_secs=$(( $(date +%s) - start_epoch ))

if [[ "$SAVE_IMAGE" == "1" && "$LOAD_IMAGE" == "1" ]]; then
  echo "saving image to $tar_path"
  docker save "$IMAGE_TAG" | gzip -c > "$tar_path"
fi

{
  echo "image=$IMAGE_TAG"
  echo "platform=linux/arm64"
  echo "builder_image=$BUILDER_IMAGE"
  echo "runtime_image=$RUNTIME_IMAGE"
  echo "elapsed_secs=$elapsed_secs"
  echo "metadata=$metadata_path"
  echo "tar=$tar_path"
  echo "tar_size_bytes=$(wc -c < "$tar_path" 2>/dev/null || echo 0)"
  echo "git_commit=$(git -C "$REPO_ROOT" rev-parse --short HEAD 2>/dev/null || echo unknown)"
  echo "git_status_count=$(git -C "$REPO_ROOT" status --short 2>/dev/null | wc -l | tr -d ' ')"
  echo "built_at_utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
} > "$OUT_DIR/$(safe_tag_name "$IMAGE_TAG").build-summary.env"

echo "build complete: elapsed=${elapsed_secs}s tar=$tar_path"
