#!/usr/bin/env bash

# =============================================================================
# SSH Tunnel Management Helper
# Gère l'ouverture/fermeture des tunnels SSH vers les containers Incus
# =============================================================================

set -euo pipefail

# Répertoire du script
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BAO_ROOT="$(dirname "$SCRIPT_DIR")"
ENV_FILE="$BAO_ROOT/config/.env"

# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# Fonctions d'affichage
log_info() {
    echo -e "${BLUE}ℹ${NC} $*"
}

log_success() {
    echo -e "${GREEN}✓${NC} $*"
}

log_error() {
    echo -e "${RED}✗${NC} $*" >&2
}

log_warning() {
    echo -e "${YELLOW}⚠${NC} $*"
}

# Charge une variable depuis .env
get_env_var() {
    local key="$1"
    grep "^${key}=" "$ENV_FILE" 2>/dev/null | cut -d'=' -f2- | tr -d ' "'
}

# Vérifie si un tunnel SSH est actif
is_tunnel_active() {
    local port="$1"

    # Vérifier si le port est en écoute
    if command -v ss >/dev/null 2>&1; then
        ss -tuln | grep -q ":${port} " && return 0
    elif command -v netstat >/dev/null 2>&1; then
        netstat -tuln | grep -q ":${port} " && return 0
    elif command -v lsof >/dev/null 2>&1; then
        lsof -i ":${port}" -sTCP:LISTEN >/dev/null 2>&1 && return 0
    fi

    return 1
}

# Trouve le PID du processus SSH pour un tunnel
get_tunnel_pid() {
    local port="$1"

    # Chercher le processus SSH qui utilise ce port local
    if command -v lsof >/dev/null 2>&1; then
        lsof -ti ":${port}" -sTCP:LISTEN 2>/dev/null | head -n1
    else
        # Fallback avec ps et grep
        ps aux | grep "ssh.*:${port}:localhost:3306" | grep -v grep | awk '{print $2}' | head -n1
    fi
}

# Ouvre un tunnel SSH
open_tunnel() {
    local env="${1^^}"  # Convertir en majuscules

    local ssh_host=$(get_env_var "${env}_SSH_HOST")
    local local_port=$(get_env_var "${env}_SSH_PORT_LOCAL")
    local enabled=$(get_env_var "${env}_ENABLED")

    if [[ "$enabled" != "true" ]]; then
        log_error "Environnement ${env} désactivé dans .env"
        return 1
    fi

    if [[ -z "$ssh_host" || -z "$local_port" ]]; then
        log_error "Configuration ${env} incomplète dans .env"
        return 1
    fi

    # Si le port local est 0, on est dans un container avec connexion directe
    if [[ "$local_port" == "0" ]]; then
        # Pas de tunnel nécessaire, connexion directe
        return 0
    fi

    # Vérifier si le tunnel est déjà actif
    if is_tunnel_active "$local_port"; then
        log_warning "Tunnel ${env} déjà actif sur le port ${local_port}"
        return 0
    fi

    log_info "Ouverture du tunnel SSH vers ${ssh_host} (port local ${local_port})..."

    # Créer le tunnel en arrière-plan
    # -N : Ne pas exécuter de commande distante
    # -f : Passer en arrière-plan
    # -o ExitOnForwardFailure=yes : Quitter si le tunnel échoue
    # -o ServerAliveInterval=60 : Garder la connexion active
    ssh -N -f \
        -L "${local_port}:localhost:3306" \
        -o ExitOnForwardFailure=yes \
        -o ServerAliveInterval=60 \
        -o ServerAliveCountMax=3 \
        "$ssh_host" 2>/dev/null

    # Attendre que le tunnel soit actif
    local max_attempts=10
    local attempt=0

    while [[ $attempt -lt $max_attempts ]]; do
        if is_tunnel_active "$local_port"; then
            log_success "Tunnel ${env} actif sur le port ${local_port}"
            return 0
        fi

        sleep 0.5
        ((attempt++))
    done

    log_error "Impossible d'ouvrir le tunnel ${env}"
    return 1
}

# Ferme un tunnel SSH
close_tunnel() {
    local env="${1^^}"

    local local_port=$(get_env_var "${env}_SSH_PORT_LOCAL")

    if [[ -z "$local_port" ]]; then
        log_error "Port local pour ${env} introuvable dans .env"
        return 1
    fi

    if ! is_tunnel_active "$local_port"; then
        log_warning "Tunnel ${env} non actif sur le port ${local_port}"
        return 0
    fi

    local pid=$(get_tunnel_pid "$local_port")

    if [[ -z "$pid" ]]; then
        log_error "Impossible de trouver le PID du tunnel ${env}"
        return 1
    fi

    log_info "Fermeture du tunnel ${env} (PID ${pid})..."

    kill "$pid" 2>/dev/null

    sleep 0.5

    if ! is_tunnel_active "$local_port"; then
        log_success "Tunnel ${env} fermé"
        return 0
    else
        log_error "Impossible de fermer le tunnel ${env}"
        return 1
    fi
}

# Affiche le statut des tunnels
status_tunnels() {
    echo -e "\n${CYAN}╔════════════════════════════════════════╗${NC}"
    echo -e "${CYAN}║   État des tunnels SSH                ║${NC}"
    echo -e "${CYAN}╚════════════════════════════════════════╝${NC}\n"

    for env in DVA RCA PRA; do
        local enabled=$(get_env_var "${env}_ENABLED")
        local local_port=$(get_env_var "${env}_SSH_PORT_LOCAL")
        local ssh_host=$(get_env_var "${env}_SSH_HOST")

        if [[ "$enabled" != "true" ]]; then
            echo -e "  ${env}: ${YELLOW}Désactivé${NC}"
            continue
        fi

        if is_tunnel_active "$local_port"; then
            local pid=$(get_tunnel_pid "$local_port")
            echo -e "  ${env}: ${GREEN}✓ Actif${NC} (port ${local_port}, PID ${pid})"
        else
            echo -e "  ${env}: ${RED}✗ Inactif${NC} (port ${local_port})"
        fi
    done

    echo ""
}

# Ferme tous les tunnels
close_all_tunnels() {
    log_info "Fermeture de tous les tunnels..."

    for env in DVA RCA PRA; do
        local enabled=$(get_env_var "${env}_ENABLED")

        if [[ "$enabled" == "true" ]]; then
            close_tunnel "$env" 2>/dev/null || true
        fi
    done

    log_success "Tous les tunnels ont été fermés"
}

# Usage
usage() {
    cat <<EOF
Usage: $(basename "$0") <command> [environment]

Commandes:
    open <env>      Ouvre un tunnel SSH vers l'environnement
    close <env>     Ferme le tunnel SSH
    status          Affiche l'état de tous les tunnels
    close-all       Ferme tous les tunnels actifs

Environnements: DVA, RCA, PRA

Exemples:
    $(basename "$0") open dva
    $(basename "$0") close rca
    $(basename "$0") status
    $(basename "$0") close-all
EOF
}

# Main
main() {
    if [[ ! -f "$ENV_FILE" ]]; then
        log_error "Fichier .env introuvable: $ENV_FILE"
        log_info "Copiez config/.env.example vers config/.env"
        exit 1
    fi

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

    local command="$1"

    case "$command" in
        open)
            if [[ $# -lt 2 ]]; then
                log_error "Environnement manquant"
                usage
                exit 1
            fi
            open_tunnel "$2"
            ;;
        close)
            if [[ $# -lt 2 ]]; then
                log_error "Environnement manquant"
                usage
                exit 1
            fi
            close_tunnel "$2"
            ;;
        status)
            status_tunnels
            ;;
        close-all)
            close_all_tunnels
            ;;
        *)
            log_error "Commande invalide: $command"
            usage
            exit 1
            ;;
    esac
}

main "$@"
