#!/bin/bash
# mint-grafana-service-account-token.sh
#
# Create a Grafana service-account API token on THIS host's local Grafana and
# print it (and only it) to stdout. Used to wire each box's local Grafana
# (Prometheus datasource: dshackle + node_exporter + cadvisor) into the DRPC
# insights MCP server's grafana_servers.yaml.
#
# Idempotent service account, fresh token on every call (token name carries a
# timestamp), so it is safe to run repeatedly. Diagnostics go to stderr; stdout
# is just the token, so callers can capture it directly:
#
#     TOKEN=$(./utils/mint-grafana-service-account-token.sh)
#
# Reads ADMIN_USER / ADMIN_PASSWORD / DOMAIN from the deploy .env (or the
# environment; environment wins). Override target/role via env or args:
#     GRAFANA_URL=https://grafana.host  ./utils/mint-grafana-service-account-token.sh [sa_name] [role]
# Defaults: sa_name=drpc-insights-ro, role=Viewer.
#
# Requires: curl, jq. Works against Grafana >=9 (service accounts API).
set -euo pipefail

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

# --- load .env (environment already set wins; otherwise source nearest .env) ---
for envf in "$PWD/.env" "$SCRIPT_DIR/../.env" "$SCRIPT_DIR/../../.env"; do
    if [ -f "$envf" ]; then set -a; . "$envf" 2>/dev/null || true; set +a; break; fi
done

ADMIN_USER="${ADMIN_USER:-admin}"
ADMIN_PASSWORD="${ADMIN_PASSWORD:-admin}"
SA_NAME="${1:-drpc-insights-ro}"
ROLE="${2:-Viewer}"

# --- resolve grafana base url (matches grafana_servers.yaml: grafana.<DOMAIN>) ---
if [ -n "${GRAFANA_URL:-}" ]; then
    BASE="$GRAFANA_URL"
elif [ -n "${DOMAIN:-}" ]; then
    BASE="https://grafana.${DOMAIN}"
else
    BASE="http://localhost:3000"
fi

log() { echo "[mint] $*" >&2; }
CURL=(curl -fsS --ipv4 -m 20 -u "${ADMIN_USER}:${ADMIN_PASSWORD}" -H "Content-Type: application/json")

command -v jq >/dev/null 2>&1 || { log "ERROR: jq not found"; exit 1; }
log "grafana=$BASE sa=$SA_NAME role=$ROLE"

# --- find existing service account, else create it (idempotent) ---
sa_id="$("${CURL[@]}" "$BASE/api/serviceaccounts/search?query=${SA_NAME}" 2>/dev/null \
    | jq -r --arg n "$SA_NAME" '.serviceAccounts[]? | select(.name==$n) | .id' | head -n1 || true)"

if [ -z "${sa_id:-}" ] || [ "$sa_id" = "null" ]; then
    log "creating service account '${SA_NAME}'"
    sa_id="$("${CURL[@]}" -X POST "$BASE/api/serviceaccounts" \
        -d "{\"name\":\"${SA_NAME}\",\"role\":\"${ROLE}\",\"isDisabled\":false}" \
        | jq -r '.id' || true)"
fi

if [ -z "${sa_id:-}" ] || [ "$sa_id" = "null" ]; then
    log "ERROR: could not find or create service account"; exit 1
fi
log "service account id=${sa_id}"

# --- mint a fresh token (unique name => a new token every call) ---
tok_name="drpc-insights-$(hostname -s 2>/dev/null || hostname)-$(date +%s)"
token="$("${CURL[@]}" -X POST "$BASE/api/serviceaccounts/${sa_id}/tokens" \
    -d "{\"name\":\"${tok_name}\",\"role\":\"${ROLE}\"}" | jq -r '.key' || true)"

if [ -z "${token:-}" ] || [ "$token" = "null" ]; then
    log "ERROR: token creation failed (check ADMIN_PASSWORD / Grafana reachability at $BASE)"; exit 1
fi

log "minted token '${tok_name}'"
echo "$token"
