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

ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
if [[ -f .env ]]; then
  set -a
  source .env
  set +a
fi
export DRUPAL_BASE_URL
DEFAULT_DRUPAL_URL="http://localhost:${DRUPAL_PORT:-8080}"
DRUPAL_BASE_URL="${DRUPAL_BASE_URL:-$DEFAULT_DRUPAL_URL}"
export KEYCLOAK_BASE_URL
DEFAULT_KEYCLOAK_URL="http://localhost:${KEYCLOAK_PORT:-8081}"
KEYCLOAK_BASE_URL="${KEYCLOAK_BASE_URL:-$DEFAULT_KEYCLOAK_URL}"
MODULE=/opt/drupal/web/modules/custom/saml
COMMAND="${1:-help}"
[[ $# -eq 0 ]] || shift

usage() {
  cat <<'HELP'
Usage: bin/drupal COMMAND [arguments]
  start [--with-idp]  Start Drupal; optionally seed the local Keycloak IdP.
  stop               Stop services, preserving all data.
  restart            Restart existing services.
  refresh            Delete development volumes and reinstall Drupal.
  status             Show container status.
  logs [service]     Follow logs (default: drupal).
  shell              Open Bash in the Drupal container.
  drush ARGS...      Run Drush with the public site URL.
  composer ARGS...   Run Composer in the Drupal project.
  login              Print a one-time administrator login URL.
  lint               Run all local checks (requires Composer and Node).
  lint:php           Run Drupal PHPCS inside the development container.
  coverage [--local] Generate and enforce 100% PHP coverage.
  test [--local]     Run PHPUnit inside Docker or with local dependencies.
  help               Show this help.
HELP
}

case "$COMMAND" in
  help|--help|-h) usage; exit 0 ;;
  lint) exec composer lint "$@" ;;
esac
if [[ "$COMMAND" == coverage && "${1:-}" == --local ]]; then
  shift
  exec composer coverage -- "$@"
fi
if [[ "$COMMAND" == test && "${1:-}" == --local ]]; then
  shift
  exec php vendor/bin/phpunit "$@"
fi
if ! command -v docker >/dev/null; then
  echo 'Docker is required. Install Docker and start its daemon.' >&2
  exit 1
fi
if docker compose version >/dev/null 2>&1; then
  COMPOSE=(docker compose)
elif command -v docker-compose >/dev/null; then
  COMPOSE=(docker-compose)
else
  echo 'Install the Docker Compose plugin or docker-compose.' >&2
  exit 1
fi
COMPOSE+=(--project-directory "$ROOT" --file "$ROOT/compose.yaml")
if ! docker info >/dev/null 2>&1; then
  echo 'Cannot reach Docker. Check its daemon and your Docker context.' >&2
  exit 1
fi

drush() {
  "${COMPOSE[@]}" exec -T drupal drush \
    --root=/opt/drupal/web --uri="$DRUPAL_BASE_URL" "$@"
}

start() {
  mkdir -p .dev/keycloak
  if [[ "${1:-}" == --with-idp ]]; then
    touch .dev/idp-enabled
  fi
  "${COMPOSE[@]}" up -d --build --wait drupal
  "${COMPOSE[@]}" exec -T drupal php "$MODULE/.docker/seed.php"
  if [[ -f .dev/idp-enabled ]]; then
    "${COMPOSE[@]}" --profile idp up -d keycloak
    local ready=0
    local discovery=http://keycloak:8080/realms/saml
    discovery+=/.well-known/openid-configuration
    for ((attempt=0; attempt<90; attempt++)); do
      if "${COMPOSE[@]}" exec -T drupal php -r \
        'exit(@file_get_contents($argv[1]) === false ? 1 : 0);' \
        "$discovery" >/dev/null 2>&1; then
        ready=1
        break
      fi
      sleep 2
    done
    if [[ "$ready" != 1 ]]; then
      echo 'Keycloak is not ready. Run bin/drupal logs keycloak.' >&2
      exit 1
    fi
  fi
  if ! drush status --field=bootstrap 2>/dev/null | grep -q Successful; then
    "${COMPOSE[@]}" exec -T drupal bash "$MODULE/.docker/install.sh"
  fi
  drush en key saml -y
  drush php:script "$MODULE/.docker/configure.php"
  if [[ -f .dev/idp-enabled ]]; then
    drush php:script "$MODULE/.docker/configure-idp.php"
    drush php:script "$MODULE/.docker/configure-admin.php"
  fi
  drush cr
  echo "Drupal: $DRUPAL_BASE_URL"
  echo "SAML settings: $DRUPAL_BASE_URL/admin/config/people/saml"
  if [[ -f .dev/idp-enabled ]]; then
    echo "Keycloak: $KEYCLOAK_BASE_URL (test user: saml.test)"
  fi
  drush uli
}

case "$COMMAND" in
  start) start "$@" ;;
  stop) "${COMPOSE[@]}" --profile idp stop ;;
  restart) "${COMPOSE[@]}" --profile idp restart ;;
  refresh)
    echo 'Deleting this project’s development volumes and reinstalling Drupal.'
    "${COMPOSE[@]}" --profile idp down --volumes --remove-orphans
    start
    ;;
  status) "${COMPOSE[@]}" --profile idp ps ;;
  logs) "${COMPOSE[@]}" logs -f "${1:-drupal}" ;;
  shell) "${COMPOSE[@]}" exec drupal bash ;;
  drush) drush "$@" ;;
  composer) "${COMPOSE[@]}" exec -T drupal composer "$@" ;;
  login) drush uli ;;
  lint:php)
    "${COMPOSE[@]}" exec -T -w "$MODULE" drupal \
      /opt/drupal/vendor/bin/phpcs "$@"
    ;;
  coverage)
    "${COMPOSE[@]}" exec -T -w "$MODULE" \
      -e SAML_TEST_CORE=/opt/drupal/web/core \
      -e COMPOSER_BIN_DIR=/opt/drupal/vendor/bin \
      -e XDEBUG_MODE=coverage drupal php tools/run-coverage.php "$@"
    ;;
  test)
    "${COMPOSE[@]}" exec -T -w "$MODULE" \
      -e SAML_TEST_CORE=/opt/drupal/web/core drupal \
      php /opt/drupal/vendor/bin/phpunit -c phpunit.xml.dist "$@"
    ;;
  *) usage >&2; exit 2 ;;
esac
