#!/bin/bash
set -euo pipefail
umask 077

ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
cd "$ROOT"

ENV_FILE="$ROOT/.env"

if [[ ! -f "$ENV_FILE" ]]; then
  echo "Missing $ENV_FILE." >&2
  exit 1
fi

set -a
# shellcheck source=/dev/null
. "$ENV_FILE"
set +a

if [[ "${DATABASE_MODE:-container}" != container ]]; then
  echo "This rollback-based staging drill requires DATABASE_MODE=container." >&2
  exit 1
fi

: "${POSTGRES_DB:?POSTGRES_DB is missing from .env}"
: "${PHX_HOST:?PHX_HOST is missing from .env}"
: "${PHX_SCHEME:?PHX_SCHEME is missing from .env}"
: "${PHX_URL_PORT:?PHX_URL_PORT is missing from .env}"

if [[ "$PHX_SCHEME" != https ]]; then
  echo "Public staging E2E requires PHX_SCHEME=https." >&2
  exit 1
fi

run_id="$(date -u +%Y%m%d%H%M%S)-$$"
output_dir="$ROOT/output/staging-e2e/$run_id"
base_url="${PHX_SCHEME}://${PHX_HOST}"

if [[ "$PHX_URL_PORT" != 443 ]]; then
  base_url="${base_url}:${PHX_URL_PORT}"
fi

mkdir -p "$output_dir"
chmod 700 "$ROOT/output" "$ROOT/output/staging-e2e" "$output_dir"

fixture_password=$(openssl rand -base64 36 | tr -d '\n')
prepared=0

db_container=$(docker compose ps -q db)

if [[ -z "$db_container" ]]; then
  echo "The ordinary Compose database container is not running." >&2
  exit 1
fi

internal_network_id=$(
  docker inspect "$db_container" |
    jq -r '.[0].NetworkSettings.Networks | to_entries[] | select(.key | endswith("_internal")) | .value.NetworkID' |
    head -n 1
)

if [[ -z "$internal_network_id" ]]; then
  echo "Could not identify the ordinary Compose internal network." >&2
  exit 1
fi

snapshot_database() {
  local destination=$1

  docker compose exec -T db sh -c \
    'psql --no-psqlrc --set ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB"' \
    >"$destination" <<'SQL'
BEGIN READ ONLY;
SELECT 'users' AS table_name, count(*) AS row_count FROM users
UNION ALL SELECT 'users_tokens', count(*) FROM users_tokens
UNION ALL SELECT 'help_requests', count(*) FROM help_requests
UNION ALL SELECT 'messages', count(*) FROM messages
UNION ALL SELECT 'help_assignments', count(*) FROM help_assignments
UNION ALL SELECT 'reports', count(*) FROM reports
UNION ALL SELECT 'reviews', count(*) FROM reviews
UNION ALL SELECT 'audit_events', count(*) FROM audit_events
UNION ALL SELECT 'abuse_signals', count(*) FROM abuse_signals
UNION ALL SELECT 'tracking_sessions', count(*) FROM tracking_sessions
UNION ALL SELECT 'tracking_positions', count(*) FROM tracking_positions
UNION ALL SELECT 'activities', count(*) FROM activities
UNION ALL SELECT 'activity_participants', count(*) FROM activity_participants
UNION ALL SELECT 'activity_messages', count(*) FROM activity_messages
UNION ALL SELECT 'category_proposals', count(*) FROM category_proposals
UNION ALL SELECT 'category_votes', count(*) FROM category_votes
UNION ALL SELECT 'blocks', count(*) FROM blocks
UNION ALL SELECT 'social_identities', count(*) FROM social_identities
ORDER BY table_name;
COMMIT;
SQL
}

run_fixture_tool() {
  local action=$1

  docker run --rm \
    --network "$internal_network_id" \
    --env-file "$ENV_FILE" \
    --env APP_ROLE=migrate \
    --env "WNH_STAGING_E2E_EXPECTED_DATABASE=$POSTGRES_DB" \
    --env WNH_STAGING_E2E_CONFIRM=public-staging-e2e \
    --env "WNH_STAGING_E2E_RUN_ID=$run_id" \
    --env "WNH_STAGING_E2E_PASSWORD=$fixture_password" \
    --env WNH_STAGING_E2E_MANIFEST_PATH=/output/fixture.json \
    --volume "$output_dir:/output" \
    who-need-help:staging-e2e-tools \
    mix wnh.staging_e2e "$action"
}

cleanup() {
  local status=$?
  trap - EXIT HUP INT TERM

  if [[ "$prepared" -eq 1 ]]; then
    if ! run_fixture_tool cleanup >"$output_dir/fixture-cleanup.log" 2>&1; then
      echo "Exact staging E2E cleanup failed; inspect $output_dir." >&2
      status=1
    else
      snapshot_database "$output_dir/database-after.txt"

      if ! diff -u \
        "$output_dir/database-before.txt" \
        "$output_dir/database-after.txt" \
        >"$output_dir/database-cleanup.diff"; then
        echo "Staging E2E cleanup did not restore application table counts." >&2
        status=1
      fi
    fi
  fi

  unset fixture_password
  exit "$status"
}
trap cleanup EXIT HUP INT TERM

curl --fail --silent --show-error "$base_url/healthz/ready" >"$output_dir/public-ready.txt"
snapshot_database "$output_dir/database-before.txt"

docker build --target load_tools --tag who-need-help:staging-e2e-tools . \
  >"$output_dir/tools-build.log"
docker build --tag who-need-help-e2e-tests:local e2e \
  >"$output_dir/browser-build.log"

run_fixture_tool prepare >"$output_dir/fixture-prepare.log"
prepared=1

docker run --rm \
  --network host \
  --user "$(id -u):$(id -g)" \
  --env "BASE_URL=$base_url" \
  --env MAILPIT_URL=http://127.0.0.1:8027 \
  --env "E2E_RUN_ID=$run_id" \
  --env "E2E_FIXTURE_PASSWORD=$fixture_password" \
  --env HOME=/tmp \
  --volume "$output_dir:/work/output" \
  who-need-help-e2e-tests:local \
  npx playwright test --project=chromium tests/mutual-aid.spec.ts

echo "Public staging medicine E2E passed: $base_url"
echo "Evidence: $output_dir"
