#!/usr/bin/env bash
set -e

# -----------------------------------------------------------------------------
# Tear down the rtgs-signing (savy) release from an AWS EKS cluster.
#
# Uses your CURRENT kube context (or $CONTEXT) and refuses obviously-local contexts.
#
# Scope grows by flag (each level includes the previous):
#   (default)          Uninstall the rtgs-signing Helm release.
#                      NOTE: the postgres PVC is OWNED by the CNPG Cluster, so this
#                      also removes the wallet/postgres data and its EBS volume.
#                      That's recoverable on redeploy — the wallet is derived from
#                      wallet.seed (kept in your values), and the agent reconnects
#                      via rtgsInvitation.
#   FORCE=true         Also scrub leftovers helm doesn't: any orphaned CNPG PVC,
#                      the cert-manager TLS secrets, and this release's Route 53
#                      records.
#   PURGE_PREREQS=true Also uninstall SHARED cluster prerequisites (ingress-nginx,
#                      CloudNativePG, cert-manager + the letsencrypt-prod issuer).
#                      DANGER: these are shared — this breaks the participant portal
#                      and anything else in the cluster. Full-decommission only.
#
# Optional env / args:
#   RELEASE          release name         (default: rtgs-signing)  [arg 2]
#   NAMESPACE        namespace            (default: rtgs-signing)
#   CONTEXT          kube context         (default: current context)
#   ROUTE53_ZONE_ID  zone for DNS cleanup (default: auto-detected from host domain)
# -----------------------------------------------------------------------------

# ------
# SETUP:
# ------
this=$(basename "${BASH_SOURCE[0]}")
force=${FORCE:-${1:-false}}
purge=${PURGE_PREREQS:-false}
name=${RELEASE:-${2:-rtgs-signing}}
ns=${NAMESPACE:-rtgs-signing}
context=${CONTEXT:-$(kubectl config current-context)}
force=${force,,}
purge=${purge,,}

kctx=(--context "$context")
hctx=(--kube-context "$context")

# -----------
# GUARDRAILS:
# -----------
case "$context" in
    docker-desktop|kind-*|*minikube*|*rancher-desktop*)
        echo "ERROR: context '$context' looks local. This script targets EKS."
        echo "       Set CONTEXT=<eks-context> to target a cloud cluster."
        exit 1
        ;;
esac

echo "Context : $context"
echo "Release : $name (namespace $ns)"
echo "Flags   : FORCE=$force  PURGE_PREREQS=$purge"
echo

# Capture the release's ingress hosts BEFORE uninstall — needed for DNS cleanup,
# since the Ingress objects are gone once the release is uninstalled.
signing_hosts=$(kubectl "${kctx[@]}" -n "$ns" get ingress \
    -o jsonpath='{range .items[*]}{range .spec.rules[*]}{.host}{"\n"}{end}{end}' 2>/dev/null \
    | sort -u | grep -v '^$' || true)

# ----------
# FUNCTIONS:
# ----------

# uninstall the Helm release (also deletes the CNPG Cluster -> its owned PVC/EBS)
function helm_uninstall {
    if helm "${hctx[@]}" status "$name" -n "$ns" >/dev/null 2>&1; then
        echo "Uninstalling release \"$name\" from namespace \"$ns\"..."
        helm "${hctx[@]}" uninstall "$name" -n "$ns" --wait || true
    else
        echo "Release \"$name\" not found in \"$ns\" (nothing to uninstall)."
    fi
    echo
}

# reclaim any CNPG PVC that outlived the Cluster (releases the EBS volume)
function delete_leftover_pvcs {
    local pvcs pvc
    pvcs=$(kubectl "${kctx[@]}" -n "$ns" get pvc -l cnpg.io/cluster --no-headers \
        -o custom-columns=":metadata.name" 2>/dev/null || true)
    if [[ -z "$pvcs" ]]; then
        echo "No leftover CNPG PVCs."
    else
        for pvc in $pvcs; do
            echo "Deleting leftover PVC $pvc (releases its EBS volume)..."
            kubectl "${kctx[@]}" -n "$ns" delete pvc "$pvc" --ignore-not-found || true
        done
    fi
    echo
}

# remove the cert-manager TLS secrets left behind after the ingresses are gone
function delete_tls_secrets {
    local s
    for s in signing-service-tls didcomm-agent-tls svix-tls; do
        if kubectl "${kctx[@]}" -n "$ns" get secret "$s" >/dev/null 2>&1; then
            echo "Deleting TLS secret $s..."
            kubectl "${kctx[@]}" -n "$ns" delete secret "$s" --ignore-not-found || true
        fi
    done
    echo
}

# delete this release's Route 53 alias records (fetched exactly, so DELETE matches)
function delete_dns {
    if [[ -z "$signing_hosts" ]]; then
        echo "No ingress hosts captured; skipping DNS cleanup."; echo; return
    fi
    local zone_id domain h dnsname zoneid evalhealth
    zone_id=$ROUTE53_ZONE_ID
    if [[ -z "$zone_id" ]]; then
        domain=$(echo "$signing_hosts" | head -1 | rev | cut -d. -f1-2 | rev)
        zone_id=$(aws route53 list-hosted-zones \
            --query "HostedZones[?Name=='${domain}.'].Id | [0]" --output text 2>/dev/null || true)
    fi
    zone_id=${zone_id#/hostedzone/}
    if [[ -z "$zone_id" || "$zone_id" == "None" ]]; then
        echo "Skipping DNS cleanup: no Route 53 zone found (set ROUTE53_ZONE_ID to force)."; echo; return
    fi
    echo "Removing DNS records from Route 53 zone $zone_id..."
    for h in $signing_hosts; do
        read -r dnsname zoneid evalhealth < <(aws route53 list-resource-record-sets \
            --hosted-zone-id "$zone_id" \
            --query "ResourceRecordSets[?Name=='${h}.' && Type=='A'].[AliasTarget.DNSName, AliasTarget.HostedZoneId, AliasTarget.EvaluateTargetHealth] | [0]" \
            --output text 2>/dev/null) || true
        if [[ -z "$dnsname" || "$dnsname" == "None" ]]; then
            echo "  no alias-A record for $h (skipping)"; continue
        fi
        case "${evalhealth,,}" in true) evalhealth=true ;; *) evalhealth=false ;; esac
        echo "  DELETE $h  (alias -> $dnsname)"
        aws route53 change-resource-record-sets --hosted-zone-id "$zone_id" --change-batch "{
            \"Comment\": \"rtgs-signing helm-down-eks\",
            \"Changes\": [{
                \"Action\": \"DELETE\",
                \"ResourceRecordSet\": {
                    \"Name\": \"${h}.\",
                    \"Type\": \"A\",
                    \"AliasTarget\": {
                        \"HostedZoneId\": \"${zoneid}\",
                        \"DNSName\": \"${dnsname}\",
                        \"EvaluateTargetHealth\": ${evalhealth}
                    }
                }
            }]
        }" >/dev/null || echo "  (failed to delete $h — check route53 permissions)"
    done
    echo
}

# uninstall SHARED prerequisites — breaks the participant portal; decommission only
function purge_prereqs {
    local r rel rns
    echo "!!  PURGE_PREREQS: removing SHARED cluster infrastructure."
    echo "!!  This breaks the participant portal and anything else using nginx / cnpg / cert-manager."
    for r in "ingress-nginx:ingress-nginx" "cnpg:cnpg-system" "cert-manager:cert-manager"; do
        rel=${r%%:*}; rns=${r##*:}
        if helm "${hctx[@]}" status "$rel" -n "$rns" >/dev/null 2>&1; then
            echo "Uninstalling $rel (ns $rns)..."
            helm "${hctx[@]}" uninstall "$rel" -n "$rns" || true
        fi
    done
    kubectl "${kctx[@]}" delete clusterissuer letsencrypt-prod --ignore-not-found || true
    echo "(metrics-server left in place — it's an EKS addon.)"
    echo
}

# ------
# LOGIC:
# ------
helm_uninstall

if [[ "$force" == "true" ]]; then
    delete_leftover_pvcs
    delete_tls_secrets
    delete_dns
else
    echo "(FORCE not set — leaving any orphaned PVC, TLS secrets, and Route 53 records."
    echo " Re-run with FORCE=true to scrub those too.)"
    echo
fi

if [[ "$purge" == "true" ]]; then
    purge_prereqs
else
    echo "(Shared prerequisites left in place. Set PURGE_PREREQS=true only to decommission the cluster.)"
    echo
fi

echo "Remaining in namespace $ns:"
kubectl "${kctx[@]}" -n "$ns" get all,pvc,ingress,secret 2>/dev/null || true
echo "Done."
