#!/usr/bin/env bash
#───────────────────────────────────────────────────────────────────────────────
#  Script : cleanup.sh
#  Author : Mihai Criveti
#  Purpose: Prune old or unused GHCR container versions for IBM's MCP Context Forge
#  Copyright 2025
#  SPDX-License-Identifier: Apache-2.0
#
#  Description:
#    This script safely manages container versions in GitHub Container Registry
#    (ghcr.io) under the IBM organization, specifically targeting the
#    `mcp-context-forge` package. It supports interactive and non-interactive
#    deletion modes to help you keep the container registry clean.
#
#    Features:
#    - Dry-run by default to avoid accidental deletion
#    - Tag whitelisting with regular expression matching
#    - GitHub CLI integration with scope validation
#    - CI/CD-compatible via environment overrides
#
#  Requirements:
#    - GitHub CLI (gh) v2.x with appropriate scopes
#    - jq (command-line JSON processor)
#
#  Required Token Scopes:
#    delete:packages
#
#  Authentication Notes:
#    Authenticate with:
#      gh auth refresh -h github.com -s read:packages,delete:packages
#    Or:
#      gh auth logout
#      gh auth login --scopes "read:packages,delete:packages,write:packages,repo,read:org,gist"
#
#    Verify authentication with:
#      gh auth status -t
#
#  Environment Variables:
#    GITHUB_TOKEN / GH_TOKEN : GitHub token with required scopes
#    DRY_RUN                 : Set to "false" to enable actual deletions (default: true)
#
#  Usage:
#    ./cleanup.sh                 # Dry-run with confirmation prompt
#    DRY_RUN=false ./cleanup.sh --yes  # Actual deletion without prompt (for CI)
#
#───────────────────────────────────────────────────────────────────────────────

set -euo pipefail

##############################################################################
# 1. PICK A TOKEN
##############################################################################
NEEDED_SCOPES="delete:packages"

if [[ -n "${GITHUB_TOKEN:-}" ]]; then
  TOKEN="$GITHUB_TOKEN"
elif [[ -n "${GH_TOKEN:-}" ]]; then
  TOKEN="$GH_TOKEN"
else
  # fall back to whatever gh already has
  if ! TOKEN=$(gh auth token 2>/dev/null); then
    echo "❌  No token exported and gh not logged in. Fix with:"
    echo "    gh auth login  (or export GITHUB_TOKEN)"
    exit 1
  fi
fi
export GH_TOKEN="$TOKEN"   # gh api uses this

# Fixed scope checking - check for both required scopes individually
if scopes=$(gh auth status --show-token 2>/dev/null | grep -oP 'Token scopes: \K.*' || echo ""); then
  missing_scopes=()

  # if ! echo "$scopes" | grep -q "read:packages"; then
  #   missing_scopes+=("read:packages")
  # fi

  if ! echo "$scopes" | grep -q "delete:packages"; then
    missing_scopes+=("delete:packages")
  fi

  if [[ ${#missing_scopes[@]} -gt 0 ]]; then
    echo "⚠️  Your token scopes are [$scopes] - but you're missing: [$(IFS=','; echo "${missing_scopes[*]}")]"
    echo "    Run: gh auth refresh -h github.com -s $NEEDED_SCOPES"
    exit 1
  fi
else
  echo "⚠️  Could not verify token scopes. Proceeding anyway..."
fi

##############################################################################
# 2. CONFIG
##############################################################################
ORG="ibm"
PKG="mcp-context-forge"
KEEP_TAGS=( "0.1.0" "v0.1.0" "0.1.1" "v0.1.1" "0.2.0" "v0.2.0" "0.3.0" "v0.3.0" "0.4.0" "v0.4.0" "0.5.0" "v0.5.0" "0.6.0" "v0.6.0" "0.7.0" "v0.7.0" "0.8.0" "v0.8.0" "latest" )
PER_PAGE=100

DRY_RUN=${DRY_RUN:-true}          # default safe
ASK_CONFIRM=true
[[ ${1:-} == "--yes" ]] && ASK_CONFIRM=false
KEEP_REGEX="^($(IFS='|'; echo "${KEEP_TAGS[*]}"))$"

##############################################################################
# 3. MAIN
##############################################################################
delete_ids=()

echo "📦  Scanning ghcr.io/${ORG}/${PKG} ..."

# Process versions and collect IDs to delete
while IFS= read -r row; do
  id=$(jq -r '.id' <<<"$row")
  digest=$(jq -r '.digest' <<<"$row")
  tags_csv=$(jq -r '.tags | join(",")' <<<"$row")
  keep=$(jq -e --arg re "$KEEP_REGEX" 'any(.tags[]?; test($re))' <<<"$row" 2>/dev/null) || keep=false

  if [[ $keep == true ]]; then
    printf "✅  KEEP    %s  [%s]\n" "$digest" "$tags_csv"
  else
    printf "🗑️   DELETE  %s  [%s]\n" "$digest" "$tags_csv"
    delete_ids+=("$id")
  fi
done < <(gh api -H "Accept: application/vnd.github+json" \
            "/orgs/${ORG}/packages/container/${PKG}/versions?per_page=${PER_PAGE}" \
            --paginate | \
         jq -cr --arg re "$KEEP_REGEX" '
           .[] |
           {
             id,
             digest: .metadata.container.digest,
             tags: (.metadata.container.tags // [])
           }
         ')

##############################################################################
# 4. CONFIRMATION & DELETION
##############################################################################
if [[ ${#delete_ids[@]} -eq 0 ]]; then
  echo "✨  Nothing to delete!"
  exit 0
fi

if [[ $DRY_RUN == true ]]; then
  if [[ $ASK_CONFIRM == true ]]; then
    echo
    read -rp "Proceed to delete the ${#delete_ids[@]} versions listed above? (y/N) " reply
    [[ $reply =~ ^[Yy]$ ]] || { echo "Aborted - nothing deleted."; exit 0; }
  fi
  echo "🚀  Re-running in destructive mode ..."
  DRY_RUN=false exec "$0" --yes
else
  echo "🗑️  Deleting ${#delete_ids[@]} versions..."
  for id in "${delete_ids[@]}"; do
    if gh api -X DELETE -H "Accept: application/vnd.github+json" \
              "/orgs/${ORG}/packages/container/${PKG}/versions/${id}" >/dev/null 2>&1; then
      echo "✅  Deleted version ID: $id"
    else
      echo "❌  Failed to delete version ID: $id"
    fi
  done
  echo "Done."
fi
