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

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
api_port="${TIKU_API_PORT:-5091}"
mode="${TIKU_MODE:-mixed}"
rate="${TIKU_RATE:-100}"
duration="${TIKU_DURATION:-30s}"
tenant_code="${TIKU_TENANT_CODE:-demo-crm-school}"
redis_container="${TIKU_REDIS_CONTAINER:-tiku-redis}"
database_name="${TIKU_DATABASE_NAME:-tiku}"
run_stamp="$(date +%Y%m%d-%H%M%S)"
result_dir="${repo_root}/artifacts/performance/${run_stamp}-${mode}-${rate}rps"
api_pid=""

cleanup() {
  if [[ -n "${api_pid}" ]] && kill -0 "${api_pid}" 2>/dev/null; then
    kill "${api_pid}" 2>/dev/null || true
    wait "${api_pid}" 2>/dev/null || true
  fi
  api_pid=""
}
trap cleanup EXIT INT TERM

mkdir -p "${result_dir}"

if ! command -v docker >/dev/null 2>&1; then
  echo "docker is required for the Redis readiness check" >&2
  exit 1
fi
if ! docker inspect "${redis_container}" >/dev/null 2>&1; then
  echo "Redis container '${redis_container}' does not exist" >&2
  exit 1
fi
if [[ "$(docker inspect -f '{{.State.Running}}' "${redis_container}")" != "true" ]]; then
  echo "Redis container '${redis_container}' is not running" >&2
  exit 1
fi
docker exec "${redis_container}" redis-cli ping | grep -qx PONG

if ! command -v psql >/dev/null 2>&1; then
  echo "psql is required to capture PostgreSQL metrics" >&2
  exit 1
fi
psql -d "${database_name}" -Atqc 'select 1' | grep -qx 1

(
  cd "${repo_root}"
  dotnet build TIKU-BACKEND.slnx -c Release --no-restore
)

host_url="http://127.0.0.1:${api_port}"
load_url="${host_url}"

(
  cd "${repo_root}"
  exec env \
    ASPNETCORE_ENVIRONMENT=Development \
    ASPNETCORE_URLS="http://0.0.0.0:${api_port}" \
    ConnectionStrings__Redis=localhost:6379 \
    RateLimiting__Enabled=false \
    BackgroundProcessing__Enabled=false \
    Serilog__MinimumLevel__Default=Warning \
    dotnet run --project Tiku.Api -c Release --no-build --no-launch-profile
) >"${result_dir}/api.log" 2>&1 &
api_pid=$!

ready_body=""
for _ in $(seq 1 60); do
  if ready_body="$(curl -fsS "${host_url}/api/health/ready" 2>/dev/null)"; then
    break
  fi
  if ! kill -0 "${api_pid}" 2>/dev/null; then
    echo "Tiku.Api stopped during startup; see ${result_dir}/api.log" >&2
    exit 1
  fi
  sleep 1
done

if [[ -z "${ready_body}" ]]; then
  echo "Tiku.Api did not become ready; see ${result_dir}/api.log" >&2
  exit 1
fi
printf '%s\n' "${ready_body}" >"${result_dir}/readiness.json"
if ! printf '%s' "${ready_body}" | grep -q '"status":"ready"'; then
  echo "PostgreSQL or Redis is not ready: ${ready_body}" >&2
  exit 1
fi

capture_dependencies() {
  local suffix="$1"
  psql -d "${database_name}" -P pager=off -c \
    "select datname, numbackends, xact_commit, xact_rollback, blks_read, blks_hit, tup_returned, tup_fetched from pg_stat_database where datname = current_database();" \
    >"${result_dir}/postgres-${suffix}.txt"
  docker exec "${redis_container}" redis-cli INFO stats \
    >"${result_dir}/redis-${suffix}.txt"
}

capture_dependencies before
{
  sw_vers
  printf 'logical_cpu: '
  sysctl -n hw.logicalcpu
  printf 'memory_bytes: '
  sysctl -n hw.memsize
  dotnet --info
} >"${result_dir}/host.txt"

set +e
if command -v k6 >/dev/null 2>&1; then
  load_url="${host_url}"
  k6 run \
    --summary-export "${result_dir}/summary.json" \
    -e "TIKU_BASE_URL=${load_url}" \
    -e "TIKU_HOST_HEADER=localhost:${api_port}" \
    -e "TIKU_TENANT_CODE=${tenant_code}" \
    -e "TIKU_MODE=${mode}" \
    -e "TIKU_RATE=${rate}" \
    -e "TIKU_DURATION=${duration}" \
    "${repo_root}/tools/performance/tiku-api.js" \
    | tee "${result_dir}/k6.txt"
  k6_exit=${PIPESTATUS[0]}
else
  load_url="http://host.docker.internal:${api_port}"
  docker run --rm \
    -v "${repo_root}:/work:ro" \
    -v "${result_dir}:/results" \
    grafana/k6:latest \
    run \
    --summary-export /results/summary.json \
    -e "TIKU_BASE_URL=${load_url}" \
    -e "TIKU_HOST_HEADER=localhost:${api_port}" \
    -e "TIKU_TENANT_CODE=${tenant_code}" \
    -e "TIKU_MODE=${mode}" \
    -e "TIKU_RATE=${rate}" \
    -e "TIKU_DURATION=${duration}" \
    /work/tools/performance/tiku-api.js \
    | tee "${result_dir}/k6.txt"
  k6_exit=${PIPESTATUS[0]}
fi
set -e

cleanup
capture_dependencies after
printf 'mode=%s\nrate=%s\nduration=%s\ntenant=%s\nk6_exit=%s\n' \
  "${mode}" "${rate}" "${duration}" "${tenant_code}" "${k6_exit}" \
  >"${result_dir}/run.env"

echo "Results: ${result_dir}"
exit "${k6_exit}"
