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

force=${FORCE:-${1:-false}}
name=${RELEASE:-${2:-participant-portal}}
ns=${NAMESPACE:-${3:-rtgsglobal}}
CLUSTER_NAME=${CLUSTER_NAME:-${4:-}}
AWS_REGION=${AWS_REGION:-eu-west-2}

function set_eks_context {
    if [[ -z "$CLUSTER_NAME" ]]; then
        echo "Error: set CLUSTER_NAME env var or pass as 4th argument"
        exit 1
    fi
    echo "Updating kubeconfig for EKS cluster \"$CLUSTER_NAME\" in $AWS_REGION..."
    aws eks update-kubeconfig --name "$CLUSTER_NAME" --region "$AWS_REGION"
}

function helm_uninstall {
    local name=$1
    if helm status "$name" --namespace "$ns" >/dev/null 2>&1; then
        echo "Cleaning up Helm deployment..."
        helm uninstall "$name" --namespace "$ns" || true
        echo
    else
        echo "No Helm release '$name' found"
    fi
}

function uninstall_nginx {
    if helm status ingress-nginx --namespace ingress-nginx >/dev/null 2>&1; then
        if [[ "${force,,}" == "true" ]]; then
            echo "Deleting ingress-nginx..."
            helm uninstall ingress-nginx --namespace ingress-nginx || true
        else
            echo "(Leaving ingress-nginx in place)"
        fi
        echo
    else
        echo "No Helm release 'ingress-nginx' found"
    fi
}

function uninstall_persistent_volumes {
    local name=$1
    local claims
    claims=$(kubectl get pvc -n "$ns" --no-headers -o custom-columns=":metadata.name" | grep "^$name" || true)
    if [[ -n "$claims" ]]; then
        for pvc in $claims; do
            echo "Deleting PVC $pvc..."
            kubectl delete pvc "$pvc" -n "$ns" || true
        done
    else
        echo "No persistent volumes found"
    fi
}

function uninstall_cnpg {
    if helm status cnpg --namespace cnpg-system >/dev/null 2>&1; then
        if [[ "${force,,}" == "true" ]]; then
            echo "Deleting cnpg..."
            helm uninstall cnpg --namespace cnpg-system || true
        else
            echo "(Leaving cnpg in place)"
        fi
        echo
    else
        echo "No Helm release 'cnpg' found"
    fi
}

function uninstall_ebs_csi_driver {
    if [[ "${force,,}" == "true" ]]; then
        if aws eks describe-addon --cluster-name "$CLUSTER_NAME" --addon-name aws-ebs-csi-driver --region "$AWS_REGION" &>/dev/null; then
            echo "Deleting EBS CSI driver addon..."
            aws eks delete-addon \
                --cluster-name "$CLUSTER_NAME" \
                --addon-name aws-ebs-csi-driver \
                --region "$AWS_REGION"
        else
            echo "No EBS CSI driver addon found"
        fi
    else
        echo "(Leaving EBS CSI driver in place)"
    fi
}

function needs_cert_manager {
    grep -Eq '^[[:space:]]*createIssuer:[[:space:]]*true([[:space:]]|#|$)' ./values-aws.yaml
}

function uninstall_metrics_server {
    if kubectl get deployment metrics-server -n kube-system &>/dev/null; then
        if [[ "${force,,}" == "true" ]]; then
            echo "Deleting metrics-server..."
            kubectl delete -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml || true
        else
            echo "(Leaving metrics-server in place)"
        fi
        echo
    else
        echo "No metrics-server deployment found"
    fi
}

function uninstall_cert_manager {
    if helm status cert-manager --namespace cert-manager >/dev/null 2>&1; then
        if [[ "${force,,}" == "true" ]]; then
            echo "Deleting cert-manager..."
            helm uninstall cert-manager --namespace cert-manager || true
        else
            echo "(Leaving cert-manager in place)"
        fi
        echo
    else
        echo "No Helm release 'cert-manager' found"
    fi
}

# Find the Route 53 hosted zone that owns a host by walking up its labels.
# Echoes the bare zone id, or nothing if no hosted zone covers the name.
function route53_zone_for_host {
    local candidate="$1"
    local zone_id=""
    while [[ "$candidate" == *.* ]]; do
        zone_id=$(aws route53 list-hosted-zones-by-name --dns-name "$candidate" \
            --query "HostedZones[?Name=='${candidate}.'].Id | [0]" --output text 2>/dev/null || true)
        if [[ -n "$zone_id" && "$zone_id" != "None" ]]; then
            echo "${zone_id#/hostedzone/}"
            return 0
        fi
        candidate="${candidate#*.}"
    done
}

# Prompt the user to remove each explicitly configured ingress host from Route 53.
# Uses a sentinel autoHostname so only hosts set in values files are considered —
# the NLB fallback hostname is never managed by Route 53 and needs no cleanup.
function remove_route53_records {
    echo "Checking for Route 53 DNS records created by this deployment..."

    local sentinel="__nlb_auto__"
    local hosts
    hosts=$(helm template "$name" . \
        --values ./values.yaml --values ./values-aws.yaml \
        --set "autoHostname=${sentinel}" 2>/dev/null \
        | awk '/^[[:space:]]*-[[:space:]]+host:[[:space:]]/ {print $3}' | sort -u \
        | grep -v "^${sentinel}$" || true)

    if [[ -z "$hosts" ]]; then
        echo "No explicitly configured ingress hosts found - nothing to remove from Route 53."
        return 0
    fi

    echo
    echo "Everything else has been uninstalled. The following DNS records may still exist in Route 53:"
    while IFS= read -r host; do
        echo "  - $host"
    done <<< "$hosts"
    echo

    while IFS= read -r host; do
        [[ -z "$host" ]] && continue

        local zone_id
        zone_id=$(route53_zone_for_host "$host")
        if [[ -z "$zone_id" ]]; then
            echo "Route 53: no hosted zone found for ${host} - skipping."
            continue
        fi

        local dns_name hosted_zone_id
        dns_name=$(aws route53 list-resource-record-sets --hosted-zone-id "$zone_id" \
            --query "ResourceRecordSets[?Name=='${host}.' && Type=='A'].AliasTarget.DNSName | [0]" \
            --output text 2>/dev/null || true)
        hosted_zone_id=$(aws route53 list-resource-record-sets --hosted-zone-id "$zone_id" \
            --query "ResourceRecordSets[?Name=='${host}.' && Type=='A'].AliasTarget.HostedZoneId | [0]" \
            --output text 2>/dev/null || true)

        if [[ -z "$dns_name" || "$dns_name" == "None" ]]; then
            echo "Route 53: no A record found for ${host} - skipping."
            continue
        fi

        echo -n "Do you want to remove the DNS record for ${host} (-> ${dns_name}) from Route 53? [y/N] "
        read -r answer </dev/tty
        if [[ "${answer,,}" == "y" || "${answer,,}" == "yes" ]]; then
            echo "Route 53: deleting A record for ${host}..."
            local change_id
            change_id=$(aws route53 change-resource-record-sets --hosted-zone-id "$zone_id" \
                --change-batch "{\"Changes\":[{\"Action\":\"DELETE\",\"ResourceRecordSet\":{\"Name\":\"${host}\",\"Type\":\"A\",\"AliasTarget\":{\"HostedZoneId\":\"${hosted_zone_id}\",\"DNSName\":\"${dns_name}\",\"EvaluateTargetHealth\":false}}}]}" \
                --query 'ChangeInfo.Id' --output text 2>/dev/null) || true
            if [[ -n "$change_id" && "$change_id" != "None" ]]; then
                echo "Route 53: waiting for deletion of ${host} to propagate..."
                aws route53 wait resource-record-sets-changed --id "$change_id" || true
                echo "Route 53: ${host} removed."
            else
                echo "Route 53: failed to delete ${host} - remove it manually."
            fi
        else
            echo "Route 53: leaving ${host} in place."
        fi
        echo
    done <<< "$hosts"
}

function delete_secret {
    local secret_name=$1
    if kubectl get secret "$secret_name" -n "$ns" &>/dev/null; then
        echo "Deleting ${secret_name}..."
        kubectl delete secret "$secret_name" -n "$ns" || true
    else
        echo "No secret '${secret_name}' found"
    fi
}

function delete_migration_jobs {
    local jobs
    jobs=$(kubectl get jobs -n "$ns" -l app.kubernetes.io/component=migration --no-headers -o custom-columns=":metadata.name" 2>/dev/null || true)
    if [[ -n "$jobs" ]]; then
        echo "Deleting migration jobs..."
        kubectl delete jobs -n "$ns" -l app.kubernetes.io/component=migration --ignore-not-found || true
    else
        echo "No migration jobs found"
    fi
}

set_eks_context
pushd "$(dirname "${BASH_SOURCE[0]}")/.."
helm_uninstall "$name"
delete_migration_jobs
uninstall_cnpg
uninstall_nginx
uninstall_ebs_csi_driver
uninstall_metrics_server
if needs_cert_manager; then
    uninstall_cert_manager
fi
uninstall_persistent_volumes "$name"
delete_secret portal-tls
delete_secret notifications-tls
remove_route53_records
popd
