#!/usr/bin/env bash
# audit.bootstrap.sh — enforces Rule #1 (no hardcoded paths, all paths/auth
# via .env + paths.php/paths.sh/auth.php). Scans entry-point PHP files
# (public/, pages/, admin/, api/) for two violation classes:
#
#   1. Missing bootstrap: a PHP entry file that doesn't require/include
#      paths.php (and auth.php, unless -p/--paths-only is given)
#   2. Hardcoded paths: any file containing a literal absolute path pattern
#      (e.g. /Users/, /home/, hardcoded DB_HOST-looking strings) instead of
#      going through the constants paths.php defines
#
# Usage:
#   audit.bootstrap.sh -n appname [-p] [-s]
#   audit.bootstrap.sh --all [--apps-root DIR] [--paths-only] [--strict]
#
# -n, --name        audit one app by name (resolved under --apps-root)
#     --all          audit every app under --apps-root
#     --apps-root    root containing apps (default: websites/apps)
# -p, --paths-only   only check for paths.php inclusion, skip auth.php check
# -s, --strict       exit non-zero if ANY violation is found (for CI/pre-deploy)
# -h, --help         show this help

set -euo pipefail

APP_NAME=""
AUDIT_ALL=0
APPS_ROOT="websites/apps"
PATHS_ONLY=0
STRICT=0

usage() {
  grep '^#' "$0" | sed 's/^# \{0,1\}//'
  exit 0
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    -n|--name) APP_NAME="$2"; shift 2 ;;
    --all) AUDIT_ALL=1; shift ;;
    --apps-root) APPS_ROOT="$2"; shift 2 ;;
    -p|--paths-only) PATHS_ONLY=1; shift ;;
    -s|--strict) STRICT=1; shift ;;
    -h|--help) usage ;;
    *) echo "Unknown option: $1" >&2; usage ;;
  esac
done

if [[ -z "$APP_NAME" && $AUDIT_ALL -eq 0 ]]; then
  echo "Error: -n/--name or --all is required" >&2
  exit 1
fi

ENTRY_DIRS=(public pages admin api)
HARDCODE_PATTERNS='(/Users/|/home/[a-zA-Z0-9_-]+/websites|localhost:[0-9]|password\s*=\s*["'"'"'][^"'"'"']+["'"'"'])'

VIOLATIONS=0

audit_one_app() {
  local app_path="$1"
  local app_name
  app_name="$(basename "$app_path")"

  echo "=== ${app_name} ==="

  local found_any=0
  for dir in "${ENTRY_DIRS[@]}"; do
    local target="${app_path}/${dir}"
    [[ -d "$target" ]] || continue

    while IFS= read -r -d '' file; do
      found_any=1
      local rel="${file#"$app_path"/}"
      local missing_paths=0
      local missing_auth=0
      local hardcoded=0

      # Check first 30 lines for the required includes
      local head_content
      head_content="$(head -n 30 "$file")"

      if ! grep -qE "(require|include)(_once)?.*paths\.php" <<< "$head_content"; then
        missing_paths=1
      fi

      if [[ $PATHS_ONLY -eq 0 ]]; then
        if ! grep -qE "(require|include)(_once)?.*auth\.php" <<< "$head_content"; then
          missing_auth=1
        fi
      fi

      if grep -qE "$HARDCODE_PATTERNS" "$file"; then
        hardcoded=1
      fi

      if [[ $missing_paths -eq 1 || $missing_auth -eq 1 || $hardcoded -eq 1 ]]; then
        VIOLATIONS=$((VIOLATIONS + 1))
        echo "  ✗ ${rel}"
        [[ $missing_paths -eq 1 ]] && echo "      - missing paths.php include"
        [[ $missing_auth -eq 1 ]] && echo "      - missing auth.php include"
        [[ $hardcoded -eq 1 ]] && echo "      - hardcoded path/credential pattern found"
      fi
    done < <(find "$target" -name '*.php' -type f -print0)
  done

  if [[ $found_any -eq 0 ]]; then
    echo "  (no entry-point PHP files found)"
  elif [[ $VIOLATIONS -eq 0 ]]; then
    echo "  clean"
  fi
  echo
}

if [[ $AUDIT_ALL -eq 1 ]]; then
  for app_path in "$APPS_ROOT"/*/; do
    [[ -d "$app_path" ]] || continue
    audit_one_app "${app_path%/}"
  done
else
  APP_PATH="${APPS_ROOT}/${APP_NAME}"
  if [[ ! -d "$APP_PATH" ]]; then
    echo "Error: ${APP_PATH} not found" >&2
    exit 1
  fi
  audit_one_app "$APP_PATH"
fi

echo "Total violations: ${VIOLATIONS}"

if [[ $STRICT -eq 1 && $VIOLATIONS -gt 0 ]]; then
  exit 2
fi
exit 0
