#!/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}"
IMAGE_TAR="${IMAGE_TAR:-}"
PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-prom/prometheus:v2.55.1}"
PROMETHEUS_IMAGE_TAR="${PROMETHEUS_IMAGE_TAR:-}"
GRAFANA_IMAGE="${GRAFANA_IMAGE:-grafana/grafana:11.3.1}"
GRAFANA_IMAGE_TAR="${GRAFANA_IMAGE_TAR:-}"
OUT_DIR="${OUT_DIR:-$REPO_ROOT/target/arm64-installer}"
PACKAGE_PREFIX="${PACKAGE_PREFIX:-ours-rp-arm64-installer}"
TEMPLATE_DIR="${TEMPLATE_DIR:-$REPO_ROOT/deploy/arm64-installer}"
MONITOR_PLATFORM="${MONITOR_PLATFORM:-linux/arm64}"

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

Options:
  --image <tag>       Runtime image tag recorded in package manifest.
  --image-tar <path>  Existing docker save tar/tar.gz to include.
  --prometheus-image <tag>
                      Prometheus image tag to record and package.
  --prometheus-image-tar <path>
                      Existing Prometheus docker save tar/tar.gz to include.
  --grafana-image <tag>
                      Grafana image tag to record and package.
  --grafana-image-tar <path>
                      Existing Grafana docker save tar/tar.gz to include.
  --out-dir <path>    Output directory.
  --prefix <name>     Package directory/tar prefix.
  -h, --help          Show help.

If --image-tar is omitted, the script uses the newest
target/arm64-docker/*.tar.gz file.
USAGE
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --image)
      IMAGE_TAG="$2"
      shift 2
      ;;
    --image-tar)
      IMAGE_TAR="$2"
      shift 2
      ;;
    --prometheus-image)
      PROMETHEUS_IMAGE="$2"
      shift 2
      ;;
    --prometheus-image-tar)
      PROMETHEUS_IMAGE_TAR="$2"
      shift 2
      ;;
    --grafana-image)
      GRAFANA_IMAGE="$2"
      shift 2
      ;;
    --grafana-image-tar)
      GRAFANA_IMAGE_TAR="$2"
      shift 2
      ;;
    --out-dir)
      OUT_DIR="$2"
      shift 2
      ;;
    --prefix)
      PACKAGE_PREFIX="$2"
      shift 2
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "unknown option: $1" >&2
      usage >&2
      exit 2
      ;;
  esac
done

[[ -d "$TEMPLATE_DIR" ]] || {
  echo "missing template dir: $TEMPLATE_DIR" >&2
  exit 2
}

if [[ -z "$IMAGE_TAR" ]]; then
  IMAGE_TAR="$(find "$REPO_ROOT/target/arm64-docker" -maxdepth 1 -type f \( -name '*.tar.gz' -o -name '*.tar' \) -printf '%T@ %p\n' 2>/dev/null | sort -nr | awk 'NR==1 {print $2}')"
fi

[[ -n "$IMAGE_TAR" && -f "$IMAGE_TAR" ]] || {
  cat >&2 <<EOF
missing runtime image tar.

Build one first, for example:
  scripts/docker/build_arm64_runtime_image.sh --image $IMAGE_TAG
EOF
  exit 2
}

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

save_image_if_needed() {
  local image="$1"
  local existing_tar="$2"
  local out_dir="$3"
  local role="$4"
  if [[ -n "$existing_tar" ]]; then
    [[ -f "$existing_tar" ]] || {
      echo "missing $role image tar: $existing_tar" >&2
      exit 2
    }
    printf '%s\n' "$existing_tar"
    return 0
  fi
  if ! docker image inspect "$image" >/dev/null 2>&1; then
    cat >&2 <<EOF
missing local $role image: $image

Prepare it before building the installer package, for example:
  docker pull --platform $MONITOR_PLATFORM $image
EOF
    exit 2
  fi
  local actual_platform
  actual_platform="$(docker image inspect --format '{{.Os}}/{{.Architecture}}' "$image" 2>/dev/null || echo unknown)"
  if [[ "$actual_platform" != "$MONITOR_PLATFORM" ]]; then
    cat >&2 <<EOF
wrong platform for $role image: $image
  expected: $MONITOR_PLATFORM
  actual:   $actual_platform

Pull the ARM64 variant explicitly:
  docker pull --platform $MONITOR_PLATFORM $image
EOF
    exit 2
  fi
  local tar_path="$out_dir/$(safe_tag_name "$image").tar.gz"
  echo "saving $role image to $tar_path" >&2
  docker save "$image" | gzip -c > "$tar_path"
  printf '%s\n' "$tar_path"
}

mkdir -p "$OUT_DIR"
commit="$(git -C "$REPO_ROOT" rev-parse --short HEAD 2>/dev/null || echo unknown)"
timestamp="$(date -u +%Y%m%dT%H%M%SZ)"
package_name="${PACKAGE_PREFIX}-${timestamp}-${commit}"
stage="$OUT_DIR/$package_name"
tar_path="$OUT_DIR/$package_name.tar.gz"

rm -rf "$stage"
rsync -a --delete "$TEMPLATE_DIR"/ "$stage"/
mkdir -p "$stage/images"
cp "$IMAGE_TAR" "$stage/images/"

monitor_image_stage="$OUT_DIR/.monitor-images-$timestamp"
rm -rf "$monitor_image_stage"
mkdir -p "$monitor_image_stage"
prometheus_tar="$(save_image_if_needed "$PROMETHEUS_IMAGE" "$PROMETHEUS_IMAGE_TAR" "$monitor_image_stage" "prometheus")"
grafana_tar="$(save_image_if_needed "$GRAFANA_IMAGE" "$GRAFANA_IMAGE_TAR" "$monitor_image_stage" "grafana")"
cp "$prometheus_tar" "$stage/images/"
cp "$grafana_tar" "$stage/images/"

if [[ -f "$stage/.env.example" ]]; then
  tmp_env="$stage/.env.example.tmp"
  awk -v image="$IMAGE_TAG" -v prometheus="$PROMETHEUS_IMAGE" -v grafana="$GRAFANA_IMAGE" -v monitor_platform="$MONITOR_PLATFORM" '
    BEGIN { done=0 }
    /^RPKI_IMAGE=/ { print "RPKI_IMAGE=" image; done=1; next }
    /^PROMETHEUS_IMAGE=/ { print "PROMETHEUS_IMAGE=" prometheus; next }
    /^GRAFANA_IMAGE=/ { print "GRAFANA_IMAGE=" grafana; next }
    /^MONITOR_PLATFORM=/ { print "MONITOR_PLATFORM=" monitor_platform; next }
    { print }
    END { if (!done) print "RPKI_IMAGE=" image }
  ' "$stage/.env.example" > "$tmp_env"
  mv "$tmp_env" "$stage/.env.example"
fi

cat > "$stage/PACKAGE-MANIFEST.env" <<EOF
package_name=$package_name
created_at_utc=$timestamp
git_commit=$commit
git_status_count=$(git -C "$REPO_ROOT" status --short 2>/dev/null | wc -l | tr -d ' ')
image_tag=$IMAGE_TAG
image_tar=$(basename "$IMAGE_TAR")
image_tar_size_bytes=$(wc -c < "$IMAGE_TAR")
prometheus_image=$PROMETHEUS_IMAGE
prometheus_image_tar=$(basename "$prometheus_tar")
prometheus_image_tar_size_bytes=$(wc -c < "$prometheus_tar")
grafana_image=$GRAFANA_IMAGE
grafana_image_tar=$(basename "$grafana_tar")
grafana_image_tar_size_bytes=$(wc -c < "$grafana_tar")
target_platform=linux/arm64
monitor_platform=$MONITOR_PLATFORM
EOF

chmod +x "$stage"/*.sh "$stage/scripts"/*.sh
tar -C "$OUT_DIR" -czf "$tar_path" "$package_name"
rm -rf "$monitor_image_stage"

{
  echo "package=$tar_path"
  echo "package_dir=$stage"
  echo "package_size_bytes=$(wc -c < "$tar_path")"
  echo "manifest=$stage/PACKAGE-MANIFEST.env"
} > "$OUT_DIR/$package_name.summary.env"

echo "package built: $tar_path"
