#!/bin/bash

set -euo pipefail

# Configuration
BASE_URL="${CLUSTER_SERVICE_NG_URL:-https://us-west-2-ng-0711.regional-api.staging.aws.tidbcloud.com/api/premium/api/v1beta}"
MAX_WAIT_ATTEMPTS="${MAX_WAIT_ATTEMPTS:-60}"
WAIT_INTERVAL="${WAIT_INTERVAL:-10}"
GITHUB_API_URL="${GITHUB_API_URL:-https://api.github.com}"

# Function to make API calls
api_call() {
  local method="$1"
  local endpoint="$2"
  local url="${BASE_URL}${endpoint}"

  response=$(curl -s -X "$method" "$url" -H "Content-Type: application/json" -w "\n%{http_code}")
  http_code=$(echo "$response" | tail -n1)
  body=$(echo "$response" | sed '$d')

  if [[ "$http_code" -ge 200 && "$http_code" -lt 300 ]]; then
    echo "$body"
  else
    return 1
  fi
}

# Function to list all shared pools
list_sharedpools() {
  api_call "GET" "/sharedPools"
}

# Get the UTC creation date of a GitHub Actions run.
get_github_run_created_date() {
  local run_id="$1"
  local response
  local http_code
  local body
  local created_at

  if [ -z "${GITHUB_TOKEN:-}" ] || [ -z "${GITHUB_REPOSITORY:-}" ]; then
    echo "GITHUB_TOKEN and GITHUB_REPOSITORY are required for run-scoped shared pool IDs." >&2
    return 1
  fi

  response=$(curl -sS -L \
    -H "Authorization: Bearer ${GITHUB_TOKEN}" \
    -H "Accept: application/vnd.github+json" \
    "${GITHUB_API_URL%/}/repos/${GITHUB_REPOSITORY}/actions/runs/${run_id}" \
    -w "\n%{http_code}")
  http_code=$(echo "$response" | tail -n1)
  body=$(echo "$response" | sed '$d')

  if [[ "$http_code" -lt 200 || "$http_code" -ge 300 ]]; then
    echo "Failed to resolve GitHub Actions run ${run_id}: HTTP ${http_code}." >&2
    return 1
  fi

  if ! created_at=$(echo "$body" | jq -er '.created_at | select(type == "string")'); then
    echo "GitHub Actions run ${run_id} has no valid created_at timestamp." >&2
    return 1
  fi

  if [[ ! "$created_at" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}T ]]; then
    echo "GitHub Actions run ${run_id} has an invalid created_at timestamp: ${created_at}." >&2
    return 1
  fi

  echo "${created_at:0:10}"
}

# Return 0 when a pool is old enough to delete, 1 when it must be kept,
# and 2 when its age cannot be determined safely.
sharedpool_is_old_enough() {
  local shared_pool_id="$1"
  local days_in_id
  local run_id
  local run_created_date

  # Legacy IDs: 3-digit prefix + 6-digit epoch day + 10-digit suffix.
  if [[ "$shared_pool_id" =~ ^9980[0-9]{15}$ ]]; then
    days_in_id=${shared_pool_id:3:6}
    [ "$days_in_id" -le "$YESTERDAY_DAYS" ]
    return
  fi

  # Matrix-scoped IDs introduced by PR #6608:
  # 3-digit prefix + 11-digit run ID + 2-digit attempt + 3-digit job index.
  if [[ "$shared_pool_id" =~ ^998[1-9][0-9]{15}$ ]]; then
    run_id=${shared_pool_id:3:11}
    if ! run_created_date=$(get_github_run_created_date "$run_id"); then
      return 2
    fi

    [[ "$run_created_date" < "$TODAY_UTC" ]]
    return
  fi

  echo "Skipping shared pool with unsupported E2E ID format: ${shared_pool_id}." >&2
  return 1
}

# Function to list TiDB clusters for a shared pool
list_tidb_clusters() {
  local shared_pool_id="$1"
  response=$(api_call "GET" "/clusters?sharedPoolId=${shared_pool_id}")
  echo "$response"
}

# Function to list TiDB groups for a cluster
list_tidb_groups() {
  local cluster_id="$1"
  response=$(api_call "GET" "/clusters/${cluster_id}/tidbGroups")
  echo "$response"
}

# Function to delete a TiDB group
delete_tidb_group() {
  local cluster_id="$1"
  local tidb_group_id="$2"
  echo "  -> DELETE /clusters/${cluster_id}/tidbGroups/${tidb_group_id}"
  response=$(api_call "DELETE" "/clusters/${cluster_id}/tidbGroups/${tidb_group_id}" 2>&1) && echo "  -> Response: $response" || echo "  -> Request failed."
}

# Function to delete a TiDB cluster
delete_tidb_cluster() {
  local cluster_id="$1"
  local attempts=0

  while [ $attempts -lt $MAX_WAIT_ATTEMPTS ]; do
    echo "  -> DELETE /clusters/${cluster_id} (attempt $((attempts + 1))/$MAX_WAIT_ATTEMPTS)"
    if response=$(api_call "DELETE" "/clusters/${cluster_id}" 2>&1); then
      echo "  -> Response: $response"
      return 0
    else
      echo "  -> Request failed."
      sleep $WAIT_INTERVAL
      attempts=$((attempts + 1))
    fi
  done

  return 1
}

# Function to delete a shared pool
delete_sharedpool() {
  local shared_pool_id="$1"
  local attempts=0

  while [ $attempts -lt $MAX_WAIT_ATTEMPTS ]; do
    echo "  -> DELETE /sharedPools/${shared_pool_id} (attempt $((attempts + 1))/$MAX_WAIT_ATTEMPTS)"
    if response=$(api_call "DELETE" "/sharedPools/${shared_pool_id}?pruneDataplane=true" 2>&1); then
      echo "  -> Response: $response"
      return 0
    else
      echo "  -> Request failed."
      sleep $WAIT_INTERVAL
      attempts=$((attempts + 1))
    fi
  done

  return 1
}

# Function to wait until TiDB groups are deleted
wait_tidb_groups_deleted() {
  local cluster_id="$1"
  local attempts=0

  while [ $attempts -lt $MAX_WAIT_ATTEMPTS ]; do
    tidb_groups=$(list_tidb_groups "$cluster_id" | jq -r '.tidbGroups // []')
    count=$(echo "$tidb_groups" | jq 'length')

    if [ "$count" -eq 0 ]; then
      return 0
    fi

    sleep $WAIT_INTERVAL
    attempts=$((attempts + 1))
  done

  return 1
}

# Function to wait until TiDB clusters are deleted
wait_tidb_clusters_deleted() {
  local shared_pool_id="$1"
  local attempts=0

  while [ $attempts -lt $MAX_WAIT_ATTEMPTS ]; do
    tidb_clusters=$(list_tidb_clusters "$shared_pool_id" | jq -r '.clusters // []')
    count=$(echo "$tidb_clusters" | jq 'length')

    if [ "$count" -eq 0 ]; then
      return 0
    fi

    sleep $WAIT_INTERVAL
    attempts=$((attempts + 1))
  done

  return 1
}

# Function to cleanup a single shared pool
cleanup_sharedpool() {
  local shared_pool_id="$1"

  echo "Cleaning up shared pool: $shared_pool_id"

  clusters_response=$(list_tidb_clusters "$shared_pool_id")
  cluster_ids=$(echo "$clusters_response" | jq -r '.clusters[]?.id // empty')

  if [ -n "$cluster_ids" ]; then
    echo "Found clusters: $cluster_ids"
    for cluster_id in $cluster_ids; do
      echo "Processing cluster: $cluster_id"
      groups_response=$(list_tidb_groups "$cluster_id")
      group_ids=$(echo "$groups_response" | jq -r '.tidbGroups[]?.id // empty')

      if [ -n "$group_ids" ]; then
        echo "Found tidbGroups: $group_ids"
        for group_id in $group_ids; do
          echo "Deleting tidbGroup: $group_id"
          delete_tidb_group "$cluster_id" "$group_id" || true
        done
        echo "Waiting for tidbGroups to be deleted for cluster: $cluster_id"
        wait_tidb_groups_deleted "$cluster_id"
        echo "TidbGroups deletion completed for cluster: $cluster_id"
      else
        echo "No tidbGroups found for cluster: $cluster_id"
      fi

      echo "Deleting cluster: $cluster_id"
      delete_tidb_cluster "$cluster_id"
    done

    echo "Waiting for all clusters to be deleted for shared pool: $shared_pool_id"
    wait_tidb_clusters_deleted "$shared_pool_id"
    echo "All clusters deleted for shared pool: $shared_pool_id"
  else
    echo "No clusters found for shared pool: $shared_pool_id"
  fi

  echo "Deleting shared pool: $shared_pool_id"
  delete_sharedpool "$shared_pool_id" || true
  echo "Shared pool deletion completed: $shared_pool_id"
}

# Main execution
main() {
  if ! command -v jq &>/dev/null; then
    exit 1
  fi
  # Keep today's resources safe. Legacy IDs carry an epoch day; matrix-scoped
  # IDs carry a GitHub Actions run ID whose creation date must be resolved.
  YESTERDAY_DAYS=$(($(date -u +%s) / 86400 - 1))
  TODAY_UTC=$(date -u +%Y-%m-%d)

  sharedpools_response=$(list_sharedpools)

  all_pool_ids=$(echo "$sharedpools_response" | jq -r '.sharedPools[]? | select(.id | startswith("998")) | .id')
  filtered_pool_ids=()
  age_resolution_failed=0

  for pool_id in $all_pool_ids; do
    if sharedpool_is_old_enough "$pool_id"; then
      filtered_pool_ids+=("$pool_id")
    else
      status=$?
      if [ "$status" -eq 2 ]; then
        age_resolution_failed=1
      fi
    fi
  done

  if [ ${#filtered_pool_ids[@]} -eq 0 ]; then
    return "$age_resolution_failed"
  fi

  pool_count=${#filtered_pool_ids[@]}
  echo "Found $pool_count shared pool(s) to cleanup:"
  for pool_id in "${filtered_pool_ids[@]}"; do
    echo "  - $pool_id"
  done

  for pool_id in "${filtered_pool_ids[@]}"; do
    cleanup_sharedpool "$pool_id" || true
  done

  return "$age_resolution_failed"
}

main "$@"
