#!/usr/bin/env bash
#ddev-generated
## Description: Reset the proving ground to baseline B for a fixture set (Composer code, settings, package files, git tree AND database), then rebuild cache
## Usage: ai-eval-reset [fixture...]
## Example: "ddev ai-eval-reset kb_docs canvas_home"
set -euo pipefail

APPROOT="${DDEV_APPROOT:-/var/www/html}"
BASELINE_DIR="${AI_PG_BASELINE_DIR:-${APPROOT}/.ai-proving-ground}"

# Fixture set must match the set passed to ai-eval-provision so the matching
# baseline pair is restored (see NOTE on the set key in ai-eval-provision).
if [ "$#" -gt 0 ]; then
  FIXTURES=("$@")
else
  # shellcheck disable=SC2206
  FIXTURES=(${AI_PG_FIXTURES:-kb_docs canvas_home})
fi
# Same content-hash derivation as ai-eval-provision, so reset lands on the
# exact pair provision captured (milestone 3). The two calls MUST stay
# identical; abort on failure, never fall back to a naive key.
AI_PG_ROOT="${AI_PG_ROOT:-${APPROOT}/recipes/ai_proving_ground}"
# Plain PHP, not drush: Drupal may not boot until the code is restored.
if ! SET_KEY="$(php "${AI_PG_ROOT}/scripts/hash.php" "${FIXTURES[@]}")"; then
  echo "ERROR: fixture-set hash failed for [${FIXTURES[*]}]; aborting." >&2
  exit 1
fi
if ! [[ "${SET_KEY}" =~ ^[0-9a-f]{12}$ ]]; then
  echo "ERROR: unexpected hash output '${SET_KEY}' for [${FIXTURES[*]}]; aborting." >&2
  exit 1
fi
DB_DUMP="${BASELINE_DIR}/baseline.${SET_KEY}.sql.gz"
BASELINE_REF="${AI_PG_BASELINE_REF:-ai-pg-baseline-${SET_KEY}}"

# Paths whose file-based state a run may touch. Scoped ON PURPOSE so the clean
# step can never remove vendor/ or settings.local.php; Composer code is
# restored by the Composer step below instead.
TRACKED_PATHS=("config/sync" "web/modules/custom" "recipes")

# Scratch paths (untracked custom code folders recorded at provision) are
# cleaned in step 4 instead of refused here.
SITE_PREFIX="${BASELINE_DIR}/site.${SET_KEY}"
SCRATCH_PATHS="$(php "${AI_PG_ROOT}/scripts/site-files.php" scratch-paths "${SITE_PREFIX}" "${APPROOT}")"
(cd "${APPROOT}" && AI_PG_SCRATCH_PATHS="${SCRATCH_PATHS}" bash "${AI_PG_ROOT}/scripts/check-tracked-paths.sh" RESET "${BASELINE_REF}" "${TRACKED_PATHS[@]}")

# Composer code first, so the database is restored onto baseline code. Plain
# PHP, not drush: an attempt can leave Drupal unable to boot.
COMPOSER_PREFIX="${BASELINE_DIR}/composer.${SET_KEY}"
echo "==> [1/5] Restoring Composer code"
set +e
php "${AI_PG_ROOT}/scripts/composer-state.php" check "${COMPOSER_PREFIX}" "${APPROOT}" APG_RESET_COMPOSER_CHANGED
composer_status=$?
set -e
case "${composer_status}" in
  0) echo "    Composer files and packages match baseline." ;;
  3) echo "    WARNING: no Composer baseline for this set; Composer code not restored. Re-provision to record it." >&2 ;;
  2)
    php "${AI_PG_ROOT}/scripts/composer-state.php" restore "${COMPOSER_PREFIX}" "${APPROOT}"
    (cd "${APPROOT}" && composer install --no-interaction --no-progress)
    if ! php "${AI_PG_ROOT}/scripts/composer-state.php" check "${COMPOSER_PREFIX}" "${APPROOT}" APG_RESET_COMPOSER_DRIFT; then
      echo "ERROR: Composer code still differs from baseline after composer install; refusing to continue." >&2
      exit 1
    fi
    echo "    Composer code restored." ;;
  *) echo "ERROR: Composer state check failed; aborting." >&2; exit 1 ;;
esac

# settings*.php and package files: git, Composer and the dump do not cover
# them. Edited packages are reinstalled, since composer install keeps a package
# whose version matches.
echo "==> [2/5] Restoring settings and package files"
if [ -f "${SITE_PREFIX}.json" ]; then
  php "${AI_PG_ROOT}/scripts/site-files.php" restore-settings "${SITE_PREFIX}" "${APPROOT}"
  EDITED="$(php "${AI_PG_ROOT}/scripts/site-files.php" edited-packages "${SITE_PREFIX}" "${APPROOT}")"
  if [ -n "${EDITED}" ]; then
    # shellcheck disable=SC2086
    (cd "${APPROOT}" && composer reinstall --no-interaction --no-progress ${EDITED})
    if [ -n "$(php "${AI_PG_ROOT}/scripts/site-files.php" edited-packages "${SITE_PREFIX}" "${APPROOT}" 2>/dev/null)" ]; then
      echo "APG_RESET_PACKAGE_DRIFT Package files still differ from baseline after composer reinstall." >&2
      exit 1
    fi
    echo "    Edited packages reinstalled."
  fi
else
  echo "    WARNING: no site files baseline for this set; settings, scratch paths and package files not restored. Re-provision to record it." >&2
fi

echo "==> [3/5] Restoring file-based state to '${BASELINE_REF}'"
if git -C "${APPROOT}" rev-parse --verify "${BASELINE_REF}" >/dev/null 2>&1; then
  for p in "${TRACKED_PATHS[@]}"; do
    # Gate on the BASELINE TREE, not the filesystem: `git checkout <ref> --
    # <path>` is fatal on a pathspec with no tracked files (found live on the
    # first disposable-bed reset, 2026-07-18). A path that HAS files on disk
    # but none tracked was already refused above by check-tracked-paths.sh, so
    # what is skipped here is only a path that is empty on both sides.
    if [ -n "$(git -C "${APPROOT}" ls-tree -r --name-only "${BASELINE_REF}" -- "${p}")" ]; then
      git -C "${APPROOT}" checkout "${BASELINE_REF}" -- "${p}"
      git -C "${APPROOT}" clean -fd -- "${p}"
    fi
  done
else
  echo "    WARNING: baseline ref '${BASELINE_REF}' not found; skipping file reset." >&2
fi

echo "==> [4/5] Restoring database from ${DB_DUMP}"
if [ ! -f "${DB_DUMP}" ]; then
  echo "ERROR: baseline DB dump missing (${DB_DUMP}). Run 'ddev ai-eval-provision ${FIXTURES[*]}' first." >&2
  exit 1
fi
drush sql:drop -y
gunzip -c "${DB_DUMP}" | drush sql:cli
# Only now: before the restore the database could still enable a module that
# lives in a scratch path, and Drupal cannot boot without its code.
if [ -f "${SITE_PREFIX}.json" ]; then
  php "${AI_PG_ROOT}/scripts/site-files.php" clean-scratch "${SITE_PREFIX}" "${APPROOT}"
fi
drush php:script --script-path="${AI_PG_ROOT}/scripts" public-files.php -- restore "${BASELINE_DIR}/files.${SET_KEY}"

echo "==> [5/5] Rebuilding cache"
drush cr
drush php:script --script-path="${AI_PG_ROOT}/scripts" versions.php -- reset "${BASELINE_DIR}/versions.${SET_KEY}" "${FIXTURES[@]}"
# Drush 13 logs success to stderr and returns empty stdout when no updates exist.
if ! UPDATE_STATUS="$(drush updatedb:status --format=json)"; then
  echo "APG_RESET_UPDATE_STATUS_ERROR Could not check pending database updates." >&2
  exit 1
fi
printf '%s' "${UPDATE_STATUS}" | php "${AI_PG_ROOT}/scripts/versions.php" pending
drush php:script --script-path="${AI_PG_ROOT}/scripts" grader-tree.php -- check "${BASELINE_DIR}/grader.${SET_KEY}"
echo "OK: proving ground reset to baseline B for set [${FIXTURES[*]}] (hash ${SET_KEY})."
