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

job_name="${1:-adminfront-tests}"
repo_root="$(pwd)"
tmp_dir=""

cleanup() {
  if [ -n "${tmp_dir:-}" ] && [ -d "$tmp_dir" ]; then
    rm -rf "$tmp_dir" || true
  fi
}

trap "cleanup; exit" INT TERM
trap "cleanup" EXIT

mkdir -p reports
rm -rf adminfront/node_modules

tmp_dir="$(mktemp -d /tmp/baron-sso-adminfront-tests.XXXXXX)"
mkdir -p "$tmp_dir/scripts"
cp "$repo_root/scripts/playwrightHostDeps.cjs" "$tmp_dir/scripts/"

if command -v rsync >/dev/null 2>&1; then
  rsync -rlptD --delete \
    --exclude 'node_modules' \
    --exclude 'playwright-report' \
    --exclude 'test-results' \
    "$repo_root/adminfront/" "$tmp_dir/adminfront/"
  rsync -rlptD --delete \
    --exclude 'node_modules' \
    "$repo_root/common/" "$tmp_dir/common/"
else
  cp -R "$repo_root/adminfront" "$tmp_dir/adminfront"
  cp -R "$repo_root/common" "$tmp_dir/common"
  rm -rf "$tmp_dir/adminfront/node_modules" \
    "$tmp_dir/adminfront/playwright-report" \
    "$tmp_dir/adminfront/test-results"
fi

is_port_available() {
  local port="$1"
  node -e '
    const net = require("net");
    const port = Number(process.argv[1]);
    const server = net.createServer();
    server.once("error", () => process.exit(1));
    server.once("listening", () => server.close(() => process.exit(0)));
    server.listen(port, "127.0.0.1");
  ' "$port"
}

find_available_port() {
  node -e '
    const net = require("net");
    const server = net.createServer();
    server.listen(0, "127.0.0.1", () => {
      const address = server.address();
      process.stdout.write(String(address.port));
      server.close();
    });
  '
}

run_with_retry() {
  local max_attempts="$1"
  shift

  local attempt=1
  local exit_code=0
  while [ "$attempt" -le "$max_attempts" ]; do
    if "$@"; then
      return 0
    fi

    exit_code=$?
    if [ "$attempt" -ge "$max_attempts" ]; then
      return "$exit_code"
    fi

    echo "==> command failed (attempt $attempt/$max_attempts): $*"
    echo "==> retrying in 10 seconds..."
    sleep 10
    attempt=$((attempt + 1))
  done

  return "$exit_code"
}

playwright_install_cmd=(npx playwright install)
playwright_install_desc="npx playwright install"
playwright_project_args=()

has_webkit_host_dependencies() {
  if [ "$(uname -s)" != "Linux" ]; then
    return 0
  fi
  if ! command -v ldconfig >/dev/null 2>&1; then
    return 1
  fi

  local missing=0
  local lib
  for lib in \
    libgtk-4.so.1 \
    libgraphene-1.0.so.0 \
    libxslt.so.1 \
    libevent-2.1.so.7 \
    libopus.so.0 \
    libgstallocators-1.0.so.0 \
    libgstapp-1.0.so.0 \
    libgstpbutils-1.0.so.0 \
    libgstaudio-1.0.so.0 \
    libgsttag-1.0.so.0 \
    libgstvideo-1.0.so.0 \
    libgstgl-1.0.so.0 \
    libgstcodecparsers-1.0.so.0 \
    libgstfft-1.0.so.0 \
    libflite.so.1 \
    libwebpdemux.so.2 \
    libavif.so.16 \
    libharfbuzz-icu.so.0 \
    libwebpmux.so.3 \
    libwayland-server.so.0 \
    libmanette-0.2.so.0 \
    libenchant-2.so.2 \
    libhyphen.so.0 \
    libsecret-1.so.0 \
    libwoff2dec.so.1.0.2 \
    libx264.so; do
    if ! ldconfig -p 2>/dev/null | grep -Fq "$lib"; then
      missing=1
      break
    fi
  done

  [ "$missing" -eq 0 ]
}

if [ "$(id -u)" -eq 0 ]; then
  playwright_install_cmd=(npx playwright install --with-deps)
  playwright_install_desc="npx playwright install --with-deps"
elif command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1; then
  playwright_install_cmd=(npx playwright install --with-deps)
  playwright_install_desc="npx playwright install --with-deps"
elif ! has_webkit_host_dependencies; then
  playwright_install_cmd=(npx playwright install chromium firefox)
  playwright_install_desc="npx playwright install chromium firefox"
  playwright_project_args=(--project=chromium --project=firefox)
  {
    echo "# Adminfront WebKit Skipped"
    echo
    echo "- Reason: WebKit host dependencies are not installed and this user cannot run passwordless sudo."
    echo "- Action: Running Chromium and Firefox projects only."
    echo "- To enable WebKit locally: run \`cd adminfront && npx playwright install-deps webkit\` with sudo privileges."
  } > reports/adminfront-webkit-skipped.md
fi

set +e
(
  cd "$tmp_dir/adminfront"
  run_with_retry 3 npm install -g pnpm
  run_with_retry 3 pnpm install -C ../common --no-frozen-lockfile
) 2>&1 | tee reports/adminfront-install.log
install_exit_code=${PIPESTATUS[0]}
set -e

if [ "$install_exit_code" -ne 0 ]; then
  {
    echo "# Adminfront Test Failure Report"
    echo
    echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`"
    echo "- Job: \`${job_name}\`"
    echo "- Reason: \`Dependency install failed\`"
    echo "- Exit Code: \`$install_exit_code\`"
    echo
    echo "## Command"
    echo "\`cd adminfront && npm install -g pnpm && pnpm install -C ../common --no-frozen-lockfile\`"
    echo
    echo "## Install Log Tail (last 200 lines)"
    echo '```text'
    tail -n 200 reports/adminfront-install.log
    echo '```'
  } > reports/adminfront-test-failure-report.md
  exit 1
fi

set +e
(
  cd "$tmp_dir/adminfront"
  "${playwright_install_cmd[@]}"
) 2>&1 | tee reports/adminfront-provision.log
provision_exit_code=${PIPESTATUS[0]}
set -e

if [ "$provision_exit_code" -ne 0 ]; then
  {
    echo "# Adminfront Test Failure Report"
    echo
    echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`"
    echo "- Job: \`${job_name}\`"
    echo "- Reason: \`Browser provisioning failed\`"
    echo "- Exit Code: \`$provision_exit_code\`"
    echo
    echo "## Command"
    echo "\`cd adminfront && ${playwright_install_desc}\`"
    echo
    echo "## Provision Log Tail (last 200 lines)"
    echo '```text'
    tail -n 200 reports/adminfront-provision.log
    echo '```'
  } > reports/adminfront-test-failure-report.md
  exit 1
fi

set +e
port="${PORT:-5180}"
if ! is_port_available "$port"; then
  fallback_port="$(find_available_port)"
  echo "==> requested PORT=$port is already in use; switching to PORT=$fallback_port"
  port="$fallback_port"
fi
echo "==> adminfront using PORT=$port"
(
  cd "$tmp_dir/adminfront"
  PORT="$port" PLAYWRIGHT_WORKERS="${PLAYWRIGHT_WORKERS:-1}" \
    npx playwright test "${playwright_project_args[@]}"
) 2>&1 | tee reports/adminfront-test.log
test_exit_code=${PIPESTATUS[0]}
set -e

[ -d "$tmp_dir/adminfront/playwright-report" ] && rm -rf reports/adminfront-playwright-report && cp -R "$tmp_dir/adminfront/playwright-report" reports/adminfront-playwright-report || true
[ -d "$tmp_dir/adminfront/test-results" ] && rm -rf reports/adminfront-test-results && cp -R "$tmp_dir/adminfront/test-results" reports/adminfront-test-results || true

if [ "$test_exit_code" -ne 0 ]; then
  {
    echo "# Adminfront Test Failure Report"
    echo
    echo "- Workflow: \`${GITHUB_WORKFLOW:-Code Check}\`"
    echo "- Job: \`${job_name}\`"
    echo "- Exit Code: \`$test_exit_code\`"
    echo
    echo "## Commands"
    echo "1. \`cd adminfront\`"
    echo "2. \`npm install -g pnpm && pnpm install -C ../common --no-frozen-lockfile\`"
    echo "3. \`${playwright_install_desc}\`"
    echo "4. \`npx playwright test\`"
    echo
    echo "## Log Tail (last 200 lines)"
    echo '```text'
    tail -n 200 reports/adminfront-test.log
    echo '```'
  } > reports/adminfront-test-failure-report.md
fi

exit "$test_exit_code"
