#!/usr/bin/env bash
# Proxmox API wrapper functions with multi-node and storage support

set -euo pipefail

source "$(dirname "${BASH_SOURCE[0]}")/common.sh"

# Proxmox API base URL
PROXMOX_API_BASE=""

# Load .env file from ~/.env (standardized location)
load_env_file() {
    local env_file="${HOME}/.env"
    if [[ -f "$env_file" ]]; then
        # Source PROXMOX_* variables from ~/.env
        set -a
        source <(grep -E "^PROXMOX_" "$env_file" 2>/dev/null | sed 's/^/export /' || true)
        set +a
    fi
}

# Initialize Proxmox API
init_proxmox_api() {
    # Load from ~/.env first (standardized location)
    load_env_file
    
    # Then load config file (which may override or add additional settings)
    load_config
    
    # Use PROXMOX_TOKEN_VALUE from .env, fallback to PROXMOX_TOKEN_SECRET for backwards compatibility
    if [[ -z "${PROXMOX_TOKEN_SECRET:-}" ]] && [[ -n "${PROXMOX_TOKEN_VALUE:-}" ]]; then
        PROXMOX_TOKEN_SECRET="${PROXMOX_TOKEN_VALUE}"
    fi
    
    validate_vars PROXMOX_HOST PROXMOX_PORT PROXMOX_USER PROXMOX_TOKEN_NAME PROXMOX_TOKEN_SECRET
    
    PROXMOX_API_BASE="https://${PROXMOX_HOST}:${PROXMOX_PORT}/api2/json"
    
    log_debug "Initialized Proxmox API: $PROXMOX_API_BASE"
}

# Make Proxmox API call
proxmox_api_call() {
    local method="${1:-GET}"
    local endpoint="${2:-}"
    local data="${3:-}"
    local node="${4:-${PROXMOX_NODE}}"
    
    if [[ -z "$PROXMOX_API_BASE" ]]; then
        init_proxmox_api
    fi
    
    # Replace {node} placeholder if present
    endpoint="${endpoint//\{node\}/$node}"
    
    local url="${PROXMOX_API_BASE}${endpoint}"
    local auth_header="Authorization: PVEAPIToken=${PROXMOX_USER}=${PROXMOX_TOKEN_NAME}=${PROXMOX_TOKEN_SECRET}"
    
    local curl_opts=(
        -s
        -k
        -X "$method"
        -H "$auth_header"
        -H "Content-Type: application/json"
    )
    
    if [[ -n "$data" ]]; then
        curl_opts+=(-d "$data")
    fi
    
    log_debug "Proxmox API: $method $url"
    
    curl "${curl_opts[@]}" "$url"
}

# List all nodes in cluster
proxmox_list_nodes() {
    proxmox_api_call "GET" "/nodes"
}

# Get node storage information
proxmox_get_node_storage() {
    local node="${1:-${PROXMOX_NODE}}"
    proxmox_api_call "GET" "/nodes/{node}/storage" "" "$node"
}

# Get available storage pools
proxmox_list_storage() {
    local node="${1:-${PROXMOX_NODE}}"
    proxmox_api_call "GET" "/nodes/{node}/storage" "" "$node"
}

# Get storage usage
proxmox_get_storage_usage() {
    local node="${1:-${PROXMOX_NODE}}"
    local storage="${2:-${PROXMOX_STORAGE}}"
    proxmox_api_call "GET" "/nodes/{node}/storage/${storage}/status" "" "$node"
}

# Find node with available resources
proxmox_find_available_node() {
    local required_memory="${1:-4096}"  # MB
    local required_disk="${2:-100}"     # GB
    local preferred_storage="${3:-${PROXMOX_STORAGE}}"
    
    log_info "Finding node with available resources (RAM: ${required_memory}MB, Disk: ${required_disk}GB)..."
    
    local nodes
    nodes=$(proxmox_list_nodes | jq -r '.data[].node' 2>/dev/null || echo "${PROXMOX_NODE}")
    
    for node in $nodes; do
        log_debug "Checking node: $node"
        
        # Check storage availability
        local storage_info
        storage_info=$(proxmox_get_storage_usage "$node" "$preferred_storage" 2>/dev/null)
        
        if [[ -n "$storage_info" ]]; then
            local available_space
            available_space=$(echo "$storage_info" | jq -r '.data.avail // 0' 2>/dev/null || echo "0")
            available_space=$((available_space / 1024 / 1024 / 1024))  # Convert to GB
            
            if [[ $available_space -gt $required_disk ]]; then
                log_info "Node $node has sufficient storage (${available_space}GB available)"
                echo "$node"
                return 0
            fi
        fi
    done
    
    log_warn "No suitable node found, using default: ${PROXMOX_NODE}"
    echo "${PROXMOX_NODE}"
    return 1
}

# Create LXC container via API with node selection
proxmox_create_container() {
    local vmid="$1"
    local ostemplate="$2"
    local storage="${3:-${PROXMOX_STORAGE}}"
    local hostname="$4"
    local memory="${5:-2048}"
    local cores="${6:-2}"
    local disk="${7:-20}"
    local network="${8:-}"
    local target_node="${9:-}"
    
    load_config
    
    # Select node if not specified
    if [[ -z "$target_node" ]]; then
        target_node=$(proxmox_find_available_node "$memory" "$disk" "$storage")
    fi
    
    local data="{
        \"vmid\": $vmid,
        \"ostemplate\": \"$ostemplate\",
        \"storage\": \"$storage\",
        \"hostname\": \"$hostname\",
        \"memory\": $memory,
        \"cores\": $cores,
        \"rootfs\": \"$storage:$disk\",
        \"net0\": \"$network\"
    }"
    
    log_info "Creating container $vmid ($hostname) on node $target_node via API..."
    proxmox_api_call "POST" "/nodes/${target_node}/lxc" "$data" "$target_node"
}

# Expand container disk
proxmox_expand_disk() {
    local vmid="$1"
    local additional_size="${2:-50}"  # GB
    local node="${3:-}"
    
    load_config
    
    # Find node if not specified
    if [[ -z "$node" ]]; then
        node=$(pct list | grep "^\s*$vmid\s" | awk '{print $3}' || echo "${PROXMOX_NODE}")
    fi
    
    log_info "Expanding disk for container $vmid by ${additional_size}GB on node $node..."
    
    # Get current disk size
    local current_config
    current_config=$(pct config "$vmid" 2>/dev/null | grep "rootfs:" || echo "")
    
    if [[ -z "$current_config" ]]; then
        log_error "Could not get current disk configuration for container $vmid"
        return 1
    fi
    
    # Extract current size
    local current_size
    current_size=$(echo "$current_config" | grep -oP 'size=\K[0-9]+' || echo "0")
    
    local new_size=$((current_size + additional_size))
    
    log_info "Expanding container $vmid disk from ${current_size}GB to ${new_size}GB..."
    
    # Expand disk using pct
    pct resize "$vmid" rootfs "+${additional_size}G" || {
        log_error "Failed to expand disk for container $vmid"
        return 1
    }
    
    log_success "Successfully expanded disk for container $vmid to ${new_size}GB"
}

# Migrate container to another node
proxmox_migrate_container() {
    local vmid="$1"
    local target_node="$2"
    local storage="${3:-}"
    local migrate_storage="${4:-false}"
    
    load_config
    
    # Get current node
    local current_node
    current_node=$(pct list | grep "^\s*$vmid\s" | awk '{print $3}' || echo "${PROXMOX_NODE}")
    
    if [[ "$current_node" == "$target_node" ]]; then
        log_warn "Container $vmid is already on node $target_node"
        return 0
    fi
    
    log_info "Migrating container $vmid from $current_node to $target_node..."
    
    # Stop container if running
    if pct status "$vmid" | grep -q "running"; then
        log_info "Stopping container $vmid for migration..."
        pct stop "$vmid" --skiplock
    fi
    
    # Migrate container
    local migrate_opts=("migrate" "$vmid" "$target_node" "--restart")
    
    if [[ -n "$storage" ]]; then
        migrate_opts+=("--storage" "$storage")
    fi
    
    if [[ "$migrate_storage" == "true" ]]; then
        migrate_opts+=("--migrate-datastore")
    fi
    
    pct "${migrate_opts[@]}" || {
        log_error "Failed to migrate container $vmid to node $target_node"
        return 1
    }
    
    log_success "Successfully migrated container $vmid to node $target_node"
}

# Start container
proxmox_start_container() {
    local vmid="$1"
    local node="${2:-}"
    load_config
    
    if [[ -z "$node" ]]; then
        node=$(pct list | grep "^\s*$vmid\s" | awk '{print $3}' || echo "${PROXMOX_NODE}")
    fi
    
    validate_vars node
    
    log_info "Starting container $vmid on node $node..."
    proxmox_api_call "POST" "/nodes/${node}/lxc/$vmid/status/start" "" "$node"
}

# Stop container
proxmox_stop_container() {
    local vmid="$1"
    local node="${2:-}"
    load_config
    
    if [[ -z "$node" ]]; then
        node=$(pct list | grep "^\s*$vmid\s" | awk '{print $3}' || echo "${PROXMOX_NODE}")
    fi
    
    validate_vars node
    
    log_info "Stopping container $vmid on node $node..."
    proxmox_api_call "POST" "/nodes/${node}/lxc/$vmid/status/stop" "" "$node"
}

# Get container status
proxmox_get_container_status() {
    local vmid="$1"
    local node="${2:-}"
    load_config
    
    if [[ -z "$node" ]]; then
        node=$(pct list | grep "^\s*$vmid\s" | awk '{print $3}' || echo "${PROXMOX_NODE}")
    fi
    
    validate_vars node
    
    proxmox_api_call "GET" "/nodes/${node}/lxc/$vmid/status/current" "" "$node"
}

# List containers
proxmox_list_containers() {
    local node="${1:-}"
    load_config
    
    if [[ -n "$node" ]]; then
        proxmox_api_call "GET" "/nodes/${node}/lxc" "" "$node"
    else
        # List all containers across all nodes
        local nodes
        nodes=$(proxmox_list_nodes | jq -r '.data[].node' 2>/dev/null || echo "${PROXMOX_NODE}")
        for n in $nodes; do
            proxmox_api_call "GET" "/nodes/${n}/lxc" "" "$n"
        done
    fi
}

# Get container current node
proxmox_get_container_node() {
    local vmid="$1"
    pct list | grep "^\s*$vmid\s" | awk '{print $3}' || echo "${PROXMOX_NODE}"
}

# Create container using pct command (when API not available)
pct_create_container() {
    local vmid="$1"
    local ostemplate="$2"
    local storage="${3:-${PROXMOX_STORAGE}}"
    local hostname="$4"
    local memory="${5:-2048}"
    local cores="${6:-2}"
    local disk="${7:-20}"
    local network="${8:-}"
    local target_node="${9:-${PROXMOX_NODE}}"
    
    load_config
    
    log_info "Creating container $vmid ($hostname) on node $target_node using pct..."
    
    # Switch to target node if needed
    if [[ "$target_node" != "$(hostname)" ]]; then
        log_info "Note: Creating on node $target_node - ensure you're on that node or use API"
    fi
    
    local create_cmd=(
        pct create "$vmid"
        "$ostemplate"
        "--storage" "$storage"
        "--hostname" "$hostname"
        "--memory" "$memory"
        "--cores" "$cores"
        "--rootfs" "${storage}:${disk}"
        "--net0" "$network"
        "--unprivileged" "0"
        "--features" "nesting=1,keyctl=1"
    )
    
    "${create_cmd[@]}"
    
    log_success "Container $vmid created successfully on node $target_node"
}
