#!/usr/bin/env bash
# Multi-node deployment script - distributes containers across available nodes

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"

source "$PROJECT_ROOT/lib/common.sh"
source "$PROJECT_ROOT/lib/proxmox-api.sh"

# Load configuration
load_config

# Node assignment strategies
assign_node_auto() {
    local memory="$1"
    local disk="$2"
    local storage="${3:-${PROXMOX_STORAGE}}"
    
    proxmox_find_available_node "$memory" "$disk" "$storage"
}

assign_node_round_robin() {
    local nodes
    nodes=$(echo "${PROXMOX_NODES:-${PROXMOX_NODE}}" | tr ',' ' ')
    local node_array=($nodes)
    local index=$((RANDOM % ${#node_array[@]}))
    echo "${node_array[$index]}"
}

assign_node_manual() {
    # For manual assignment, use configuration file mapping
    local vmid="$1"
    local node_mapping="${NODE_MAPPING:-}"
    
    if [[ -n "$node_mapping" && -f "$node_mapping" ]]; then
        local assigned_node
        assigned_node=$(grep "^${vmid}:" "$node_mapping" | cut -d: -f2 || echo "")
        if [[ -n "$assigned_node" ]]; then
            echo "$assigned_node"
            return 0
        fi
    fi
    
    # Fallback to default node
    echo "${PROXMOX_NODE}"
}

# Get node for container based on strategy
get_assignment_node() {
    local vmid="$1"
    local memory="$2"
    local disk="$3"
    local storage="${4:-${PROXMOX_STORAGE}}"
    
    local strategy="${NODE_ASSIGNMENT_STRATEGY:-auto}"
    
    case "$strategy" in
        auto)
            assign_node_auto "$memory" "$disk" "$storage"
            ;;
        round-robin)
            assign_node_round_robin
            ;;
        manual)
            assign_node_manual "$vmid"
            ;;
        *)
            log_warn "Unknown strategy: $strategy, using default node"
            echo "${PROXMOX_NODE}"
            ;;
    esac
}

# Function to create container on specific node
create_container_on_node() {
    local vmid="$1"
    local hostname="$2"
    local ip_address="$3"
    local memory="$4"
    local cores="$5"
    local disk="$6"
    local network_config="$7"
    local target_node="$8"
    local storage="${9:-${PROXMOX_STORAGE}}"
    
    log_info "Creating container $vmid ($hostname) on node $target_node..."
    
    if pct list | grep -q "^\s*$vmid\s"; then
        log_warn "Container $vmid already exists, skipping creation"
        return 0
    fi
    
    # If on target node, create directly, otherwise use API
    if [[ "$(hostname)" == "$target_node" ]] || [[ "${PROXMOX_HOST}" == "$target_node" ]]; then
        pct create "$vmid" \
            "${CONTAINER_OS_TEMPLATE:-local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst}" \
            --storage "$storage" \
            --hostname "$hostname" \
            --memory "$memory" \
            --cores "$cores" \
            --rootfs "${storage}:${disk}" \
            --net0 "$network_config" \
            --unprivileged 0 \
            --features nesting=1,keyctl=1
        
        log_success "Container $vmid created on node $target_node"
    else
        # Use API to create on remote node
        proxmox_create_container "$vmid" \
            "${CONTAINER_OS_TEMPLATE}" \
            "$storage" \
            "$hostname" \
            "$memory" \
            "$cores" \
            "$disk" \
            "$network_config" \
            "$target_node"
    fi
}

# Example: Deploy validators across nodes
deploy_validators_multi_node() {
    local count="${1:-4}"
    local start_vmid="${VMID_VALIDATORS_START:-1000}"
    
    log_info "Deploying $count validators across available nodes..."
    
    for i in $(seq 0 $((count - 1))); do
        local vmid=$((start_vmid + i))
        local hostname="validator-$((i + 1))"
        local ip_octet=$((10 + i))
        local ip_address="${SUBNET_BASE:-10.3.1}.${ip_octet}"
        
        # Assign node
        local target_node
        target_node=$(get_assignment_node "$vmid" "${VALIDATOR_MEMORY:-8192}" "${VALIDATOR_DISK:-100}")
        
        log_info "Validator $((i + 1)) will be deployed on node: $target_node"
        
        # Network config
        local vlan="${VLAN_VALIDATORS:-100}"
        local network_config="bridge=${PROXMOX_BRIDGE:-vmbr0},tag=$vlan,name=eth0,ip=${ip_address}/${NETMASK:-24},gw=${GATEWAY:-10.3.1.1}"
        
        # Create container
        create_container_on_node \
            "$vmid" \
            "$hostname" \
            "$ip_address" \
            "${VALIDATOR_MEMORY:-8192}" \
            "${VALIDATOR_CORES:-4}" \
            "${VALIDATOR_DISK:-100}" \
            "$network_config" \
            "$target_node"
    done
}

# Main
if [[ $# -eq 0 ]]; then
    echo "Usage: $0 <command> [options]"
    echo ""
    echo "Commands:"
    echo "  validators [count]  - Deploy validators across nodes"
    echo "  list-nodes          - List available nodes"
    echo "  check-resources     - Check resource availability on all nodes"
    exit 1
fi

check_root

COMMAND="$1"
shift || true

case "$COMMAND" in
    validators)
        COUNT="${1:-4}"
        deploy_validators_multi_node "$COUNT"
        ;;
    list-nodes)
        log_info "Available nodes:"
        local nodes_output
        nodes_output=$(proxmox_list_nodes 2>/dev/null)
        if command_exists jq && [[ -n "$nodes_output" ]]; then
            echo "$nodes_output" | jq -r '.data[] | "  - \(.node): \(.status)"' 2>/dev/null
        else
            if [[ -n "${PROXMOX_NODES:-}" ]]; then
                echo "$PROXMOX_NODES" | tr ',' '\n' | while read -r node; do
                    log_info "  - $node"
                done
            else
                log_info "  - ${PROXMOX_NODE} (default node)"
            fi
        fi
        ;;
    check-resources)
        log_info "Checking resources on all nodes..."
        local nodes
        nodes=$(echo "${PROXMOX_NODES:-${PROXMOX_NODE}}" | tr ',' ' ')
        for node in $nodes; do
            log_info "Node: $node"
            proxmox_get_storage_usage "$node" "${PROXMOX_STORAGE}"
        done
        ;;
    *)
        error_exit "Unknown command: $COMMAND"
        ;;
esac

log_success "Multi-node deployment completed!"

