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

KEEP_COUNT="${REGISTRY_PACKAGE_KEEP_COUNT:-3}"
API_BASE_URL="${REGISTRY_API_BASE_URL:-https://gitea.banlv-ai.com/api/v1}"
TOKEN="${REGISTRY_PACKAGE_TOKEN:-}"
REGISTRY_IMAGE="${REGISTRY_IMAGE:-${IMAGE:-}}"
DEPLOY_ENV="${DEPLOY_ENV:-}"
CURRENT_IMAGE_TAG="${IMAGE_VERSION_TAG:-}"

if [ -z "$TOKEN" ] && [ -z "${REGISTRY_PACKAGE_VERSIONS_FILE:-}" ]; then
  echo "Missing REGISTRY_PACKAGE_TOKEN" >&2
  exit 1
fi

if [ -z "$REGISTRY_IMAGE" ] || [ -z "$DEPLOY_ENV" ]; then
  echo "Missing REGISTRY_IMAGE/IMAGE or DEPLOY_ENV" >&2
  exit 1
fi

case "$DEPLOY_ENV" in
  test|prod) ;;
  *)
    echo "Unsupported DEPLOY_ENV for package pruning: $DEPLOY_ENV" >&2
    exit 1
    ;;
esac

if ! command -v node >/dev/null 2>&1; then
  echo "node is required for package pruning" >&2
  exit 127
fi

if ! command -v curl >/dev/null 2>&1; then
  echo "curl is required for package pruning" >&2
  exit 127
fi

image_without_tag="${REGISTRY_IMAGE%%:*}"
path_without_registry="${image_without_tag#*/}"
owner="${path_without_registry%%/*}"
package="${path_without_registry#*/}"

if [ "$owner" = "$path_without_registry" ] || [ -z "$owner" ] || [ -z "$package" ]; then
  echo "Could not parse owner/package from REGISTRY_IMAGE: $REGISTRY_IMAGE" >&2
  exit 1
fi

current_version="${CURRENT_IMAGE_TAG##*:}"
version_prefix="${DEPLOY_ENV}-"
latest_version="${DEPLOY_ENV}-latest"
api_base="${API_BASE_URL%/}"

echo "=== prune Gitea container package versions ==="
echo "owner: $owner"
echo "package: $package"
echo "environment: $DEPLOY_ENV"
echo "keep count: $KEEP_COUNT"

versions_json="$(mktemp)"
delete_list="$(mktemp)"
cleanup() {
  rm -f "$versions_json" "$delete_list"
}
trap cleanup EXIT

if [ -n "${REGISTRY_PACKAGE_VERSIONS_FILE:-}" ]; then
  cp "$REGISTRY_PACKAGE_VERSIONS_FILE" "$versions_json"
else
  curl -fsS \
    -H "Authorization: token $TOKEN" \
    -H "Accept: application/json" \
    "$api_base/packages/$owner/container/$package" \
    -o "$versions_json"
fi

KEEP_COUNT="$KEEP_COUNT" \
VERSION_PREFIX="$version_prefix" \
LATEST_VERSION="$latest_version" \
CURRENT_VERSION="$current_version" \
VERSIONS_JSON_FILE="$versions_json" \
node <<'NODE' > "$delete_list"
const fs = require("node:fs");

const file = process.env.VERSIONS_JSON_FILE;
const keepCount = Number.parseInt(process.env.KEEP_COUNT || "3", 10);
const prefix = process.env.VERSION_PREFIX || "";
const latest = process.env.LATEST_VERSION || "";
const current = process.env.CURRENT_VERSION || "";
const raw = JSON.parse(fs.readFileSync(file, "utf8"));
const list = Array.isArray(raw) ? raw : Array.isArray(raw.versions) ? raw.versions : [];

function versionOf(item) {
  return String(item.version || item.name || item.tag_name || "").trim();
}

function createdAtOf(item) {
  return String(
    item.created_at ||
      item.created ||
      item.createdAt ||
      item.published_at ||
      item.updated_at ||
      "",
  );
}

const candidates = list
  .map((item) => ({
    version: versionOf(item),
    createdAt: createdAtOf(item),
  }))
  .filter(({ version }) => {
    if (!version.startsWith(prefix)) return false;
    if (version === latest) return false;
    return true;
  })
  .sort((a, b) => {
    const bTime = Date.parse(b.createdAt);
    const aTime = Date.parse(a.createdAt);
    if (Number.isFinite(bTime) && Number.isFinite(aTime) && bTime !== aTime) {
      return bTime - aTime;
    }
    return b.version.localeCompare(a.version);
  });

const kept = new Set(candidates.slice(0, Math.max(0, keepCount)).map((item) => item.version));
const toDelete = candidates
  .slice(Math.max(0, keepCount))
  .map((item) => item.version)
  .filter((version) => version !== current && !kept.has(version));
process.stdout.write(toDelete.join("\n"));
if (toDelete.length > 0) process.stdout.write("\n");
NODE

if [ ! -s "$delete_list" ]; then
  echo "No old $DEPLOY_ENV package versions to delete."
  exit 0
fi

echo "Package versions selected for deletion:"
sed 's/^/  - /' "$delete_list"

if [ "${PRUNE_DRY_RUN:-}" = "1" ]; then
  echo "Dry run enabled, skip DELETE requests."
  exit 0
fi

while IFS= read -r version; do
  [ -n "$version" ] || continue
  encoded_owner="$(node -e 'process.stdout.write(encodeURIComponent(process.argv[1] || ""))' "$owner")"
  encoded_package="$(node -e 'process.stdout.write(encodeURIComponent(process.argv[1] || ""))' "$package")"
  encoded_version="$(node -e 'process.stdout.write(encodeURIComponent(process.argv[1] || ""))' "$version")"
  curl -fsS \
    -X DELETE \
    -H "Authorization: token $TOKEN" \
    "$api_base/packages/$encoded_owner/container/$encoded_package/$encoded_version" \
    >/dev/null
  echo "Deleted package version: $version"
done < "$delete_list"

echo "=== package prune done ==="
