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

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT="${ROOT:-$(cd "${SCRIPT_DIR}/.." && pwd)}"
RUNNER_LABEL="${RUNNER_LABEL:-amd64}"
ARTIFACT_DIR="${ARTIFACT_DIR:-${ROOT}/.artifacts/integration}"
LEGACY_CLIENT_MANIFEST_PATH="${LEGACY_CLIENT_MANIFEST_PATH:-${ROOT}/testing/pd-compat-tests/legacy-client-version-manifest.yaml}"

rm -rf "${ARTIFACT_DIR}"
mkdir -p "${ARTIFACT_DIR}"

source "${ROOT}/scripts/pd-rs-integration-helper.sh"

declare -a LEGACY_CLIENT_VERSIONS=()
declare -a LEGACY_CLIENT_ENDPOINT_ENVS=()
declare -a LEGACY_CLIENT_IMAGE_ENVS=()
declare -a LEGACY_CLIENT_SLOTS=()
declare -a LEGACY_CLIENT_LOG_DIRS=()
declare -a LEGACY_CLIENT_PD_PIDS=()
declare -a LEGACY_CLIENT_TSO_PIDS=()
declare -a LEGACY_CLIENT_ENDPOINT_VALUES=()
declare -a LEGACY_CLIENT_CLIENT_ENDPOINTS=()
declare -a LEGACY_CLIENT_IMAGES=()
declare -a LEGACY_CLIENT_PD_SOURCES=()
PRIMARY_REAL_ETCD_ENDPOINT=""

sanitize_slot() {
  printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/_/g; s/^_+|_+$//g'
}

load_legacy_client_manifest() {
  python3 - "${LEGACY_CLIENT_MANIFEST_PATH}" <<'PY'
import sys
from pathlib import Path

path = Path(sys.argv[1])
content = path.read_text().splitlines()
entries = []
pending = {}

def flush_pending():
    global pending
    if not pending:
        return
    missing = [
        key for key in ("version", "endpoint_env", "image_env")
        if not pending.get(key)
    ]
    if missing:
        formatted = ", ".join(f"`{key}`" for key in missing)
        raise SystemExit(
            f"legacy client manifest entry missing {formatted} in {path}"
        )
    entries.append(
        (pending["version"], pending["endpoint_env"], pending["image_env"])
    )
    pending = {}

for raw_line in content:
    line = raw_line.strip()
    if not line or line.startswith("#") or line == "legacy_clients:":
        continue
    if line.startswith("- "):
        line = line[2:].strip()
    if ":" not in line:
        continue
    key, raw_value = line.split(":", 1)
    key = key.strip()
    value = raw_value.strip().strip('"').strip("'")
    if key == "version":
        flush_pending()
    if value:
        pending[key] = value

flush_pending()

if not entries:
    raise SystemExit(f"legacy client manifest is empty: {path}")

for version, endpoint_env, image_env in entries:
    print(f"{version}\t{endpoint_env}\t{image_env}")
PY
}

require_manifest_images() {
  local version endpoint_env image_env image_value
  while IFS=$'\t' read -r version endpoint_env image_env; do
    [[ -n "${version}" ]] || continue
    LEGACY_CLIENT_VERSIONS+=("${version}")
    LEGACY_CLIENT_ENDPOINT_ENVS+=("${endpoint_env}")
    LEGACY_CLIENT_IMAGE_ENVS+=("${image_env}")
    image_value="${!image_env:-${PD_IMAGE:-}}"
    if [[ -z "${image_value}" ]]; then
      echo "missing required image env ${image_env} for legacy client version ${version} (and PD_IMAGE fallback is unset)" >&2
      exit 1
    fi
  done < <(load_legacy_client_manifest)
}

start_legacy_client_target() {
  local version="$1"
  local endpoint_env="$2"
  local image_env="$3"
  local image_value="${!image_env:-${PD_IMAGE:-}}"
  local slot

  slot="$(sanitize_slot "${version}")"
  if [[ -z "${slot}" ]]; then
    echo "failed to derive slot name for legacy client version ${version}" >&2
    exit 1
  fi

  PD_IMAGE="${image_value}"
  PD_FORCE_IMAGE=1
  PD_RS_INTEGRATION_BASENAME="pd-rs-integration-${RUNNER_LABEL}-${slot}-${GITHUB_RUN_ID:-manual}-${GITHUB_RUN_ATTEMPT:-1}"
  unset PD_DIR PD_RS_INTEGRATION_DIR PD_IMAGE_DIR LOG_DIR PD_PID TSO_PID PD_SOURCE_KIND PD_SOURCE_DETAIL

  start_pd_rs_integration_env

  local endpoint_value="http://127.0.0.1:${TSO_PORT}"
  local client_endpoint_value="http://127.0.0.1:${CLIENT_PORT}"

  printf -v "${endpoint_env}" '%s' "${endpoint_value}"
  export "${endpoint_env}"

  if [[ -z "${PRIMARY_REAL_ETCD_ENDPOINT}" ]]; then
    PRIMARY_REAL_ETCD_ENDPOINT="${client_endpoint_value}"
  fi

  LEGACY_CLIENT_SLOTS+=("${slot}")
  LEGACY_CLIENT_LOG_DIRS+=("${LOG_DIR}")
  LEGACY_CLIENT_PD_PIDS+=("${PD_PID}")
  LEGACY_CLIENT_TSO_PIDS+=("${TSO_PID}")
  LEGACY_CLIENT_ENDPOINT_VALUES+=("${endpoint_value}")
  LEGACY_CLIENT_CLIENT_ENDPOINTS+=("${client_endpoint_value}")
  LEGACY_CLIENT_IMAGES+=("${image_value}")
  LEGACY_CLIENT_PD_SOURCES+=("${PD_SOURCE_KIND}:${PD_SOURCE_DETAIL}")
}

write_runtime_metadata() {
  {
    printf 'LEGACY_CLIENT_MANIFEST_PATH=%s\n' "${LEGACY_CLIENT_MANIFEST_PATH}"
    printf 'PD_ALLOW_MISSING_GO_TSO_ENDPOINT=%s\n' "${PD_ALLOW_MISSING_GO_TSO_ENDPOINT:-0}"
    printf 'PD_REAL_ETCD_ENDPOINTS=%s\n' "${PRIMARY_REAL_ETCD_ENDPOINT}"
    printf 'RUNNER_LABEL=%s\n' "${RUNNER_LABEL}"
    local index
    for index in "${!LEGACY_CLIENT_VERSIONS[@]}"; do
      printf 'LEGACY_CLIENT_%s_VERSION=%s\n' "${index}" "${LEGACY_CLIENT_VERSIONS[index]}"
      printf 'LEGACY_CLIENT_%s_ENDPOINT_ENV=%s\n' "${index}" "${LEGACY_CLIENT_ENDPOINT_ENVS[index]}"
      printf 'LEGACY_CLIENT_%s_ENDPOINT=%s\n' "${index}" "${LEGACY_CLIENT_ENDPOINT_VALUES[index]}"
      printf 'LEGACY_CLIENT_%s_CLIENT_ENDPOINT=%s\n' "${index}" "${LEGACY_CLIENT_CLIENT_ENDPOINTS[index]}"
      printf 'LEGACY_CLIENT_%s_IMAGE_ENV=%s\n' "${index}" "${LEGACY_CLIENT_IMAGE_ENVS[index]}"
      printf 'LEGACY_CLIENT_%s_IMAGE=%s\n' "${index}" "${LEGACY_CLIENT_IMAGES[index]}"
      printf 'LEGACY_CLIENT_%s_SLOT=%s\n' "${index}" "${LEGACY_CLIENT_SLOTS[index]}"
      printf 'LEGACY_CLIENT_%s_SOURCE=%s\n' "${index}" "${LEGACY_CLIENT_PD_SOURCES[index]}"
    done
  } >"${ARTIFACT_DIR}/summary.env"
}

copy_logs() {
  mkdir -p "${ARTIFACT_DIR}"
  local index log_dir slot
  for index in "${!LEGACY_CLIENT_LOG_DIRS[@]}"; do
    log_dir="${LEGACY_CLIENT_LOG_DIRS[index]}"
    slot="${LEGACY_CLIENT_SLOTS[index]}"
    if [[ -n "${log_dir}" && -d "${log_dir}" ]]; then
      mkdir -p "${ARTIFACT_DIR}/${slot}"
      cp -a "${log_dir}/." "${ARTIFACT_DIR}/${slot}/" 2>/dev/null || true
    fi
  done
}

cleanup() {
  local status=$?
  trap - EXIT
  local index
  for (( index=${#LEGACY_CLIENT_TSO_PIDS[@]}-1; index>=0; index-- )); do
    if [[ -n "${LEGACY_CLIENT_TSO_PIDS[index]:-}" ]]; then
      kill "${LEGACY_CLIENT_TSO_PIDS[index]}" 2>/dev/null || true
      wait "${LEGACY_CLIENT_TSO_PIDS[index]}" 2>/dev/null || true
    fi
  done
  for (( index=${#LEGACY_CLIENT_PD_PIDS[@]}-1; index>=0; index-- )); do
    if [[ -n "${LEGACY_CLIENT_PD_PIDS[index]:-}" ]]; then
      kill "${LEGACY_CLIENT_PD_PIDS[index]}" 2>/dev/null || true
      wait "${LEGACY_CLIENT_PD_PIDS[index]}" 2>/dev/null || true
    fi
  done
  copy_logs
  exit "${status}"
}

trap cleanup EXIT

require_command cargo
require_command git
require_command make
require_command protoc
require_command python3

export PD_ALLOW_MISSING_GO_TSO_ENDPOINT=0

require_manifest_images

for index in "${!LEGACY_CLIENT_VERSIONS[@]}"; do
  start_legacy_client_target \
    "${LEGACY_CLIENT_VERSIONS[index]}" \
    "${LEGACY_CLIENT_ENDPOINT_ENVS[index]}" \
    "${LEGACY_CLIENT_IMAGE_ENVS[index]}"
done

write_runtime_metadata
for index in "${!LEGACY_CLIENT_VERSIONS[@]}"; do
  {
    printf 'version=%s\n' "${LEGACY_CLIENT_VERSIONS[index]}"
    printf 'endpoint_env=%s\n' "${LEGACY_CLIENT_ENDPOINT_ENVS[index]}"
    printf 'endpoint=%s\n' "${LEGACY_CLIENT_ENDPOINT_VALUES[index]}"
    printf 'image_env=%s\n' "${LEGACY_CLIENT_IMAGE_ENVS[index]}"
    printf 'image=%s\n' "${LEGACY_CLIENT_IMAGES[index]}"
    printf 'source=%s\n' "${LEGACY_CLIENT_PD_SOURCES[index]}"
  } >"${ARTIFACT_DIR}/${LEGACY_CLIENT_SLOTS[index]}-runtime.env"
done

make integration-test \
  PD_REAL_ETCD_ENDPOINTS="${PRIMARY_REAL_ETCD_ENDPOINT}" \
  PD_ALLOW_MISSING_GO_TSO_ENDPOINT=0 \
  2>&1 | tee "${ARTIFACT_DIR}/integration-test.log"
