#!/usr/bin/env bash
# Manage per-user age keys and sops recipients.
# - Creates a new age keypair under creds/age/<user>.key
# - Updates .sops.yaml recipients list for creds/secrets.enc.env
# - Can delete a user (removes key file and recipient entry)
#
# Usage:
#   ./scripts/manage-age-key.sh add <username>
#   ./scripts/manage-age-key.sh remove <username>
#   ./scripts/manage-age-key.sh list
#
# Notes:
# - Keep private keys out of git; creds/age/ is git-ignored.
# - After add/remove, re-encrypt secrets: sops --encrypt --in-place creds/secrets.enc.env

set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
AGE_DIR="$ROOT_DIR/creds/age"
SOPS_CONFIG="$ROOT_DIR/.sops.yaml"

usage() {
  sed -n '1,12p' "${BASH_SOURCE[0]}"
  exit 1
}

list_keys() {
  if [[ -d "$AGE_DIR" ]]; then
    find "$AGE_DIR" -maxdepth 1 -type f -name '*.key' -printf '%f\n'
  fi
}

ensure_age_dir() {
  mkdir -p "$AGE_DIR"
}

add_user() {
  local user="$1"
  ensure_age_dir
  local key_file="$AGE_DIR/${user}.key"
  if [[ -f "$key_file" ]]; then
    echo "Key already exists: $key_file"
    exit 1
  fi
  echo "Generating age key for ${user} -> ${key_file}"
  age-keygen -o "$key_file" >/dev/null
  local pub
  pub=$(grep '^# public key:' "$key_file" | awk '{print $4}')
  echo "Public key: $pub"

  if [[ ! -f "$SOPS_CONFIG" ]]; then
    echo "sops config not found at $SOPS_CONFIG; skipping recipient update."
    echo "Add this recipient manually: $pub"
    exit 0
  fi

  if grep -q "$pub" "$SOPS_CONFIG"; then
    echo "Recipient already present in $SOPS_CONFIG"
  else
    echo "Adding recipient to $SOPS_CONFIG"
    # Append under the first age key list.
    tmp=$(mktemp)
    awk -v pub="$pub" '
      /^ *- age:/ { in_age=1; print; next }
      in_age && /^ *- age1/ { print "          - " pub; in_age=0 }
      { print }
    ' "$SOPS_CONFIG" >"$tmp"
    mv "$tmp" "$SOPS_CONFIG"
  fi

  echo "Done. Re-encrypt secrets after updating recipients:"
  echo "  sops --encrypt --in-place creds/secrets.enc.env"
}

remove_user() {
  local user="$1"
  local key_file="$AGE_DIR/${user}.key"
  if [[ -f "$key_file" ]]; then
    rm -f "$key_file"
    echo "Removed key $key_file"
  else
    echo "No key file for $user at $key_file"
  fi
  if [[ -f "$SOPS_CONFIG" ]]; then
    local pub
    pub=$(grep '^# public key:' "$key_file" 2>/dev/null | awk '{print $4}')
    if [[ -n "${pub:-}" ]]; then
      tmp=$(mktemp)
      awk -v pub="$pub" '!($0 ~ pub)' "$SOPS_CONFIG" >"$tmp"
      mv "$tmp" "$SOPS_CONFIG"
      echo "Removed recipient from $SOPS_CONFIG (if present)."
    fi
  fi
  echo "Re-encrypt secrets to drop removed recipients if needed:"
  echo "  sops --encrypt --in-place creds/secrets.enc.env"
}

cmd="${1:-}"
case "$cmd" in
  add)
    [[ $# -eq 2 ]] || usage
    add_user "$2"
    ;;
  remove|rm|delete)
    [[ $# -eq 2 ]] || usage
    remove_user "$2"
    ;;
  list|ls)
    list_keys
    ;;
  *)
    usage
    ;;
esac
