#!/usr/bin/env bash

set -euo pipefail

DB_NAME="${DB_NAME:-px_unsaac}"
DB_USER="${DB_USER:-sinchiroca}"
DB_HOST_PATTERN="${DB_HOST_PATTERN:-%}"
MYSQL_ADMIN_USER="${MYSQL_ADMIN_USER:-root}"
MYSQL_ADMIN_HOST="${MYSQL_ADMIN_HOST:-localhost}"
MYSQL_ADMIN_PORT="${MYSQL_ADMIN_PORT:-3306}"
MYSQL_USE_SUDO="${MYSQL_USE_SUDO:-auto}"
DRY_RUN=0

usage() {
  cat <<EOF
Uso: ./mysql-grant-docker-access.sh [opciones]

Concede permisos MySQL para que un contenedor Docker pueda conectarse.

Opciones:
  --db-name NAME          Base de datos. Default: ${DB_NAME}
  --db-user USER          Usuario de la app. Default: ${DB_USER}
  --db-host-pattern HOST  Host permitido en MySQL. Default: ${DB_HOST_PATTERN}
                          Usa '%' para cualquier origen o '172.19.%' para Docker bridge.
  --admin-user USER       Usuario admin MySQL. Default: ${MYSQL_ADMIN_USER}
  --admin-host HOST       Host admin MySQL. Default: ${MYSQL_ADMIN_HOST}
  --admin-port PORT       Puerto admin MySQL. Default: ${MYSQL_ADMIN_PORT}
  --sudo                  Usa sudo mysql con socket local
  --no-sudo               Usa mysql -u/host/port y pide password admin si hace falta
  --dry-run               Muestra SQL sin ejecutarlo
  --help                  Muestra esta ayuda

Variables equivalentes:
  DB_NAME, DB_USER, DB_PASS, DB_HOST_PATTERN,
  MYSQL_ADMIN_USER, MYSQL_ADMIN_PASSWORD, MYSQL_ADMIN_HOST, MYSQL_ADMIN_PORT.
EOF
}

prompt_value() {
  local label="$1"
  local default_value="${2:-}"
  local value=""

  if [[ -n "${default_value}" ]]; then
    printf '%s [%s]: ' "${label}" "${default_value}" >&2
  else
    printf '%s: ' "${label}" >&2
  fi

  read -r value
  if [[ -z "${value}" ]]; then
    value="${default_value}"
  fi

  printf '%s' "${value}"
}

prompt_secret() {
  local label="$1"
  local default_value="${2:-}"
  local value=""

  if [[ -n "${default_value}" ]]; then
    printf '%s [oculto, Enter para conservar]: ' "${label}" >&2
  else
    printf '%s: ' "${label}" >&2
  fi

  read -r -s value
  printf '\n' >&2
  if [[ -z "${value}" ]]; then
    value="${default_value}"
  fi

  printf '%s' "${value}"
}

sql_escape() {
  local value="$1"
  value="${value//\\/\\\\}"
  value="${value//\'/\'\'}"
  printf '%s' "${value}"
}

ident_escape() {
  local value="$1"
  value="${value//\`/\`\`}"
  printf '%s' "${value}"
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --db-name)
      DB_NAME="$2"
      shift 2
      ;;
    --db-user)
      DB_USER="$2"
      shift 2
      ;;
    --db-host-pattern)
      DB_HOST_PATTERN="$2"
      shift 2
      ;;
    --admin-user)
      MYSQL_ADMIN_USER="$2"
      shift 2
      ;;
    --admin-host)
      MYSQL_ADMIN_HOST="$2"
      shift 2
      ;;
    --admin-port)
      MYSQL_ADMIN_PORT="$2"
      shift 2
      ;;
    --sudo)
      MYSQL_USE_SUDO=1
      shift
      ;;
    --no-sudo)
      MYSQL_USE_SUDO=0
      shift
      ;;
    --dry-run)
      DRY_RUN=1
      shift
      ;;
    --help|-h)
      usage
      exit 0
      ;;
    *)
      printf '[ERROR] Opcion desconocida: %s\n' "$1" >&2
      exit 1
      ;;
  esac
done

command -v mysql >/dev/null 2>&1 || {
  printf '[ERROR] No se encontro el cliente mysql en este servidor.\n' >&2
  exit 1
}

DB_NAME="$(prompt_value "DB_NAME" "${DB_NAME}")"
DB_USER="$(prompt_value "DB_USER" "${DB_USER}")"
DB_HOST_PATTERN="$(prompt_value "Host permitido para el usuario MySQL" "${DB_HOST_PATTERN}")"
DB_PASS="$(prompt_secret "Password real de ${DB_USER}" "${DB_PASS:-}")"

[[ -n "${DB_NAME}" ]] || { printf '[ERROR] Falta DB_NAME\n' >&2; exit 1; }
[[ -n "${DB_USER}" ]] || { printf '[ERROR] Falta DB_USER\n' >&2; exit 1; }
[[ -n "${DB_HOST_PATTERN}" ]] || { printf '[ERROR] Falta DB_HOST_PATTERN\n' >&2; exit 1; }
[[ -n "${DB_PASS}" ]] || { printf '[ERROR] Falta DB_PASS\n' >&2; exit 1; }

DB_NAME_SQL="$(ident_escape "${DB_NAME}")"
DB_USER_SQL="$(sql_escape "${DB_USER}")"
DB_HOST_SQL="$(sql_escape "${DB_HOST_PATTERN}")"
DB_PASS_SQL="$(sql_escape "${DB_PASS}")"

SQL="$(cat <<EOF
CREATE USER IF NOT EXISTS '${DB_USER_SQL}'@'${DB_HOST_SQL}' IDENTIFIED BY '${DB_PASS_SQL}';
ALTER USER '${DB_USER_SQL}'@'${DB_HOST_SQL}' IDENTIFIED BY '${DB_PASS_SQL}';
GRANT ALL PRIVILEGES ON \`${DB_NAME_SQL}\`.* TO '${DB_USER_SQL}'@'${DB_HOST_SQL}';
FLUSH PRIVILEGES;
SELECT user, host FROM mysql.user WHERE user = '${DB_USER_SQL}';
SHOW GRANTS FOR '${DB_USER_SQL}'@'${DB_HOST_SQL}';
EOF
)"

printf '[INFO] Aplicando permisos MySQL\n'
printf '  DB_NAME      : %s\n' "${DB_NAME}"
printf '  DB_USER      : %s\n' "${DB_USER}"
printf '  HOST_PATTERN : %s\n' "${DB_HOST_PATTERN}"

if [[ "${DRY_RUN}" == "1" ]]; then
  printf '[INFO] Dry-run activo. SQL generado sin password visible:\n'
  printf "CREATE USER IF NOT EXISTS '%s'@'%s' IDENTIFIED BY '<PASSWORD_REAL>';\n" "${DB_USER}" "${DB_HOST_PATTERN}"
  printf "ALTER USER '%s'@'%s' IDENTIFIED BY '<PASSWORD_REAL>';\n" "${DB_USER}" "${DB_HOST_PATTERN}"
  printf "GRANT ALL PRIVILEGES ON \`%s\`.* TO '%s'@'%s';\n" "${DB_NAME}" "${DB_USER}" "${DB_HOST_PATTERN}"
  printf 'FLUSH PRIVILEGES;\n'
  exit 0
fi

if [[ "${MYSQL_USE_SUDO}" == "auto" ]]; then
  if sudo -n mysql -e 'SELECT 1' >/dev/null 2>&1; then
    MYSQL_USE_SUDO=1
  else
    MYSQL_USE_SUDO=0
  fi
fi

if [[ "${MYSQL_USE_SUDO}" == "1" ]]; then
  printf '%s\n' "${SQL}" | sudo mysql
else
  if [[ -z "${MYSQL_ADMIN_PASSWORD:-}" ]]; then
    MYSQL_ADMIN_PASSWORD="$(prompt_secret "Password admin MySQL (${MYSQL_ADMIN_USER})" "")"
  fi
  MYSQL_PWD="${MYSQL_ADMIN_PASSWORD}" mysql \
    -h "${MYSQL_ADMIN_HOST}" \
    -P "${MYSQL_ADMIN_PORT}" \
    -u "${MYSQL_ADMIN_USER}" \
    < <(printf '%s\n' "${SQL}")
fi

printf '[INFO] Permisos aplicados. Reintenta el deploy remoto.\n'
