#!/usr/bin/env bash
# Run the dockerized integration tests in isolation: builds the app image, starts it on a
# random port, runs the suite against it, then tears everything down and exits with the
# suite's exit code.
#
# With COVERAGE=1 (see script/integration-coverage) the app runs under Cloverage
# (docker-compose.coverage.yml); after the suite finishes the app is stopped gracefully so
# it writes its report, which is copied to target/coverage/integration.
set -euo pipefail
cd "$(dirname "$0")/.."
root=$PWD
source script/lib/docker.sh

# Picks a random port in [lo, hi] that's currently free on this host; retries on
# collision since another process could grab it first.
free_port_in_range() {
  local lo=$1 hi=$2 port attempt
  for attempt in $(seq 20); do
    port=$((lo + RANDOM % (hi - lo + 1)))
    # A successful connect means something is already listening.
    if ! (exec 3<>"/dev/tcp/127.0.0.1/$port") 2>/dev/null; then
      echo "$port"
      return 0
    fi
  done
  echo "no free port found in range $lo-$hi" >&2
  return 1
}

port=$(free_port_in_range 30000 40000)
echo "[test] starting vibe-app on random port $port${COVERAGE:+ (under coverage instrumentation)}"

compose=(docker compose)
if [[ -n "${COVERAGE:-}" ]]; then
  compose+=(-f docker-compose.yml -f docker-compose.coverage.yml)
fi

use_builder

cd integration-test
export VIBE_PORT=$port

teardown() {
  local status=$?
  trap - EXIT
  "${compose[@]}" down -v || true
  exit "$status"
}
trap teardown EXIT
trap 'exit 130' INT
trap 'exit 143' TERM

# `run` returns the test container's own exit code; `up --abort-on-container-exit` can leak
# the app's SIGTERM exit (143) during teardown instead.
status=0
"${compose[@]}" --ansi never --progress plain run --build --rm integration-test || status=$?

if [[ -n "${COVERAGE:-}" ]]; then
  # SIGTERM is what makes Cloverage write its report, so stop (not kill) the app and pull
  # the report out of the stopped container before `down` removes it.
  out_dir=$root/target/coverage
  echo "[test] stopping vibe-app to flush coverage report"
  "${compose[@]}" stop -t 120 vibe-app || true
  rm -rf "$out_dir/integration"
  mkdir -p "$out_dir"
  if ! "${compose[@]}" cp vibe-app:/app/target/coverage/integration "$out_dir" \
      || [[ ! -f $out_dir/integration/lcov.info ]]; then
    echo "[test] WARNING: no integration coverage report was produced"
  fi
fi

exit "$status"
