#!/usr/bin/env bash
# shellcheck shell=bash
set -euo pipefail
IFS=$'\n\t'

# -----------------------------
# Config (env/.env/flags)
# -----------------------------
: "${GITLAB_URL:=https://gitlab.ellisbs.co.uk}" # default to your home lab
: "${GITLAB_TOKEN:=}"                           # required unless --no-auth
: "${GITLAB_TLS_INSECURE:=false}"               # true to allow self-signed
: "${PER_PAGE:=100}"
: "${MAX_PAGES:=1000}"

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

load_dotenv() {
  # Load minimal KEY=VALUE pairs from .env files (repo root or script dir)
  local f
  for f in ".env" "${SCRIPT_DIR}/.env"; do
    [[ -f $f ]] || continue
    # shellcheck disable=SC2162
    while IFS= read -r line || [[ -n $line ]]; do
      [[ $line =~ ^[A-Z0-9_]+= ]] || continue
      local key="${line%%=*}"
      local val="${line#*=}"
      export "${key}"="${val}"
    done <"$f"
  done
}

parse_common_flags() {
  local no_auth=false
  while [[ $# -gt 0 ]]; do
    case "$1" in
    --url)
      GITLAB_URL="${2:?}"
      shift 2
      ;;
    --token)
      GITLAB_TOKEN="${2:-}"
      shift 2
      ;;
    --insecure)
      GITLAB_TLS_INSECURE=true
      shift
      ;;
    --per-page)
      PER_PAGE="${2:?}"
      shift 2
      ;;
    --max-pages)
      MAX_PAGES="${2:?}"
      shift 2
      ;;
    --no-auth)
      no_auth=true
      shift
      ;;
    --)
      shift
      break
      ;;
    -*)
      printf 'Unknown flag: %s\n' "$1" >&2
      return 2
      ;;
    *) break ;;
    esac
  done
  if [[ $no_auth != "true" && -z ${GITLAB_TOKEN:-} ]]; then
    printf 'ERROR: GITLAB_TOKEN is required (or pass --no-auth)\n' >&2
    return 2
  fi
}

need_jq() {
  command -v jq &>/dev/null || {
    printf 'ERROR: jq is required\n' >&2
    exit 127
  }
}

gitlab_get() {
  # $1: path like /api/v4/users?per_page=...&page=...
  local path="${1:?}"
  local curl_args=(--silent --show-error --fail-with-body --location --max-time 30)
  [[ $GITLAB_TLS_INSECURE == "true" ]] && curl_args+=(--insecure)
  if [[ -n ${GITLAB_TOKEN:-} ]]; then
    curl_args+=(--header "PRIVATE-TOKEN: ${GITLAB_TOKEN}")
  fi
  curl "${curl_args[@]}" "${GITLAB_URL%/}${path}"
}

assert_json_array() {
  jq -e 'type=="array"' &>/dev/null
}

# -----------------------------
# Main
# -----------------------------
load_dotenv
parse_common_flags "$@"
need_jq

page=1
count_total=0

while ((page <= MAX_PAGES)); do
  path="/api/v4/users?per_page=${PER_PAGE}&page=${page}"

  if ! body="$(gitlab_get "$path")"; then
    printf 'ERROR: fetch failed for page %d\n' "$page" >&2
    exit 1
  fi

  sanitized="$(printf '%s' "$body" | tr -d '\000-\037')"

  if ! printf '%s' "$sanitized" | assert_json_array; then
    printf 'ERROR: non-array response on page %d\n' "$page" >&2
    printf '%s\n' "$sanitized" >&2
    exit 1
  fi
  if printf '%s' "$sanitized" | jq -e 'length==0' >/dev/null; then
    break
  fi

  mapfile -t items < <(printf '%s' "$sanitized" | jq -c '.[]')
  ((${#items[@]} == 0)) && break
  printf '%s\n' "${items[@]}"

  count_total=$((count_total + ${#items[@]}))
  page=$((page + 1))
done >&1

printf 'Fetched %d users from %s\n' "$count_total" "$GITLAB_URL" >&2
