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

# If nix is available and we are not already in a nix shell, re-enter via nix develop
if [[ -z "${IN_NIX_SHELL:-}" ]] && command -v nix >/dev/null 2>&1; then
  exec nix develop -c "$0" "$@"
fi

WORKDIR=$(mktemp -d)
PD_LOG="${WORKDIR}/flaredb-pd.log"
SERVER_LOG="${WORKDIR}/flaredb-server.log"
DATA_DIR="${WORKDIR}/data"

run_client() {
  local output=""
  local status=0
  local attempt=0
  while (( attempt < 20 )); do
    if output=$(cargo run --quiet --bin flaredb-client -- --pd-addr 127.0.0.1:2479 --addr 127.0.0.1:50052 "$@" 2>&1); then
      printf '%s\n' "${output}" | awk 'NF { last = $0 } END { print last }'
      return 0
    fi
    status=$?
    attempt=$((attempt + 1))
    sleep 1
  done
  printf '%s\n' "${output}" >&2
  return "${status}"
}

cleanup() {
  local exit_code=$?
  if [[ -n "${SERVER_PID:-}" ]]; then
    kill "$SERVER_PID" >/dev/null 2>&1 || true
  fi
  if [[ -n "${PD_PID:-}" ]]; then
    kill "$PD_PID" >/dev/null 2>&1 || true
  fi
  if (( exit_code != 0 )); then
    echo "verify-core failed; logs preserved at ${WORKDIR}" >&2
    [[ -f "${PD_LOG}" ]] && { echo "--- ${PD_LOG} ---" >&2; tail -n 200 "${PD_LOG}" >&2; }
    [[ -f "${SERVER_LOG}" ]] && { echo "--- ${SERVER_LOG} ---" >&2; tail -n 200 "${SERVER_LOG}" >&2; }
    return "${exit_code}"
  fi
  rm -rf "${WORKDIR}"
}
trap cleanup EXIT

echo "Building workspace..."
cargo build

echo "Running tests..."
cargo test

echo "Starting PD..."
cargo run --bin flaredb-pd -- --addr 127.0.0.1:2479 >"${PD_LOG}" 2>&1 &
PD_PID=$!
sleep 2

echo "Starting Server..."
cargo run --bin flaredb-server -- \
  --pd-addr 127.0.0.1:2479 \
  --addr 127.0.0.1:50052 \
  --data-dir "${DATA_DIR}" \
  --namespace-mode raw=eventual \
  --namespace-mode cas=strong \
  >"${SERVER_LOG}" 2>&1 &
SERVER_PID=$!
sleep 2

echo "Running Client Verification..."

echo "Testing TSO..."
TSO_OUTPUT=$(run_client tso)
[[ "${TSO_OUTPUT}" == Timestamp:* ]]

echo "Testing Raw Put/Get..."
run_client --namespace raw raw-put --key foo --value bar >/dev/null
RAW_VALUE=$(run_client --namespace raw raw-get --key foo)
[[ "${RAW_VALUE}" == "bar" ]]

echo "Testing CAS success..."
CAS_SUCCESS=$(run_client --namespace cas cas --key cas1 --value v1 --expected 0)
[[ "${CAS_SUCCESS}" == Success,* ]]

echo "Testing CAS conflict..."
CAS_CONFLICT=$(run_client --namespace cas cas --key cas1 --value v2 --expected 0)
[[ "${CAS_CONFLICT}" == Conflict!* ]]

echo "Verification Complete!"
