#!/usr/bin/env bash
#
# Consulta las bases del servidor de PRUEBAS sin que la clave quede a la vista.
#
#   scripts/consultar-pruebas.sh "SELECT ..."          consulta suelta
#   scripts/consultar-pruebas.sh --bases               lista las bases
#   scripts/consultar-pruebas.sh --tablas <base>       lista las tablas de una base
#   scripts/consultar-pruebas.sh --columnas <base> <tabla>
#   scripts/consultar-pruebas.sh --quien-soy           comprueba el acceso
#
# PARA QUÉ ES. Para que una sesión de Claude pueda revisar datos de las bases de
# pruebas sin que nadie tenga que pegar una contraseña en el chat — si se pega,
# queda en el historial de la conversación para siempre.
#
# QUÉ DEJA HACER. Todo lo que necesites: consultar, insertar, actualizar, borrar
# filas, crear y alterar tablas. Es el servidor de pruebas y ahí se trabaja.
#
# ⚠️ LO ÚNICO QUE PIDE CONFIRMACIÓN es borrar una BASE ENTERA (DROP DATABASE /
# SCHEMA), y un DELETE o UPDATE sin WHERE — que se lleva la tabla completa. No es
# que no se pueda: hay que agregar --se-lo-que-hago. El motivo: en pruebas viven
# copias de bases de CLIENTES REALES, y esas tres son las que no se deshacen.
# Para todo lo demás el guion no se mete.
#
# CÓMO SE CONFIGURA (una sola vez, cada quien en su máquina):
#
#   mkdir -p ~/.config/mb
#   printf 'BD_USUARIO=tu_usuario\nBD_CLAVE=tu_clave\n' > ~/.config/mb/pruebas.env
#   chmod 600 ~/.config/mb/pruebas.env
#
# Ese archivo NO va a ningún repo y el guion nunca imprime su contenido.

set -euo pipefail

CONFIG="${MB_PRUEBAS_ENV:-$HOME/.config/mb/pruebas.env}"
SERVIDOR="132.226.40.48"
PUERTO="3310"            # 3310 = PRUEBAS. 3309 es PRODUCCIÓN: este guion no la toca.

# Huella del servidor de pruebas, para no confundirlo con producción.
#
# ⚠️ CAMBIA cuando se recarga el servidor. La de antes —wemuedtigeloq3nx— quedó
# obsoleta con la carga nueva del 17-ago-2026, y desde entonces este guion daba
# FALSA ALARMA en cada `--quien-soy`. Eso es peor que no avisar: la conclusión
# natural de ver una huella que no calza es «entonces estoy en producción».
# Actualizada el 25-ago-2026 midiéndola con este mismo guion (#23598).
#
# Hoy pruebas.db.interno es 10.0.1.204 (mb-oracle-mysql-pruebas-8.0-restaurado-20260817),
# @@server_id 245329159. El 10.0.1.5 de antes está DELETED y su 3306 no responde.
HUELLA_PRUEBAS="m8hucbdmrohmyeo2"

usar() { sed -n '3,30p' "$0" | sed 's/^# \{0,1\}//'; exit 1; }

[ $# -eq 0 ] && usar

if [ ! -f "$CONFIG" ]; then
    cat >&2 <<AYUDA
No existe $CONFIG

Creálo una sola vez, con tu usuario del servidor de pruebas:

    mkdir -p ~/.config/mb
    printf 'BD_USUARIO=tu_usuario\nBD_CLAVE=tu_clave\n' > ~/.config/mb/pruebas.env
    chmod 600 ~/.config/mb/pruebas.env

Si no sabés tu usuario o tu clave, pedíselas a Manuel. No las pegues en el chat.
AYUDA
    exit 1
fi

PERM=$(stat -f '%Lp' "$CONFIG" 2>/dev/null || stat -c '%a' "$CONFIG" 2>/dev/null)
if [ "$PERM" != "600" ]; then
    echo "⚠️  $CONFIG tiene permisos $PERM. Debería ser 600:" >&2
    echo "    chmod 600 $CONFIG" >&2
    exit 1
fi

# shellcheck disable=SC1090
set -a; . "$CONFIG"; set +a
: "${BD_USUARIO:?falta BD_USUARIO en $CONFIG}"
: "${BD_CLAVE:?falta BD_CLAVE en $CONFIG}"

correr() {   # $1 = SQL ya validado
    mysqlsh --sql --uri "${BD_USUARIO}:${BD_CLAVE}@${SERVIDOR}:${PUERTO}" \
            --result-format=table -e "$1" 2>&1 | grep -v "WARNING.*password"
}

# Igual que correr(), pero devuelve el valor pelado — sin el marco de la tabla.
# Hace falta para poder COMPARAR desde el guion en vez de dejarle el cotejo al ojo.
correr_valor() {   # $1 = SQL que devuelve UNA columna y UNA fila
    mysqlsh --sql --uri "${BD_USUARIO}:${BD_CLAVE}@${SERVIDOR}:${PUERTO}" \
            --result-format=tabbed -e "$1" 2>/dev/null \
        | grep -v "WARNING.*password" | tail -1 | tr -d " \t\r"
}

# Los nombres de base y tabla se interpolan en el SQL de --tablas/--columnas, así que
# tienen que ser identificadores de verdad. Sin esto, un argumento con una comilla
# escapa del literal y se puede leer mysql.user — comprobado el 14-ago-2026.
identificador() {
    case "$1" in
        ''|*[!A-Za-z0-9_-]*)
            echo "✋ \"$1\" no es un nombre válido de base o tabla." >&2
            echo "   Sólo letras, números, guión bajo y guión." >&2
            exit 2 ;;
    esac
}

# Sólo frena lo irreversible. Todo lo demás pasa.
#
# ⚠️ SE MIRA SENTENCIA POR SENTENCIA, no sólo el principio del texto.
# La primera versión miraba con qué palabra empezaba TODO lo que se le pasaba, y
# eso lo saltaba cualquier cosa que llevara dos sentencias:
#
#     consultar-pruebas.sh "SELECT 1; DROP DATABASE mbinvlachimalteca;"
#
# empieza con SELECT, así que pasaba el freno — y mysqlsh ejecuta las dos. Un
# freno que se salta sin querer es peor que no tenerlo: da confianza que no
# corresponde. Comprobado el 14-ago-2026, antes de mergear el PR.
revisar_riesgo() {
    [ "$PERMITIR_TODO" = "1" ] && return 0

    # Se quitan comentarios, se pasa a mayúsculas, y los saltos de línea cuentan
    # como espacio: si no, «\nDROP DATABASE» tampoco coincidía con el patrón.
    local texto
    texto=$(printf '%s' "$1" | sed 's|/\*[^*]*\*/||g' | tr '\n\t' '  ' \
            | tr '[:lower:]' '[:upper:]' | tr -s ' ')

    local sentencia resto="$texto"
    while [ -n "$resto" ]; do
        sentencia="${resto%%;*}"
        if [ "$sentencia" = "$resto" ]; then resto=""; else resto="${resto#*;}"; fi
        # se recorta el espacio de adelante
        sentencia="${sentencia#"${sentencia%%[![:space:]]*}"}"
        [ -z "$sentencia" ] && continue

        case "$sentencia" in
            DROP\ DATABASE*|DROP\ SCHEMA*)
                echo "✋ Eso borra una BASE ENTERA, y en pruebas hay copias de clientes reales." >&2
                echo "   Si es lo que querés:  $(basename "$0") --se-lo-que-hago \"...\"" >&2
                exit 2 ;;
            DELETE\ FROM*|UPDATE\ *)
                if ! printf '%s' "$sentencia" | grep -q ' WHERE '; then
                    echo "✋ Un $(printf '%s' "$sentencia" | cut -d' ' -f1) sin WHERE toca la tabla ENTERA." >&2
                    echo "   Si es lo que querés:  $(basename "$0") --se-lo-que-hago \"...\"" >&2
                    exit 2
                fi ;;
        esac
    done
}

# Un nombre de base o de tabla que viene de la línea de comandos NO se pega
# dentro del SQL tal cual: se le escapan las comillas. Es el mismo agujero que se
# arregló hoy en los reportes de mbinv (#23185) — acá el riesgo es menor, porque
# quien lo corre ya tiene la credencial, pero el patrón se copia y se propaga.
entrecomillar() { printf "'%s'" "$(printf '%s' "$1" | sed "s/'/''/g; s/\\\\/\\\\\\\\/g")"; }

PERMITIR_TODO=0
if [ "${1:-}" = "--se-lo-que-hago" ]; then
    PERMITIR_TODO=1; shift
    [ $# -ge 1 ] || { echo "Falta la sentencia después de --se-lo-que-hago" >&2; exit 1; }
fi

case "${1:-}" in
    --quien-soy)
        echo "Servidor: $SERVIDOR:$PUERTO   usuario: $BD_USUARIO"
        correr "SELECT @@hostname AS huella, @@server_id AS id, CURRENT_USER() AS conectado_como;"
        echo
        # Se compara acá, no con el ojo. El mensaje viejo sólo imprimía la huella
        # esperada y dejaba el cotejo a quien mirara la tabla de arriba — y con la
        # huella desactualizada eso daba una alarma falsa cada vez.
        HUELLA_VISTA="$(correr_valor "SELECT @@hostname;")"
        if [ "$HUELLA_VISTA" = "$HUELLA_PRUEBAS" ]; then
            echo "COINCIDE con la huella de PRUEBAS ($HUELLA_PRUEBAS). Podés trabajar."
        else
            echo "⚠️ NO COINCIDE."
            echo "   esperada (PRUEBAS): $HUELLA_PRUEBAS"
            echo "   la que contestó   : ${HUELLA_VISTA:-(no se pudo leer)}"
            echo "   Parás y avisás. Puede ser que el servidor se haya recargado y"
            echo "   haya que actualizar HUELLA_PRUEBAS en este guion — o que estés"
            echo "   en el servidor equivocado. NO sigas hasta saber cuál de las dos."
        fi
        ;;
    --bases)
        correr "SELECT SCHEMA_NAME AS base FROM information_schema.SCHEMATA
                WHERE SCHEMA_NAME NOT IN ('mysql','information_schema','performance_schema','sys')
                ORDER BY SCHEMA_NAME;"
        ;;
    --tablas)
        [ $# -ge 2 ] || { echo "Falta la base: --tablas <base>" >&2; exit 1; }
        identificador "$2"
        correr "SELECT TABLE_NAME AS tabla, TABLE_ROWS AS filas_aprox
                FROM information_schema.TABLES WHERE TABLE_SCHEMA=$(entrecomillar "$2") ORDER BY TABLE_NAME;"
        ;;
    --columnas)
        [ $# -ge 3 ] || { echo "Faltan datos: --columnas <base> <tabla>" >&2; exit 1; }
        identificador "$2"; identificador "$3"
        correr "SELECT COLUMN_NAME AS columna, COLUMN_TYPE AS tipo, IS_NULLABLE AS acepta_nulo
                FROM information_schema.COLUMNS
                WHERE TABLE_SCHEMA=$(entrecomillar "$2")
                    AND TABLE_NAME=$(entrecomillar "$3") ORDER BY ORDINAL_POSITION;"
        ;;
    --ayuda|-h|--help) usar ;;
    *)
        revisar_riesgo "$1"
        correr "$1"
        ;;
esac
