#!/usr/bin/env bash
# check_service_health_via_ssh — Comprueba la salud de un service HTTP que solo
# escucha en loopback de un host remoto, entrando por SSH y haciendo curl con
# bearer token opcional (leido de un .env remoto o pasado literal).
set -euo pipefail

check_service_health_via_ssh() {
    local ssh_host="" local_url=""
    local remote_env_path="" env_var=""
    local token_literal=""
    local expect_status=""        # vacio = aceptar cualquier 2xx
    local connect_timeout=5
    local curl_timeout=10

    # --- parseo de args (posicionales + flags) ---
    local positional=()
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --token-from-env)
                remote_env_path="${2:-}"
                env_var="${3:-}"
                if [[ -z "$remote_env_path" || -z "$env_var" ]]; then
                    echo "check_service_health_via_ssh: --token-from-env requiere <remote_env_path> <ENV_VAR>" >&2
                    return 2
                fi
                shift 3
                ;;
            --token)
                token_literal="${2:-}"
                shift 2
                ;;
            --expect-status)
                expect_status="${2:-}"
                shift 2
                ;;
            --connect-timeout)
                connect_timeout="${2:-5}"
                shift 2
                ;;
            --curl-timeout)
                curl_timeout="${2:-10}"
                shift 2
                ;;
            --)
                shift
                ;;
            -*)
                echo "check_service_health_via_ssh: flag desconocida '$1'" >&2
                return 2
                ;;
            *)
                positional+=("$1")
                shift
                ;;
        esac
    done

    ssh_host="${positional[0]:-}"
    local_url="${positional[1]:-}"

    if [[ -z "$ssh_host" || -z "$local_url" ]]; then
        echo "check_service_health_via_ssh: uso: check_service_health_via_ssh <ssh_host> <local_url> [--token-from-env <remote_env_path> <ENV_VAR>] [--token <literal>] [--expect-status 200]" >&2
        return 2
    fi

    # --- construir el snippet remoto que se ejecuta dentro del host via SSH ---
    # El token NUNCA se imprime: se resuelve dentro del host remoto y se usa
    # directamente en el header Authorization. El snippet emite SOLO el http_code.
    #
    # Casos de token:
    #   1) --token-from-env: lee el valor de <ENV_VAR>= del .env remoto.
    #   2) --token <literal>: el literal se inyecta en el snippet (cuidado: queda
    #      en argv del comando ssh local; preferir --token-from-env para secretos).
    #   3) sin token: curl sin header Authorization.
    local remote_script
    if [[ -n "$remote_env_path" ]]; then
        # grep el valor del .env remoto, recortando posibles comillas y espacios.
        remote_script=$(cat <<REMOTE
set -e
TOKEN=\$(grep -E '^[[:space:]]*${env_var}[[:space:]]*=' '${remote_env_path}' 2>/dev/null | head -n1 | cut -d= -f2- | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*\$//' -e 's/^["'\'']//' -e 's/["'\'']\$//')
if [ -z "\$TOKEN" ]; then
  echo "000"
  exit 7
fi
curl -sf -o /dev/null -w '%{http_code}' --max-time ${curl_timeout} -H "Authorization: Bearer \$TOKEN" '${local_url}' || echo "\$?:\$(curl -s -o /dev/null -w '%{http_code}' --max-time ${curl_timeout} -H "Authorization: Bearer \$TOKEN" '${local_url}' 2>/dev/null)"
REMOTE
)
    elif [[ -n "$token_literal" ]]; then
        remote_script=$(cat <<REMOTE
set -e
TOKEN='${token_literal}'
curl -sf -o /dev/null -w '%{http_code}' --max-time ${curl_timeout} -H "Authorization: Bearer \$TOKEN" '${local_url}' || echo "\$?:\$(curl -s -o /dev/null -w '%{http_code}' --max-time ${curl_timeout} -H "Authorization: Bearer \$TOKEN" '${local_url}' 2>/dev/null)"
REMOTE
)
    else
        remote_script=$(cat <<REMOTE
set -e
curl -sf -o /dev/null -w '%{http_code}' --max-time ${curl_timeout} '${local_url}' || echo "\$?:\$(curl -s -o /dev/null -w '%{http_code}' --max-time ${curl_timeout} '${local_url}' 2>/dev/null)"
REMOTE
)
    fi

    # --- ejecutar via SSH (o via runner inyectado en tests) ---
    # CHECK_HEALTH_SSH_BIN permite a los tests sustituir el comando ssh por un
    # stub que devuelve un http_code fijo, sin tocar la red.
    local ssh_bin="${CHECK_HEALTH_SSH_BIN:-ssh}"
    local raw rc=0
    raw=$("$ssh_bin" -o BatchMode=yes -o ConnectTimeout="$connect_timeout" "$ssh_host" "$remote_script" 2>/dev/null) || rc=$?

    # El snippet remoto, cuando curl -sf falla, emite "<curl_rc>:<http_code>".
    # Cuando curl tiene exito, emite solo "<http_code>". Normalizamos a http_code.
    local http_code
    if [[ "$raw" == *:* ]]; then
        http_code="${raw##*:}"
    else
        http_code="$raw"
    fi
    # sanitizar: solo digitos; cualquier otra cosa => 000
    if [[ ! "$http_code" =~ ^[0-9]+$ ]]; then
        http_code="000"
    fi

    # Si el SSH en si fallo (conexion, host caido) y no hay codigo util.
    local status="ok"
    if [[ "$rc" -ne 0 && "$http_code" == "000" ]]; then
        status="error"
    fi

    # --- decidir healthy ---
    local healthy="false"
    if [[ -n "$expect_status" ]]; then
        [[ "$http_code" == "$expect_status" ]] && healthy="true"
    else
        # default: cualquier 2xx
        [[ "$http_code" =~ ^2[0-9][0-9]$ ]] && healthy="true"
    fi

    printf '{"status":"%s","host":"%s","url":"%s","http_code":%s,"healthy":%s}\n' \
        "$status" "$ssh_host" "$local_url" "$http_code" "$healthy"

    [[ "$healthy" == "true" ]] && return 0 || return 1
}

if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
    check_service_health_via_ssh "$@"
fi
