#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel)"
source "$REPO_ROOT/deployments/lib/lib.sh"

EXPECTED_CLUSTER_ARN="${EXPECTED_CLUSTER_ARN:-arn:aws:eks:us-west-2:227896186585:cluster/o11y-dev-us-west-2-byoc-0303}"
DATAPLANE_ADOPTION_BEFORE_FILE=""
DATAPLANE_ADOPTION_AFTER_FILE=""

if ! declare -f get_helmrelease >/dev/null; then
  get_helmrelease() {
    local server_url="$1"
    local name="$2"
    local region_id="${O11Y_OPS_API_REGION_ID:-aws-us-west-2}"
    local logical_region="${O11Y_OPS_API_LOGICAL_REGION:-us-west-2-byoc-0303}"
    local headers_json

    if [[ -z "${OPS_API_ACCESS_TOKEN:-}" && -n "${O11Y_OPS_API_TOKEN:-}" ]]; then
      OPS_API_ACCESS_TOKEN="$O11Y_OPS_API_TOKEN"
    fi

    mint_ops_api_token >/dev/null
    headers_json="$(build_ops_api_headers "$OPS_API_ACCESS_TOKEN" "$region_id" "$logical_region")"
    ops_api_request GET "$server_url" "helmreleases/${name}" "$headers_json"
  }
fi

validate_context() {
  local current
  current="$(kubectl config current-context)"
  [[ "$current" == "$EXPECTED_CLUSTER_ARN" ]] || { echo "ERROR: current context $current, expected $EXPECTED_CLUSTER_ARN" >&2; return 1; }
}

validate_live_env() {
  : "${O11Y_OPS_API_BASE_URL:?O11Y_OPS_API_BASE_URL is required}"
  : "${AUTH0_CLIENT_ID:?AUTH0_CLIENT_ID is required}"
  : "${AUTH0_CLIENT_SECRET:?AUTH0_CLIENT_SECRET is required}"
}

make_dataplane_tmpfile() {
  local name="$1"
  local temp_path
  temp_path="$(git -C "$REPO_ROOT" rev-parse --path-format=absolute --git-path "${name}.XXXXXX")"
  mktemp "$temp_path"
}

cleanup_dataplane_state() {
  if [[ -n "${DATAPLANE_ADOPTION_BEFORE_FILE:-}" ]]; then
    rm -f "$DATAPLANE_ADOPTION_BEFORE_FILE"
    DATAPLANE_ADOPTION_BEFORE_FILE=""
  fi
  if [[ -n "${DATAPLANE_ADOPTION_AFTER_FILE:-}" ]]; then
    rm -f "$DATAPLANE_ADOPTION_AFTER_FILE"
    DATAPLANE_ADOPTION_AFTER_FILE=""
  fi
}

capture_dataplane_state() {
  local output_file="$1"
  {
    kubectl -n observability get pods -o json | jq -r '
      .items[]
      | select(.metadata.name | test("^(vminsert|vmselect|vmstorage|vmalert|loki-ha)-"))
      | "pod|\(.metadata.name)|\(.metadata.uid)|\(.status.phase)|\([.status.containerStatuses[]? | "\(.name):\(.restartCount)"] | join(","))"
    '
    kubectl -n default get pods -o json | jq -r '
      .items[]
      | select(.metadata.name | startswith("alertmanager-alert-regional-"))
      | "pod|\(.metadata.name)|\(.metadata.uid)|\(.status.phase)|\([.status.containerStatuses[]? | "\(.name):\(.restartCount)"] | join(","))"
    '
    kubectl -n observability get pvc -o json | jq -r '.items[] | "pvc|\(.metadata.name)|\(.status.phase)|\(.spec.storageClassName)"'
  } | sort >"$output_file"
}

verify_helmrelease_ready() {
  local name="$1"
  kubectl -n ops-system wait --for=condition=Ready "helmrelease/${name}" --timeout=5m
  get_helmrelease "${O11Y_OPS_API_BASE_URL:?O11Y_OPS_API_BASE_URL is required}" "$name" | jq -e '
    ([.data.status.conditions[]? | select(.type == "Ready" and .status == "True")] | length) > 0
  ' >/dev/null
}

verify_dataplane_health() {
  local loki_deployment_count

  kubectl -n observability get vmcluster vmcluster >/dev/null
  kubectl -n observability get ingress dataplane-metrics-read >/dev/null
  loki_deployment_count="$(kubectl -n observability get deploy -l app.kubernetes.io/name=loki-ha -o json | jq -r '.items | length')"
  [[ "$loki_deployment_count" -gt 0 ]] || { echo "ERROR: no loki-ha deployments found in observability namespace" >&2; return 1; }
  kubectl -n default get alertmanager alert-regional >/dev/null
}

compare_snapshots() {
  local before="$1"
  local after="$2"
  if ! diff -u "$before" "$after"; then
    echo "ERROR: dataplane state changed during adoption-only step" >&2
    return 1
  fi
}

main() {
  local access_link_check

  validate_live_env
  validate_context
  access_link_check="$REPO_ROOT/deployments/infra-v2/e2e/ops-server-access-link-check.sh"
  if [[ ! -x "$access_link_check" ]]; then
    echo "ERROR: missing $access_link_check; complete the ops-server access-link prerequisite first" >&2
    return 1
  fi
  "$access_link_check"
  trap cleanup_dataplane_state EXIT
  DATAPLANE_ADOPTION_BEFORE_FILE="$(make_dataplane_tmpfile dataplane-adoption-before)"
  DATAPLANE_ADOPTION_AFTER_FILE="$(make_dataplane_tmpfile dataplane-adoption-after)"
  capture_dataplane_state "$DATAPLANE_ADOPTION_BEFORE_FILE"
  verify_helmrelease_ready dataplane-vmcluster
  verify_helmrelease_ready loki-ha
  verify_helmrelease_ready alertmanager-regional
  verify_dataplane_health
  capture_dataplane_state "$DATAPLANE_ADOPTION_AFTER_FILE"
  compare_snapshots "$DATAPLANE_ADOPTION_BEFORE_FILE" "$DATAPLANE_ADOPTION_AFTER_FILE"
}

if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
  main "$@"
fi
