#!/usr/bin/env bash
# Ensure Keycloak users are in the GitOps admin group used by weave-gitops (cd.bstein.dev).
# Weave GitOps relies on OIDC; membership in the "admin" group maps to cluster-admin via RBAC.
# Requires: curl, jq. Needs a Keycloak client with realm-management (manage-users/groups).

set -euo pipefail

require() { command -v "$1" >/dev/null 2>&1 || { echo "missing required binary: $1" >&2; exit 1; }; }
require curl; require jq

: "${KEYCLOAK_URL:=https://sso.bstein.dev}"
: "${KEYCLOAK_REALM:=atlas}"
: "${KEYCLOAK_CLIENT_ID:?set KEYCLOAK_CLIENT_ID or export via secret}"
: "${KEYCLOAK_CLIENT_SECRET:?set KEYCLOAK_CLIENT_SECRET or export via secret}"
: "${GITOPS_GROUP:=admin}"
# Comma-separated usernames to sync; set SYNC_ALL_USERS=true to include all Keycloak users.
: "${TARGET_USERNAMES:=bstein}"
: "${SYNC_ALL_USERS:=false}"

fetch_token() {
  curl -fsS -X POST \
    -d "grant_type=client_credentials" \
    -d "client_id=${KEYCLOAK_CLIENT_ID}" \
    -d "client_secret=${KEYCLOAK_CLIENT_SECRET}" \
    "${KEYCLOAK_URL}/realms/${KEYCLOAK_REALM}/protocol/openid-connect/token" \
    | jq -r '.access_token'
}

ensure_group() {
  local token="$1" group="$2" id
  id=$(curl -fsS -H "Authorization: Bearer ${token}" \
    "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/groups?search=${group}" \
    | jq -r --arg g "${group}" '.[] | select(.name==$g) | .id' | head -n1)
  if [[ -n "${id}" ]]; then
    echo "${id}"
    return
  fi
  curl -fsS -H "Authorization: Bearer ${token}" \
    -H "Content-Type: application/json" \
    -d "{\"name\":\"${group}\"}" \
    -X POST "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/groups"
  # Fetch again to get id
  curl -fsS -H "Authorization: Bearer ${token}" \
    "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/groups?search=${group}" \
    | jq -r --arg g "${group}" '.[] | select(.name==$g) | .id' | head -n1
}

user_id_by_name() {
  local token="$1" username="$2"
  curl -fsS -H "Authorization: Bearer ${token}" \
    "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users?username=${username}" \
    | jq -r '.[0].id'
}

add_user_to_group() {
  local token="$1" user_id="$2" group_id="$3" username="$4"
  if [[ -z "${user_id}" ]]; then
    echo "user ${username} not found in Keycloak; skip" >&2
    return
  fi
  curl -fsS -o /dev/null -w '%{http_code}' \
    -H "Authorization: Bearer ${token}" \
    -X PUT "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users/${user_id}/groups/${group_id}" \
    | grep -qE '^(204|409)$' || echo "failed adding ${username} to group" >&2
}

main() {
  local token group_id users=()
  token="$(fetch_token)"
  group_id="$(ensure_group "${token}" "${GITOPS_GROUP}")"

  if [[ "${SYNC_ALL_USERS}" == "true" ]]; then
    readarray -t users < <(curl -fsS -H "Authorization: Bearer ${token}" \
      "${KEYCLOAK_URL}/admin/realms/${KEYCLOAK_REALM}/users?max=500" \
      | jq -r '.[] | select(.enabled==true) | .username')
  else
    IFS=',' read -ra users <<< "${TARGET_USERNAMES}"
  fi

  for user in "${users[@]}"; do
    user="$(echo "${user}" | xargs)"
    [[ -z "${user}" ]] && continue
    add_user_to_group "${token}" "$(user_id_by_name "${token}" "${user}")" "${group_id}" "${user}"
  done
}

main "$@"
