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

readonly WP_IMAGE='docker.io/library/wordpress:6.8.2-php8.3-apache'
readonly DB_IMAGE='docker.io/library/mariadb:11.4.5'
readonly CLI_IMAGE='docker.io/library/wordpress:cli-2.11.0-php8.3'
readonly ACF_VERSION='6.3.12'
readonly ACF_SHA256='ad5d7d16a85d0465c73e84e2f8bea915fb3cedd8fb369c85fd86634981d2a5b1'
readonly ACF_URL="https://downloads.wordpress.org/plugin/advanced-custom-fields.${ACF_VERSION}.zip"
readonly ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
readonly RUN_ID="ipz-acf-${$}-$(date +%s)"
readonly NETWORK="${RUN_ID}-net"
readonly DB="${RUN_ID}-db"
readonly WP="${RUN_ID}-wp"
readonly WP_VOLUME="${RUN_ID}-wordpress"
readonly CACHE_VOLUME="${RUN_ID}-cache"
readonly DB_VOLUME="${RUN_ID}-db-data"
readonly ACF_ARCHIVE="$(mktemp "${XDG_CACHE_HOME:-$HOME/.cache}/ipz-acf.XXXXXX.zip")"
readonly OWNER_LOG="${ROOT}/tests/integration/.owner-${RUN_ID}.log"
readonly NATIVE_LOG="${ROOT}/tests/integration/.native-${RUN_ID}.log"
readonly BARRIER_FILE="${ROOT}/tests/integration/.barrier-${RUN_ID}"

child_pids=()
child_logs=("$OWNER_LOG" "$NATIVE_LOG")

bounded_reap() {
  local pid="$1" attempt
  if kill -0 -- "-$pid" 2>/dev/null; then
    kill -TERM -- "-$pid" 2>/dev/null || true
    for attempt in $(seq 1 50); do
      kill -0 -- "-$pid" 2>/dev/null || break
      sleep 0.1
    done
  fi
  if kill -0 -- "-$pid" 2>/dev/null; then
    kill -KILL -- "-$pid" 2>/dev/null || true
    for attempt in $(seq 1 20); do
      kill -0 -- "-$pid" 2>/dev/null || break
      sleep 0.1
    done
  fi
  wait "$pid" 2>/dev/null || true
}

cleanup_resources() {
  local pid log
  set +e
  for pid in "${child_pids[@]}"; do bounded_reap "$pid"; done
  for log in "${child_logs[@]}"; do rm -f -- "$log"; done
  rm -f -- "$BARRIER_FILE" "$ACF_ARCHIVE"
  timeout 20s podman rm -f -v "$WP" >/dev/null 2>&1 || true
  timeout 20s podman rm -f -v "$DB" >/dev/null 2>&1 || true
  timeout 20s podman volume rm -f "$WP_VOLUME" >/dev/null 2>&1 || true
  timeout 20s podman volume rm -f "$CACHE_VOLUME" >/dev/null 2>&1 || true
  timeout 20s podman volume rm -f "$DB_VOLUME" >/dev/null 2>&1 || true
  timeout 20s podman network rm -f "$NETWORK" >/dev/null 2>&1 || true
  set -e
}

on_exit() {
  local status=$?
  trap - EXIT INT TERM HUP
  cleanup_resources
  exit "$status"
}
on_signal() {
  local status="$1"
  trap - EXIT INT TERM HUP
  cleanup_resources
  exit "$status"
}
trap on_exit EXIT
trap 'on_signal 130' INT
trap 'on_signal 143' TERM
trap 'on_signal 129' HUP
cleanup_resources

for image in "$WP_IMAGE" "$DB_IMAGE" "$CLI_IMAGE"; do timeout 300s podman pull --quiet "$image" >/dev/null; done
podman network create --internal "$NETWORK" >/dev/null
podman volume create "$WP_VOLUME" >/dev/null
podman volume create "$CACHE_VOLUME" >/dev/null
podman volume create "$DB_VOLUME" >/dev/null
podman run -d --name "$DB" --network "$NETWORK" -v "$DB_VOLUME:/var/lib/mysql" \
  -e MARIADB_DATABASE=wordpress -e MARIADB_USER=wordpress -e MARIADB_PASSWORD=wordpress \
  -e MARIADB_ROOT_PASSWORD=root-test-only "$DB_IMAGE" >/dev/null

for _ in $(seq 1 120); do
  if podman exec "$DB" sh -c 'mariadb -uroot -p"$MARIADB_ROOT_PASSWORD" -N -e "SELECT 1"' >/dev/null 2>&1; then break; fi
  sleep 1
done
podman exec "$DB" sh -c 'mariadb -uroot -p"$MARIADB_ROOT_PASSWORD" -N -e "SELECT 1"' >/dev/null
podman exec "$DB" sh -c "mariadb -uroot -p\"\$MARIADB_ROOT_PASSWORD\" -e \"GRANT PROCESS ON *.* TO 'wordpress'@'%'; FLUSH PRIVILEGES\"" >/dev/null

podman run -d --name "$WP" --network "$NETWORK" -v "$WP_VOLUME:/var/www/html" \
  -e WORDPRESS_DB_HOST="$DB" -e WORDPRESS_DB_USER=wordpress -e WORDPRESS_DB_PASSWORD=wordpress \
  -e WORDPRESS_DB_NAME=wordpress "$WP_IMAGE" >/dev/null
for _ in $(seq 1 120); do
  if podman exec "$WP" test -f /var/www/html/wp-includes/version.php; then break; fi
  sleep 1
done
podman exec "$WP" test -f /var/www/html/wp-includes/version.php

tar -C "$ROOT/.." -cf - "$(basename "$ROOT")" | podman run --rm --user 0 -i -v "$WP_VOLUME:/var/www/html" "$CLI_IMAGE" sh -c 'mkdir -p /var/www/html/wp-content/plugins && tar -C /var/www/html/wp-content/plugins -xf -'
curl --fail --location --silent --show-error "$ACF_URL" --output "$ACF_ARCHIVE"
printf '%s  %s\n' "$ACF_SHA256" "$ACF_ARCHIVE" | sha256sum -c -
podman run --rm --user 0 -i -v "$CACHE_VOLUME:/cache" "$CLI_IMAGE" sh -c 'cat > /cache/acf.zip' < "$ACF_ARCHIVE"
podman run --rm --user 0 -v "$WP_VOLUME:/var/www/html" -v "$CACHE_VOLUME:/cache:ro" "$CLI_IMAGE" sh -ceu 'cd /var/www/html/wp-content/plugins; unzip -q /cache/acf.zip; chown -R 33:33 /var/www/html/wp-content/plugins'

wpcli() {
  timeout 90s podman run --rm --user 0 --network "$NETWORK" -v "$WP_VOLUME:/var/www/html" -w /var/www/html \
    -e WORDPRESS_DB_HOST="$DB" -e WORDPRESS_DB_USER=wordpress -e WORDPRESS_DB_PASSWORD=wordpress \
    -e WORDPRESS_DB_NAME=wordpress "$CLI_IMAGE" wp --allow-root "$@"
}
run_mode() {
  wpcli eval-file wp-content/plugins/international-press-zone/tests/integration/acf-field-transaction-race.php "$1"
}
start_mode() {
  local mode="$1" log="$2"
  local -n destination="$3"
  setsid timeout 90s podman run --rm --user 0 --network "$NETWORK" -v "$WP_VOLUME:/var/www/html" -w /var/www/html \
    -e WORDPRESS_DB_HOST="$DB" -e WORDPRESS_DB_USER=wordpress -e WORDPRESS_DB_PASSWORD=wordpress \
    -e WORDPRESS_DB_NAME=wordpress "$CLI_IMAGE" wp --allow-root eval-file \
    wp-content/plugins/international-press-zone/tests/integration/acf-field-transaction-race.php "$mode" >"$log" 2>&1 &
  destination=$!
  child_pids+=("$destination")
}
wait_child() {
  local pid="$1" log="$2" label="$3" status
  set +e
  wait "$pid"
  status=$?
  set -e
  if (( status != 0 )); then
    printf 'FAIL: %s exited %d\n' "$label" "$status" >&2
    test ! -f "$log" || command cat "$log" >&2
    return "$status"
  fi
}

wpcli core install --url=http://ipz.test --title=IPZ --admin_user=admin --admin_password=test-only-password --admin_email=test@example.test --skip-email >/dev/null
wpcli plugin activate advanced-custom-fields international-press-zone >/dev/null
run_mode setup >/dev/null
printf 'PASS mode=setup\n'

start_mode owner "$OWNER_LOG" owner_pid
start_mode native "$NATIVE_LOG" native_pid
wait_child "$owner_pid" "$OWNER_LOG" owner
wait_child "$native_pid" "$NATIVE_LOG" native
printf 'PASS mode=owner\nPASS mode=native\n'
run_mode verify >/dev/null
printf 'PASS scenario=transaction-race\n'
run_mode rollback >/dev/null
printf 'PASS scenario=rollback\n'
run_mode nested >/dev/null
printf 'PASS scenario=nested-reentrancy\n'
run_mode cleanup >/dev/null
printf 'PASS mode=database-cleanup\n'

cleanup_resources
for resource in "$WP" "$DB"; do
  ! podman container exists "$resource"
done
for resource in "$WP_VOLUME" "$CACHE_VOLUME" "$DB_VOLUME"; do
  ! podman volume exists "$resource"
done
! podman network exists "$NETWORK"
for resource in "$OWNER_LOG" "$NATIVE_LOG" "$BARRIER_FILE" "$ACF_ARCHIVE"; do
  test ! -e "$resource"
done
printf 'PASS resource-cleanup\n'
printf 'SUMMARY ACF=%s sha256=%s images=%s,%s,%s resource-cleanup=PASS overall=PASS\n' "$ACF_VERSION" "$ACF_SHA256" "$WP_IMAGE" "$DB_IMAGE" "$CLI_IMAGE"
printf 'PASS overall\n'
