#!/usr/bin/env bash
# blue-green-deploy.sh — swap the active soul slot on GKE
#
# Usage:
#   blue-green-deploy.sh --image <image-tag> --slot <blue|green>
#
# What it does:
#   1. Sets the new image on the target slot deployment
#   2. Scales the target slot to 1 replica and waits for it to become ready
#   3. Patches the neuron-mcp Service selector to point at the new slot
#   4. Scales the old slot down to 0 replicas
#
# This script uses kubectl imperatively for the live traffic swap.
# After a successful swap, Argo CD manifests should be updated to reflect
# the new active slot (so Argo CD doesn't revert the replica counts on next sync).
#
# Prerequisites:
#   - kubectl configured with access to neuron-platform cluster
#   - Sufficient RBAC: get/patch/scale Deployments and Services in neuron-prod
#
# Examples:
#   blue-green-deploy.sh --image us-central1-docker.pkg.dev/neuron-785695/neuron-api/neuron-soul:abc12345 --slot green
#   blue-green-deploy.sh --image us-central1-docker.pkg.dev/neuron-785695/neuron-api/neuron-soul:latest --slot blue

set -euo pipefail

NAMESPACE="neuron-prod"
APP="neuron-mcp"
SERVICE="neuron-mcp"

IMAGE=""
NEW_SLOT=""

usage() {
  echo "Usage: $0 --image <image-tag> --slot <blue|green>"
  echo ""
  echo "  --image   Full image URI including tag"
  echo "  --slot    Target slot to deploy to: blue or green"
  exit 1
}

while [[ $# -gt 0 ]]; do
  case $1 in
    --image)
      IMAGE="$2"; shift 2 ;;
    --slot)
      NEW_SLOT="$2"; shift 2 ;;
    -h|--help)
      usage ;;
    *)
      echo "Unknown argument: $1"
      usage ;;
  esac
done

[[ -z "$IMAGE" ]] && { echo "ERROR: --image is required"; usage; }
[[ -z "$NEW_SLOT" ]] && { echo "ERROR: --slot is required"; usage; }
[[ "$NEW_SLOT" != "blue" && "$NEW_SLOT" != "green" ]] && {
  echo "ERROR: --slot must be 'blue' or 'green'"; exit 1
}

# Determine the old (currently active) slot
if [[ "$NEW_SLOT" == "blue" ]]; then
  OLD_SLOT="green"
else
  OLD_SLOT="blue"
fi

NEW_DEPLOYMENT="${APP}-${NEW_SLOT}"
OLD_DEPLOYMENT="${APP}-${OLD_SLOT}"

echo "==> Deploying to slot: ${NEW_SLOT}"
echo "    Image:      ${IMAGE}"
echo "    New deploy: ${NEW_DEPLOYMENT}"
echo "    Old deploy: ${OLD_DEPLOYMENT}"
echo "    Namespace:  ${NAMESPACE}"
echo ""

# Step 1: Update the image on the new slot
echo "[1/4] Setting image on ${NEW_DEPLOYMENT}..."
kubectl set image deployment/"${NEW_DEPLOYMENT}" \
  soul="${IMAGE}" \
  --namespace="${NAMESPACE}"

# Step 2: Scale the new slot up (it may already be at 0)
echo "[2/4] Scaling ${NEW_DEPLOYMENT} to 1 replica..."
kubectl scale deployment/"${NEW_DEPLOYMENT}" \
  --replicas=1 \
  --namespace="${NAMESPACE}"

# Wait for rollout to complete (pod ready)
echo "      Waiting for rollout to complete (timeout: 5m)..."
kubectl rollout status deployment/"${NEW_DEPLOYMENT}" \
  --namespace="${NAMESPACE}" \
  --timeout=5m

echo "      ${NEW_DEPLOYMENT} is ready."

# Step 3: Patch the service selector to point at the new slot
echo "[3/4] Flipping service selector to slot=${NEW_SLOT}..."
kubectl patch service "${SERVICE}" \
  --namespace="${NAMESPACE}" \
  --type=merge \
  --patch="{\"spec\":{\"selector\":{\"app\":\"${APP}\",\"slot\":\"${NEW_SLOT}\"}}}"

echo "      Traffic now routing to ${NEW_SLOT}."

# Step 4: Scale down the old slot
echo "[4/4] Scaling ${OLD_DEPLOYMENT} down to 0 replicas..."
kubectl scale deployment/"${OLD_DEPLOYMENT}" \
  --replicas=0 \
  --namespace="${NAMESPACE}"

echo ""
echo "==> Blue-green swap complete."
echo "    Active slot: ${NEW_SLOT} (${IMAGE})"
echo "    Idle slot:   ${OLD_SLOT} (scaled to 0)"
echo ""
echo "NOTE: Update Argo CD manifests to reflect new state:"
echo "  - deployment-${NEW_SLOT}.yaml: replicas: 1, image: ${IMAGE}"
echo "  - deployment-${OLD_SLOT}.yaml: replicas: 0"
