#!/bin/bash
# SSH Manager CLI - Simple and powerful SSH server management

set -e

# Script directory - resolve symlinks if necessary
if [ -L "$0" ]; then
    # Script is a symlink, resolve it
    SCRIPT_PATH="$(readlink -f "$0" 2>/dev/null || readlink "$0")"
else
    SCRIPT_PATH="$0"
fi
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)"

# Source libraries
source "$SCRIPT_DIR/lib/colors.sh"
source "$SCRIPT_DIR/lib/config.sh"
source "$SCRIPT_DIR/lib/menu.sh"

# Source command modules
source "$SCRIPT_DIR/commands/server.sh"
source "$SCRIPT_DIR/commands/tools.sh"

# Version
VERSION="3.1.0"

# Show version
show_version() {
    echo "SSH Manager CLI v$VERSION"
    echo "Simple and powerful SSH server management"
}

# Show help
show_help() {
    cat <<EOF
${BOLD}SSH Manager CLI${NC} - Simple and powerful SSH server management

${BOLD}USAGE:${NC}
    ssh-manager              # Interactive mode (menu)
    ssh-manager -i           # Interactive mode (menu)
    ssh-manager <command>    # Direct command mode

${BOLD}COMMANDS:${NC}
    ${CYAN}server${NC}      Server management
        add         Add a new server
        list        List all servers
        test        Test server connection
        remove      Remove a server
        edit        Edit server configuration
        show        Show server details
    
    ${CYAN}sync${NC}        File synchronization (rsync)
        push        Push files to server
        pull        Pull files from server
    
    ${CYAN}tunnel${NC}      SSH tunnel management
        create      Create a new tunnel
        list        List active tunnels
        close       Close a tunnel
    
    ${CYAN}monitor${NC}     System monitoring
        cpu         Monitor CPU usage
        memory      Monitor memory usage
        disk        Monitor disk usage
        network     Monitor network
    
    ${CYAN}session${NC}     SSH session management
        start       Start interactive session
        list        List active sessions
        close       Close a session
    
    ${CYAN}exec${NC}        Execute commands
        run         Run command on server
        group       Run on server group
    
    ${CYAN}config${NC}      Configuration
        edit        Edit configuration
        show        Show configuration
        init        Initialize configuration

    ${CYAN}tools${NC}       Tool activation/deactivation
        list        Show all tools and their status
        configure   Interactive configuration wizard
        enable      Enable a tool group
        disable     Disable a tool group
        reset       Reset to default (all tools enabled)
        export      Export Claude Code auto-approval config

${BOLD}OPTIONS:${NC}
    -h, --help      Show this help message
    -v, --version   Show version
    -q, --quiet     Quiet mode
    -d, --debug     Debug mode

${BOLD}EXAMPLES:${NC}
    # Add a new server
    ssh-manager server add
    
    # List all servers
    ssh-manager server list
    
    # Test connection to prod1
    ssh-manager server test prod1
    
    # Sync files to server
    ssh-manager sync push prod1 ./app /var/www/app
    
    # Create SSH tunnel
    ssh-manager tunnel create prod1 local 3307:localhost:3306
    
    # Monitor server
    ssh-manager monitor prod1 cpu

${BOLD}CONFIGURATION:${NC}
    Config directory: ${SSH_MANAGER_HOME:-~/.ssh-manager}
    Server config:    ${SSH_MANAGER_ENV:-.env}

${BOLD}DOCUMENTATION:${NC}
    https://github.com/bvisible/mcp-ssh-manager

EOF
}

# Execute command on server
cmd_exec() {
    local server="$1"
    shift
    local command="$@"
    
    if [ -z "$server" ] || [ -z "$command" ]; then
        print_error "Usage: ssh-manager exec <server> <command>"
        return 1
    fi
    
    local host=$(get_server_config "$server" "HOST")
    local user=$(get_server_config "$server" "USER")
    local port=$(get_server_config "$server" "PORT")
    local keypath=$(get_server_config "$server" "KEYPATH")
    
    port=${port:-22}
    
    if [ -z "$host" ] || [ -z "$user" ]; then
        print_error "Server '$server' not found"
        return 1
    fi
    
    local ssh_opts="-p $port"
    if [ -n "$keypath" ]; then
        ssh_opts="$ssh_opts -i $keypath"
    fi
    
    print_info "Executing on $server: $command"
    ssh $ssh_opts "$user@$host" "$command"
}

# Sync files using rsync
cmd_sync() {
    local direction="$1"
    local server="$2"
    local source="$3"
    local dest="$4"

    if [ -z "$direction" ] || [ -z "$server" ] || [ -z "$source" ] || [ -z "$dest" ]; then
        print_error "Usage: ssh-manager sync <push|pull> <server> <source> <destination>"
        return 1
    fi

    # rsync is only required at this point — fail with a clear message
    # rather than blocking the whole CLI at startup.
    require_command rsync "ssh-manager sync" || return 1
    
    local host=$(get_server_config "$server" "HOST")
    local user=$(get_server_config "$server" "USER")
    local port=$(get_server_config "$server" "PORT")
    local keypath=$(get_server_config "$server" "KEYPATH")
    
    port=${port:-22}
    
    if [ -z "$host" ] || [ -z "$user" ]; then
        print_error "Server '$server' not found"
        return 1
    fi
    
    local ssh_opts="ssh -p $port"
    if [ -n "$keypath" ]; then
        ssh_opts="$ssh_opts -i $keypath"
    fi
    
    local rsync_opts="-avz --progress"
    
    case "$direction" in
        push)
            print_info "Pushing $source to $server:$dest"
            rsync $rsync_opts -e "$ssh_opts" "$source" "$user@$host:$dest"
            ;;
        pull)
            print_info "Pulling $server:$source to $dest"
            rsync $rsync_opts -e "$ssh_opts" "$user@$host:$source" "$dest"
            ;;
        *)
            print_error "Invalid direction: $direction (use push or pull)"
            return 1
            ;;
    esac
}

# Quick SSH connection
cmd_ssh() {
    local server="$1"
    
    if [ -z "$server" ]; then
        print_error "Usage: ssh-manager ssh <server>"
        return 1
    fi
    
    local host=$(get_server_config "$server" "HOST")
    local user=$(get_server_config "$server" "USER")
    local port=$(get_server_config "$server" "PORT")
    local keypath=$(get_server_config "$server" "KEYPATH")
    
    port=${port:-22}
    
    if [ -z "$host" ] || [ -z "$user" ]; then
        print_error "Server '$server' not found"
        return 1
    fi
    
    local ssh_opts="-p $port"
    if [ -n "$keypath" ]; then
        ssh_opts="$ssh_opts -i $keypath"
    fi
    
    print_info "Connecting to $server..."
    ssh $ssh_opts "$user@$host"
}

# Simple tunnel creation
cmd_tunnel() {
    local action="$1"
    shift
    
    case "$action" in
        create)
            local server="$1"
            local type="$2"
            local ports="$3"
            
            if [ -z "$server" ] || [ -z "$type" ] || [ -z "$ports" ]; then
                print_error "Usage: ssh-manager tunnel create <server> <local|remote|dynamic> <ports>"
                print_info "Examples:"
                print_info "  Local:   ssh-manager tunnel create prod1 local 3307:localhost:3306"
                print_info "  Remote:  ssh-manager tunnel create prod1 remote 8080:localhost:8080"
                print_info "  Dynamic: ssh-manager tunnel create prod1 dynamic 1080"
                return 1
            fi
            
            local host=$(get_server_config "$server" "HOST")
            local user=$(get_server_config "$server" "USER")
            local port=$(get_server_config "$server" "PORT")
            local keypath=$(get_server_config "$server" "KEYPATH")
            
            port=${port:-22}
            
            if [ -z "$host" ] || [ -z "$user" ]; then
                print_error "Server '$server' not found"
                return 1
            fi
            
            local ssh_opts="-p $port -N -f"
            if [ -n "$keypath" ]; then
                ssh_opts="$ssh_opts -i $keypath"
            fi
            
            case "$type" in
                local)
                    print_info "Creating local tunnel: $ports"
                    ssh $ssh_opts -L "$ports" "$user@$host"
                    ;;
                remote)
                    print_info "Creating remote tunnel: $ports"
                    ssh $ssh_opts -R "$ports" "$user@$host"
                    ;;
                dynamic)
                    print_info "Creating SOCKS proxy on port $ports"
                    ssh $ssh_opts -D "$ports" "$user@$host"
                    ;;
                *)
                    print_error "Invalid tunnel type: $type"
                    return 1
                    ;;
            esac
            
            if [ $? -eq 0 ]; then
                print_success "Tunnel created successfully"
            else
                print_error "Failed to create tunnel"
                return 1
            fi
            ;;
            
        list)
            print_header "Active SSH Tunnels"
            ps aux | grep -E "ssh.*(-L|-R|-D)" | grep -v grep || print_info "No active tunnels"
            ;;
            
        *)
            print_error "Unknown tunnel command: $action"
            echo "Available commands: create, list"
            return 1
            ;;
    esac
}

# Main command handler
main() {
    # Check for help/version flags
    case "$1" in
        -h|--help|help)
            show_help
            exit 0
            ;;
        -v|--version|version)
            show_version
            exit 0
            ;;
    esac
    
    # Initialize configuration
    init_config
    
    # Check dependencies
    if ! check_dependencies; then
        exit 1
    fi
    
    # Get command
    local command="$1"
    shift || true
    
    # Handle commands
    case "$command" in
        server)
            cmd_server "$@"
            ;;
        exec)
            cmd_exec "$@"
            ;;
        sync)
            cmd_sync "$@"
            ;;
        ssh|connect)
            cmd_ssh "$@"
            ;;
        tunnel)
            cmd_tunnel "$@"
            ;;
        tools)
            cmd_tools "$@"
            ;;
        config)
            case "$1" in
                edit)
                    ${EDITOR:-nano} "$SSH_MANAGER_CONFIG"
                    ;;
                show)
                    cat "$SSH_MANAGER_CONFIG"
                    ;;
                init)
                    init_config
                    ;;
                *)
                    print_error "Unknown config command: $1"
                    ;;
            esac
            ;;
        ""|-i|--interactive|menu)
            # Interactive mode
            interactive_mode
            ;;
        *)
            print_error "Unknown command: $command"
            echo "Run 'ssh-manager --help' for usage information"
            exit 1
            ;;
    esac
}

# Interactive mode with menu
interactive_mode() {
    # Initialize configuration
    init_config
    
    # Check dependencies
    if ! check_dependencies; then
        exit 1
    fi
    
    while true; do
        show_main_menu
        read choice
        
        case "$choice" in
            1)
                # Server Management submenu
                while true; do
                    show_server_menu
                    read server_choice
                    
                    case "$server_choice" in
                        1)
                            wizard_add_server
                            ;;
                        2)
                            cmd_server_list
                            echo
                            read -p "Press Enter to continue..."
                            ;;
                        3)
                            if select_server_menu "Test Connection"; then
                                test_ssh_connection "$selected_server"
                                echo
                                read -p "Press Enter to continue..."
                            fi
                            ;;
                        4)
                            if select_server_menu "Show Server Details"; then
                                cmd_server_show "$selected_server"
                                echo
                                read -p "Press Enter to continue..."
                            fi
                            ;;
                        5)
                            wizard_edit_server
                            echo
                            read -p "Press Enter to continue..."
                            ;;
                        6)
                            if select_server_menu "Remove Server"; then
                                echo
                                if prompt_yes_no "Remove server '$selected_server'?" "n"; then
                                    remove_server_from_env "$selected_server"
                                fi
                                echo
                                read -p "Press Enter to continue..."
                            fi
                            ;;
                        7)
                            cmd_server_edit_file
                            echo
                            read -p "Press Enter to continue..."
                            ;;
                        0)
                            break
                            ;;
                    esac
                done
                ;;
            2)
                # Quick Connect
                if select_server_menu "Quick Connect"; then
                    print_info "Connecting to $selected_server..."
                    cmd_ssh "$selected_server"
                fi
                ;;
            3)
                # File Sync
                show_sync_menu
                ;;
            4)
                # SSH Tunnels
                wizard_create_tunnel
                ;;
            5)
                # System Monitoring
                if select_server_menu "System Monitoring"; then
                    echo
                    print_subheader "Monitor Type"
                    echo "  1) Overview"
                    echo "  2) CPU"
                    echo "  3) Memory"
                    echo "  4) Disk"
                    echo "  5) Network"
                    echo
                    read -p "Choose [1-5]: " monitor_type
                    
                    case "$monitor_type" in
                        1) cmd_exec "$selected_server" "uptime && free -h && df -h" ;;
                        2) cmd_exec "$selected_server" "top -bn1 | head -20" ;;
                        3) cmd_exec "$selected_server" "free -h && ps aux --sort=-%mem | head -10" ;;
                        4) cmd_exec "$selected_server" "df -h && du -sh /* 2>/dev/null | sort -h | tail -10" ;;
                        5) cmd_exec "$selected_server" "netstat -tulpn 2>/dev/null | grep LISTEN" ;;
                    esac
                    echo
                    read -p "Press Enter to continue..."
                fi
                ;;
            6)
                # Execute Commands
                if select_server_menu "Execute Command"; then
                    echo
                    local command
                    prompt_input "Command to execute" "uptime" "command"
                    echo
                    cmd_exec "$selected_server" "$command"
                    echo
                    read -p "Press Enter to continue..."
                fi
                ;;
            7)
                # Configuration
                clear
                print_header "Configuration"
                echo "  1) Edit CLI config"
                echo "  2) Show CLI config"
                echo "  3) Edit server config (.env)"
                echo "  0) Back"
                echo
                read -p "Choose [0-3]: " config_choice
                
                case "$config_choice" in
                    1) ${EDITOR:-nano} "$SSH_MANAGER_CONFIG" ;;
                    2) cat "$SSH_MANAGER_CONFIG"; read -p "Press Enter..." ;;
                    3) cmd_server_edit ;;
                esac
                ;;
            8)
                # Help
                show_help | less
                ;;
            0|q|Q)
                print_info "Goodbye!"
                exit 0
                ;;
        esac
    done
}

# Run main function
main "$@"