#!/bin/bash

# AutoNAS Remote Deploy Script
# Instalează și gestionează AutoNAS pe serverele remote 192.168.2.91-93

set -e  # Exit on any error


# Configurații
SSH_USER="root"
REMOTE_DIR="/tmp/autonas-deploy"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Parse cluster.json for nodes
parse_cluster_nodes() {
    local json_file="$SCRIPT_DIR/cluster.json"
    if ! [ -f "$json_file" ]; then
        log_error "cluster.json not found in $SCRIPT_DIR"
        exit 1
    fi
    jq -c '.cluster.nodes[]' "$json_file" 2>/dev/null
}

# Build arrays of IPs and hostnames
get_targets() {
    local nodes_json
    nodes_json=$(parse_cluster_nodes)
    local ips=()
    local names=()
    while IFS= read -r node; do
        local ip name
        ip=$(echo "$node" | jq -r '.ip')
        name=$(echo "$node" | jq -r '.hostname')
        ips+=("$ip")
        names+=("$name")
    done <<< "$nodes_json"
    echo "${ips[@]}"
}

# Get node name by IP
get_node_name() {
    local search_ip="$1"
    local nodes_json
    nodes_json=$(parse_cluster_nodes)
    while IFS= read -r node; do
        local ip name
        ip=$(echo "$node" | jq -r '.ip')
        name=$(echo "$node" | jq -r '.hostname')
        if [[ "$ip" == "$search_ip" ]]; then
            echo "$name"
            return
        fi
    done <<< "$nodes_json"
    echo "$search_ip"
}

# Culori pentru output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Funcții helper
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

print_banner() {
    echo "======================================"
    echo "    AutoNAS Remote Deploy Script"
    echo "======================================"
    echo ""
}

# Funcție pentru verificarea dacă hostul este up
check_host_up() {
    local target="$1"
    log_info "Verificare dacă hostul $target este accesibil..."

    # Pentru simplitate, verificăm direct SSH în loc de ping pe macOS
    if [[ "$OSTYPE" == "darwin"* ]]; then
        # macOS: verificare directă SSH cu timeout rapid
        if ssh -o ConnectTimeout=3 -o BatchMode=yes -o LogLevel=ERROR "$SSH_USER@$target" "echo 'OK'" >/dev/null 2>&1; then
            log_success "Host $target este UP și SSH funcționează"
            return 0
        else
            log_warning "Host $target nu este accesibil prin SSH"
            return 1
        fi
    else
        # Linux: folosim ping normal
        if timeout 5 ping -c 2 -W 3 "$target" >/dev/null 2>&1; then
            log_success "Host $target este UP"
            return 0
        else
            log_warning "Host $target este DOWN sau nu răspunde la ping"
            return 1
        fi
    fi
}

# Funcție pentru verificarea conectivității SSH
check_ssh_connectivity() {
    local target="$1"

    # Verifică mai întâi dacă hostul este up
    if ! check_host_up "$target"; then
        log_warning "Skipping SSH test pentru $target - hostul nu este up"
        return 1
    fi

    log_info "Verificare conectivitate SSH pentru $target..."

    if ssh -o ConnectTimeout=5 -o BatchMode=yes -o LogLevel=ERROR "$SSH_USER@$target" "echo 'SSH OK'" >/dev/null 2>&1; then
        log_success "SSH conectare OK pentru $target"
        return 0
    else
        log_error "SSH conectare FAILED pentru $target - verifică cheia SSH"
        return 1
    fi
}

# Funcție pentru copierea fișierelor pe ținta remotă
copy_files() {
    local target="$1"
    log_info "Copierea fișierelor pe $target..."

    # Creare director temporar pe țintă
    ssh -o LogLevel=ERROR "$SSH_USER@$target" "mkdir -p $REMOTE_DIR"

    # Copierea tuturor fișierelor proiectului
    rsync -avz --delete --quiet \
        --exclude='.git' \
        --exclude='deploy.sh' \
        --exclude='*.log' \
        "$SCRIPT_DIR/" "$SSH_USER@$target:$REMOTE_DIR/"

    log_success "Fișiere copiate pe $target"
}

# Funcție generică pentru executarea unei comenzi pe ținta remotă
run_on_target() {
    local target="$1"
    local action="$2"
    local success_msg="$3"
    local error_msg="$4"
    local cmd_arg="${5:-$action}"
    
    log_info "$action pe $target..."
    if ssh -o LogLevel=ERROR "$SSH_USER@$target" "bash $REMOTE_DIR/scripts/install.sh $cmd_arg"; then
        log_success "$success_msg"
    else
        log_error "$error_msg"
        return 1
    fi
}

# Funcție pentru verificarea statusului (nu necesită rsync)
check_status() {
    local target="$1"
    log_info "Verificarea statusului AutoNAS pe $target..."
    # Încearcă să folosească uninstaller pentru status sau install.sh dacă există
    ssh -o LogLevel=ERROR "$SSH_USER@$target" "
        if [ -f '$REMOTE_DIR/scripts/install.sh' ]; then
            bash $REMOTE_DIR/scripts/install.sh status
        elif [ -f '/usr/local/bin/autonas' ]; then
            /usr/local/bin/autonas --version 2>/dev/null || echo 'AutoNAS instalat dar versiune necunoscută'
        else
            echo 'AutoNAS nu este instalat'
        fi
    "
}

# Funcție pentru cleanup (ștergerea fișierelor temporare)
cleanup() {
    local target="$1"
    log_info "Cleanup fișiere temporare pe $target..."

    ssh -o LogLevel=ERROR "$SSH_USER@$target" "rm -rf $REMOTE_DIR" || true
    log_success "Cleanup realizat pe $target"
}

# Funcție pentru cleanup complet (delegat către uninstaller)
force_cleanup() {
    local target="$1"
    log_info "Cleanup forțat AutoNAS pe $target..."
    
    # Încearcă să folosească uninstaller-ul existent
    ssh -o LogLevel=ERROR "$SSH_USER@$target" "
        if [ -f '/usr/local/bin/autonas-uninstall.sh' ]; then
            bash /usr/local/bin/autonas-uninstall.sh --force
        elif [ -f '/usr/local/lib/autonas/autonas-uninstall.sh' ]; then
            bash /usr/local/lib/autonas/autonas-uninstall.sh --force
        else
            echo 'WARNING: Nu s-a găsit uninstaller-ul AutoNAS'
        fi
    " || true
    
    ssh -o LogLevel=ERROR "$SSH_USER@$target" "rm -rf $REMOTE_DIR" || true
    log_success "Cleanup forțat completat pe $target"
}

# Funcție pentru uninstall AutoNAS (delegat către uninstaller)
uninstall_autonas() {
    local target="$1"
    log_info "Dezinstalarea AutoNAS pe $target..."

    if ssh -o LogLevel=ERROR "$SSH_USER@$target" "
        if [ -f '/usr/local/bin/autonas-uninstall.sh' ]; then
            bash /usr/local/bin/autonas-uninstall.sh
            rm -f '/usr/local/bin/autonas-uninstall.sh'
            echo 'AutoNAS dezinstalat cu succes!'
        elif [ -f '/usr/local/lib/autonas/autonas-uninstall.sh' ]; then
            bash /usr/local/lib/autonas/autonas-uninstall.sh
            echo 'AutoNAS dezinstalat cu succes!'
        else
            echo 'ERROR: Scriptul de dezinstalare nu a fost găsit!'
            exit 1
        fi
    "; then
        log_success "AutoNAS dezinstalat cu succes de pe $target"
    else
        log_error "Dezinstalarea AutoNAS a eșuat pe $target"
        return 1
    fi
}

# Funcții de delegare pentru operațiunile de servicii
install_autonas() {
    run_on_target "$1" "Instalarea AutoNAS" "AutoNAS instalat cu succes pe $1" "Instalarea AutoNAS a eșuat pe $1" "install"
}

start_services() {
    run_on_target "$1" "Pornirea serviciilor AutoNAS" "Serviciile AutoNAS pornite cu succes pe $1" "Pornirea serviciilor AutoNAS a eșuat pe $1" "start"
}

restart_services() {
    run_on_target "$1" "Restartarea serviciilor AutoNAS" "Serviciile AutoNAS restartate cu succes pe $1" "Restartarea serviciilor AutoNAS a eșuat pe $1" "restart"
}

stop_services() {
    run_on_target "$1" "Oprirea serviciilor AutoNAS" "Serviciile AutoNAS oprite cu succes pe $1" "Oprirea serviciilor AutoNAS a eșuat pe $1" "stop"
}

check_dependencies() {
    run_on_target "$1" "Verificarea dependințelor" "Verificarea dependințelor completată pe $1" "Verificarea dependințelor a eșuat pe $1" "check-deps"
}

install_dependencies() {
    run_on_target "$1" "Instalarea dependințelor" "Dependințele instalate cu succes pe $1" "Instalarea dependințelor a eșuat pe $1" "install-deps"
}

# Funcție pentru afișarea ajutorului
show_help() {
    echo "Utilizare: $0 [COMANDĂ] [ȚINTE]"
    echo ""
    echo "COMENZI:"
    echo "  install       - Instalare completă AutoNAS pe toate țintele"
    echo "  install-deps  - Instalare doar dependințe (nfs-kernel-server, autofs, etc.)"
    echo "  check-deps    - Verificare dependințe fără instalare"
    echo "  uninstall     - Dezinstalare completă AutoNAS de pe toate țintele"
    echo "  start         - Pornește serviciile AutoNAS"
    echo "  restart       - Restartează serviciile AutoNAS"
    echo "  stop          - Oprește serviciile AutoNAS"
    echo "  status        - Afișează statusul serviciilor"
    echo "  cleanup       - Șterge fișierele temporare"
    echo "  force-cleanup - Cleanup agresiv (inclusiv fișiere orfane)"
    echo "  help          - Afișează acest ajutor"
    echo ""
    echo "ȚINTE (opțional):"
    echo "  192.168.2.91, 192.168.2.92, 192.168.2.93"
    echo "  Dacă nu se specifică ținte, se rulează pe toate"
    echo ""
    echo "Exemple:"
    echo "  $0 check-deps                 # Verifică dependințele pe toate țintele"
    echo "  $0 install-deps               # Instalează dependințele pe toate țintele"
    echo "  $0 install                    # Instalează pe toate țintele"
    echo "  $0 install 192.168.2.91       # Instalează doar pe .91"
    echo "  $0 restart 192.168.2.91 192.168.2.92  # Restart pe .91 și .92"
    echo "  $0 status                     # Verifică statusul pe toate țintele"
    echo "  $0 force-cleanup              # Cleanup agresiv pe toate nodurile"
}

# Funcție pentru executarea unei comenzi pe ținte specifice
execute_command() {
    local command="$1"
    shift
    local targets_to_use=("$@")


    # Dacă nu sunt specificate ținte, folosește toate din cluster.json
    if [ ${#targets_to_use[@]} -eq 0 ]; then
        targets_to_use=( $(get_targets) )
    fi

    log_info "Executare comandă '$command' pe noduri: ${targets_to_use[*]}"

    for target in "${targets_to_use[@]}"; do
        local node_name
        node_name=$(get_node_name "$target")
        echo ""
        echo "======================================"
        echo "  $command pe $node_name ($target)"
        echo "======================================"

        if ! check_ssh_connectivity "$target"; then
            log_error "Nu se poate conecta la $target - skip"
            continue
        fi

        case "$command" in
            "install")
                copy_files "$target"
                install_autonas "$target"
                start_services "$target"
                cleanup "$target"
                ;;
            "install-deps")
                copy_files "$target"
                install_dependencies "$target"
                cleanup "$target"
                ;;
            "check-deps")
                copy_files "$target"
                check_dependencies "$target"
                cleanup "$target"
                ;;
            "uninstall")
                uninstall_autonas "$target"
                cleanup "$target"
                ;;
            "start")
                start_services "$target"
                ;;
            "restart")
                restart_services "$target"
                ;;
            "stop")
                stop_services "$target"
                ;;
            "status")
                check_status "$target"
                ;;
            "cleanup")
                cleanup "$target"
                ;;
            "force-cleanup")
                force_cleanup "$target"
                ;;
            *)
                log_error "Comandă necunoscută: $command"
                return 1
                ;;
        esac

        if [ $? -eq 0 ]; then
            log_success "Comandă '$command' executată cu succes pe $target"
        else
            log_error "Comandă '$command' a eșuat pe $target"
        fi
    done
}

# Main function
main() {
    print_banner

    # Verifică dacă avem argumente
    if [ $# -eq 0 ]; then
        show_help
        exit 1
    fi

    local command="$1"
    shift

    case "$command" in
        "install"|"install-deps"|"check-deps"|"uninstall"|"start"|"restart"|"stop"|"status"|"cleanup"|"force-cleanup")
            execute_command "$command" "$@"
            ;;
        "help"|"--help"|"-h")
            show_help
            ;;
        *)
            log_error "Comandă necunoscută: $command"
            echo ""
            show_help
            exit 1
            ;;
    esac
}

# Verifică dacă rulează ca script principal
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
    main "$@"
fi
