#!/usr/bin/env bash
set -euo pipefail

USERS_FILE="${USERS_FILE:-config/users}"
DEFAULT_COST="${BCRYPT_COST:-12}"
SKIP_RESTART="${SKIP_RESTART:-0}"

# --- Utilidades -------------------------------------------------------------

usage() {
  cat <<'EOF'
Gestor de usuarios Radicale

Uso:
  ./radicale_users.sh list
  ./radicale_users.sh add <usuario> [--password <pwd> | --random]
  ./radicale_users.sh passwd <usuario> [--password <pwd> | --random]
  ./radicale_users.sh delete <usuario> [--force]
  ./radicale_users.sh --help

Variables:
  USERS_FILE     Ruta del archivo htpasswd (por defecto config/users)
  SKIP_RESTART   Si vale 1, no reinicia el contenedor automáticamente
  BCRYPT_COST    Coste para htpasswd -B (por defecto 12)

Sin argumentos se abre el menú interactivo original.
EOF
}

ensure_users_file() {
  if [[ ! -f "$USERS_FILE" ]]; then
    echo "⚠️  No existe $USERS_FILE. Creándolo..."
    mkdir -p "$(dirname "$USERS_FILE")"
    touch "$USERS_FILE"
  fi
}

require_command() {
  if ! command -v "$1" >/dev/null 2>&1; then
    echo "❌ Necesitas '$1' instalado en el sistema." >&2
    exit 1
  fi
}

maybe_restart() {
  if [[ "$SKIP_RESTART" == "1" ]]; then
    echo "⚠️  SKIP_RESTART=1, no se reiniciará Radicale automáticamente."
    return
  fi
  echo "🔄 Reiniciando contenedor Radicale..."
  docker compose restart radicale >/dev/null 2>&1 || true
  echo "✅ Radicale reiniciado."
}

generate_password() {
  if command -v openssl >/dev/null 2>&1; then
    openssl rand -base64 18
  else
    date +%s | sha256sum | head -c 16
  fi
}

prompt_password() {
  local pwd confirm
  read -rs -p "Introduce contraseña: " pwd
  echo ""
  read -rs -p "Confirma contraseña: " confirm
  echo ""
  if [[ "$pwd" != "$confirm" ]]; then
    echo "❌ Las contraseñas no coinciden." >&2
    exit 1
  fi
  echo "$pwd"
}

htpasswd_update() {
  local user="$1" password="$2"
  htpasswd -B -C "$DEFAULT_COST" -b "$USERS_FILE" "$user" "$password" >/dev/null
  normalize_bcrypt_prefix "$user"
}

normalize_bcrypt_prefix() {
  local user="$1"
  if ! command -v python3 >/dev/null 2>&1; then
    echo "⚠️  python3 no disponible: no se pudo normalizar el hash bcrypt de '$user' (prefijo \$2y\$)." >&2
    echo "   Radicale solo acepta hashes \$2b\$, por lo que este usuario podría fallar." >&2
    return
  fi
  python3 - "$USERS_FILE" "$user" <<'PY'
import pathlib, re, sys
path = pathlib.Path(sys.argv[1])
user = sys.argv[2]
data = path.read_text()
pattern = re.compile(rf'^({re.escape(user)}:\$)2y', re.M)
updated, count = pattern.subn(r'\g<1>2b', data)
if count:
    path.write_text(updated)
PY
}

list_users() {
  ensure_users_file
  echo "👥 Usuarios actuales:"
  if [[ -s "$USERS_FILE" ]]; then
    cut -d':' -f1 "$USERS_FILE" | sort
  else
    echo "(ninguno)"
  fi
}

cmd_add() {
  ensure_users_file
  local user="$1" password="" random=0
  shift || true
  while [[ $# -gt 0 ]]; do
    case "$1" in
      --password|-p) password="$2"; shift 2 ;;
      --random|-r) random=1; shift ;;
      --no-restart) SKIP_RESTART=1; shift ;;
      *) echo "❗ Opción desconocida: $1" >&2; exit 1 ;;
    esac
  done
  if [[ -z "$user" ]]; then
    echo "❌ Debes indicar un usuario." >&2
    exit 1
  fi
  if grep -q "^$user:" "$USERS_FILE"; then
    echo "⚠️  El usuario '$user' ya existe." >&2
    exit 1
  fi
  if [[ $random -eq 1 ]]; then
    password="$(generate_password)"
    echo "🔐 Contraseña generada para '$user': $password"
  elif [[ -z "$password" ]]; then
    password="$(prompt_password)"
  fi
  htpasswd_update "$user" "$password"
  maybe_restart
}

cmd_passwd() {
  ensure_users_file
  local user="$1" password="" random=0
  shift || true
  while [[ $# -gt 0 ]]; do
    case "$1" in
      --password|-p) password="$2"; shift 2 ;;
      --random|-r) random=1; shift ;;
      --no-restart) SKIP_RESTART=1; shift ;;
      *) echo "❗ Opción desconocida: $1" >&2; exit 1 ;;
    esac
  done
  if [[ -z "$user" ]]; then
    echo "❌ Debes indicar usuario." >&2
    exit 1
  fi
  if ! grep -q "^$user:" "$USERS_FILE"; then
    echo "⚠️  El usuario '$user' no existe." >&2
    exit 1
  fi
  if [[ $random -eq 1 ]]; then
    password="$(generate_password)"
    echo "🔐 Nueva contraseña generada: $password"
  elif [[ -z "$password" ]]; then
    password="$(prompt_password)"
  fi
  htpasswd_update "$user" "$password"
  maybe_restart
}

cmd_delete() {
  ensure_users_file
  local user="$1" force=0
  shift || true
  while [[ $# -gt 0 ]]; do
    case "$1" in
      --force|-f) force=1; shift ;;
      --no-restart) SKIP_RESTART=1; shift ;;
      *) echo "❗ Opción desconocida: $1" >&2; exit 1 ;;
    esac
  done
  if [[ -z "$user" ]]; then
    echo "❌ Debes indicar usuario." >&2
    exit 1
  fi
  if ! grep -q "^$user:" "$USERS_FILE"; then
    echo "⚠️  El usuario '$user' no existe." >&2
    exit 1
  fi
  if [[ $force -eq 0 ]]; then
    read -rp "¿Eliminar '$user'? (s/N): " confirm
    [[ "$confirm" =~ ^[sS]$ ]] || { echo "🚫 Operación cancelada."; return; }
  fi
  sed -i.bak "/^$user:/d" "$USERS_FILE"
  rm -f "${USERS_FILE}.bak"
  echo "❌ Usuario '$user' eliminado."
  maybe_restart
}

# --- Menú interactivo legado -----------------------------------------------
interactive_menu() {
  while true; do
    echo "========================================"
    echo "🔐  GESTOR DE USUARIOS RADICALE"
    echo "========================================"
    echo "1️⃣  Listar usuarios"
    echo "2️⃣  Crear nuevo usuario"
    echo "3️⃣  Editar contraseña de usuario"
    echo "4️⃣  Eliminar usuario"
    echo "5️⃣  Salir"
    echo "----------------------------------------"
    read -rp "Selecciona una opción [1-5]: " opt
    echo ""
    case "$opt" in
      1) list_users ;;
      2) read -rp "Usuario nuevo: " user; cmd_add "$user" ;;
      3) read -rp "Usuario a modificar: " user; cmd_passwd "$user" ;;
      4) read -rp "Usuario a eliminar: " user; cmd_delete "$user" ;;
      5) echo "👋 Saliendo..."; exit 0 ;;
      *) echo "❗ Opción no válida." ;;
    esac
    echo ""
    read -rp "Presiona ENTER para continuar..." _
    clear
  done
}

# --- Punto de entrada -------------------------------------------------------
main() {
  require_command htpasswd

  if [[ $# -eq 0 ]]; then
    interactive_menu
    exit 0
  fi

  case "$1" in
    list) list_users ;;
    add)
      shift
      cmd_add "${1:-}" "${@:2}"
      ;;
    passwd)
      shift
      cmd_passwd "${1:-}" "${@:2}"
      ;;
    delete|remove)
      shift
      cmd_delete "${1:-}" "${@:2}"
      ;;
    --help|-h) usage ;;
    *) echo "❗ Comando desconocido: $1"; usage; exit 1 ;;
  esac
}

main "$@"
