#!/usr/bin/env bash
# Setup ThirdWeb RPC Node LXC Containers
# Creates and configures Besu RPC nodes optimized for ThirdWeb integration
#
# VMIDs: 2400-2402 (ThirdWeb RPC nodes) - aligned with IP addresses
# IP Range: 192.168.11.240-242 (VMIDs 2400-2402)
# IP Management: VMID 2400 = 192.168.11.240, VMID 2401 = 192.168.11.241, etc.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
CONFIG_DIR="$PROJECT_ROOT/smom-dbis-138/config"

# Configuration
PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.10}"
STORAGE="${STORAGE:-local-lvm}"  # Use local-lvm (LVM-thin) like other containers
TEMPLATE="${TEMPLATE:-local:vztmpl/debian-12-standard_12.12-1_amd64.tar.zst}"
NETWORK="${NETWORK:-vmbr0}"
GATEWAY="${GATEWAY:-192.168.11.1}"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }

# VMID to IP Address Mapping Function
# Maps VMID to IP based on VMID pattern for 192.168.11.X network:
#   - 4-digit VMID (2400-2499) -> last octet matches last 2 digits
#   - Example: VMID 2400 = 192.168.11.240, VMID 2401 = 192.168.11.241
vmid_to_ip() {
    local vmid=$1
    local base_network="${2:-192.168.11}"
    
    # For 4-digit VMIDs in 192.168.11.X network
    if [[ $vmid =~ ^[0-9]{4}$ ]] && [[ "$base_network" == "192.168.11" ]]; then
        local last_octet=$((vmid % 1000))
        # Ensure last octet is in valid range (1-254, since .255 is broadcast)
        if [[ $last_octet -ge 1 ]] && [[ $last_octet -le 254 ]]; then
            echo "${base_network}.${last_octet}"
            return 0
        fi
    fi
    
    # Fallback: return empty (should not happen with valid VMIDs)
    echo ""
    return 1
}

# ThirdWeb RPC Node Configuration
# VMIDs 2400-2402 map to IPs 192.168.11.240-242 (aligned numbering)
# Note: .254 is last usable IP, .255 is broadcast in /24 network
#       Existing RPC nodes use .250-252 (VMIDs 2500-2502)
declare -A THIRDWEB_RPC_NODES=(
    [2400]="thirdweb-rpc-1:192.168.11.240:ThirdWeb RPC Node 1 (Primary)"
    [2401]="thirdweb-rpc-2:192.168.11.241:ThirdWeb RPC Node 2 (Secondary)"
    [2402]="thirdweb-rpc-3:192.168.11.242:ThirdWeb RPC Node 3 (Tertiary)"
)

# Resource specifications per node
MEMORY_GB=16
CPU_CORES=4
DISK_GB=200

# Check SSH access
check_ssh_access() {
    log_info "Checking SSH access to $PROXMOX_HOST..."
    if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} "echo 'SSH OK'" &>/dev/null; then
        log_success "SSH access confirmed"
        return 0
    else
        log_error "Cannot access $PROXMOX_HOST via SSH"
        log_error "Please ensure:"
        log_error "  1. SSH key is set up"
        log_error "  2. Host is reachable"
        log_error "  3. Root access is available"
        return 1
    fi
}

# Check if container exists
container_exists() {
    local vmid=$1
    ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} \
        "pct list | grep -q '^$vmid ' && echo 'exists' || echo 'missing'" 2>/dev/null || echo "error"
}

# Create a container
create_container() {
    local vmid=$1
    local hostname=$2
    local ip=$3
    local description="$4"
    
    log_info "Creating container $vmid: $hostname ($ip)..."
    
    # Check if already exists
    local exists=$(container_exists "$vmid")
    if [[ "$exists" == "exists" ]]; then
        log_warn "Container $vmid already exists, skipping creation..."
        return 0
    fi
    
    log_info "  Memory: ${MEMORY_GB}GB, CPU: ${CPU_CORES} cores, Disk: ${DISK_GB}GB"
    log_info "  Creating with DHCP first, then configuring static IP..."
    
    # Create container with DHCP (more reliable)
    ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} <<CREATE_CONTAINER_EOF
set -e
pct create $vmid $TEMPLATE \
    --hostname $hostname \
    --memory $((MEMORY_GB * 1024)) \
    --cores ${CPU_CORES} \
    --rootfs ${STORAGE}:${DISK_GB} \
    --net0 name=eth0,bridge=${NETWORK},ip=dhcp,type=veth \
    --description "$description" \
    --start 1 \
    --onboot 1 \
    --unprivileged 0 \
    --features nesting=1,keyctl=1
CREATE_CONTAINER_EOF
    
    if [ $? -eq 0 ]; then
        log_success "Container $vmid created successfully with DHCP"
        
        # Wait for container to start
        log_info "  Waiting for container to start..."
        sleep 8
        
        # Check status
        local status=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} \
            "pct status $vmid 2>/dev/null | awk '{print \$2}'" || echo "unknown")
        
        if [[ "$status" == "running" ]]; then
            log_success "  Container $vmid is running"
            
            # Now configure static IP
            log_info "  Configuring static IP: $ip/24"
            local configure_result=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} bash -s <<CONFIGURE_IP_EOF
set -e
VMID=$vmid
NETWORK=$NETWORK
IP=$ip
GATEWAY=$GATEWAY

# Stop container to configure network
pct stop \$VMID 2>/dev/null || true
sleep 2

# Get current MAC address from config (if exists)
MAC_ADDRESS=\$(pct config \$VMID 2>/dev/null | grep "^net0:" | sed -n 's/.*hwaddr=\\([^,]*\\).*/\\1/p' || echo "")

if [[ -z "\$MAC_ADDRESS" ]]; then
    # Generate a new MAC address if not found
    MAC_ADDRESS=\$(printf "02:00:27:%02x:%02x:%02x" \$((RANDOM%256)) \$((RANDOM%256)) \$((RANDOM%256)))
fi

# Configure static IP
if pct set \$VMID --net0 name=eth0,bridge=\$NETWORK,hwaddr=\$MAC_ADDRESS,ip=\$IP/24,gw=\$GATEWAY,type=veth; then
    # Start container
    pct start \$VMID
    echo "SUCCESS"
else
    echo "FAILED"
    exit 1
fi
CONFIGURE_IP_EOF
)

            if echo "$configure_result" | grep -q "SUCCESS"; then
                log_success "  Static IP configured: $ip/24"
                sleep 5
            else
                log_warn "  Failed to configure static IP, container is running with DHCP"
                log_info "  Attempting to start container anyway..."
                ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} "pct start $vmid 2>/dev/null || true"
            fi
        else
            log_warn "  Container $vmid status: $status"
        fi
        
        return 0
    else
        log_error "Failed to create container $vmid"
        return 1
    fi
}

# Setup container with Besu RPC
setup_besu_rpc() {
    local vmid=$1
    local hostname=$2
    local ip=$3
    
    log_info "Setting up Besu RPC on container $vmid..."
    
    # Copy installation script
    local install_script="$SCRIPT_DIR/../smom-dbis-138-proxmox/install/besu-rpc-install.sh"
    if [[ ! -f "$install_script" ]]; then
        log_error "Besu installation script not found: $install_script"
        return 1
    fi
    
    # Copy config file
    local config_file="$CONFIG_DIR/config-rpc-thirdweb.toml"
    if [[ ! -f "$config_file" ]]; then
        log_warn "ThirdWeb config not found, will create default..."
        create_thirdweb_config "$config_file"
    fi
    
    # First, copy files to Proxmox host, then push to container
    log_info "  Copying files to Proxmox host..."
    local remote_install="/tmp/besu-rpc-install-$$.sh"
    local remote_config="/tmp/config-rpc-thirdweb-$$.toml"
    
    # Define paths for genesis and permissions (before heredoc)
    local genesis_dir="$PROJECT_ROOT/smom-dbis-138/genesis"
    local permissions_dir="$PROJECT_ROOT/smom-dbis-138/permissions"
    
    scp -o ConnectTimeout=5 -o StrictHostKeyChecking=no "$install_script" root@${PROXMOX_HOST}:${remote_install} || {
        log_error "Failed to copy installation script to Proxmox host"
        return 1
    }
    
    scp -o ConnectTimeout=5 -o StrictHostKeyChecking=no "$config_file" root@${PROXMOX_HOST}:${remote_config} || {
        log_error "Failed to copy config file to Proxmox host"
        return 1
    }
    
    # Execute setup inside container
    ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} <<SETUP_EOF
set -e

# Wait for container to be fully ready
echo "Waiting for container $vmid to be ready..."
for i in {1..30}; do
    if pct exec $vmid -- test -f /etc/os-release 2>/dev/null; then
        break
    fi
    sleep 1
done

# Copy installation script from Proxmox host to container
pct push $vmid ${remote_install} /tmp/besu-rpc-install.sh

# Copy config from Proxmox host to container
pct push $vmid ${remote_config} /tmp/config-rpc-thirdweb.toml

# Install Besu
pct exec $vmid -- bash /tmp/besu-rpc-install.sh

# Move config to proper location
pct exec $vmid -- mkdir -p /etc/besu
pct exec $vmid -- cp /tmp/config-rpc-thirdweb.toml /etc/besu/config-rpc-thirdweb.toml

# Update systemd service to use ThirdWeb config
pct exec $vmid -- sed -i 's|config-rpc.toml|config-rpc-thirdweb.toml|g' /etc/systemd/system/besu-rpc.service || true

# Reload systemd and enable service
pct exec $vmid -- systemctl daemon-reload
pct exec $vmid -- systemctl enable besu-rpc.service

echo "Besu RPC setup completed for $vmid"
SETUP_EOF
    
    # Copy genesis and permissions files if they exist (after heredoc to avoid variable issues)
    local genesis_dir="$PROJECT_ROOT/smom-dbis-138/genesis"
    local permissions_dir="$PROJECT_ROOT/smom-dbis-138/permissions"
    
    if [[ -d "$genesis_dir" ]]; then
        log_info "  Copying genesis files..."
        ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} "pct exec $vmid -- mkdir -p /genesis /permissions" || true
        
        if [[ -f "$genesis_dir/genesis.json" ]]; then
            local remote_genesis="/tmp/genesis-$$.json"
            scp -o ConnectTimeout=5 -o StrictHostKeyChecking=no "$genesis_dir/genesis.json" root@${PROXMOX_HOST}:${remote_genesis} && {
                ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} "pct push $vmid ${remote_genesis} /genesis/genesis.json && rm -f ${remote_genesis}" || true
            }
        fi
        
        if [[ -f "$genesis_dir/static-nodes.json" ]]; then
            local remote_static="/tmp/static-nodes-$$.json"
            scp -o ConnectTimeout=5 -o StrictHostKeyChecking=no "$genesis_dir/static-nodes.json" root@${PROXMOX_HOST}:${remote_static} && {
                ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} "pct push $vmid ${remote_static} /genesis/static-nodes.json && rm -f ${remote_static}" || true
            }
        fi
    fi
    
    if [[ -d "$permissions_dir" ]] && [[ -f "$permissions_dir/permissions-nodes.toml" ]]; then
        log_info "  Copying permissions files..."
        local remote_perms="/tmp/permissions-$$.toml"
        scp -o ConnectTimeout=5 -o StrictHostKeyChecking=no "$permissions_dir/permissions-nodes.toml" root@${PROXMOX_HOST}:${remote_perms} && {
            ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} "pct exec $vmid -- mkdir -p /permissions && pct push $vmid ${remote_perms} /permissions/permissions-nodes.toml && rm -f ${remote_perms}" || true
        }
    fi
    
    # Clean up temporary files on Proxmox host
    ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} "rm -f ${remote_install} ${remote_config}" || true
    
    if [ $? -eq 0 ]; then
        log_success "Besu RPC setup completed for container $vmid"
        return 0
    else
        log_error "Failed to setup Besu RPC on container $vmid"
        # Clean up on failure
        ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} "rm -f ${remote_install} ${remote_config}" || true
        return 1
    fi
}

# Create ThirdWeb-optimized Besu config
create_thirdweb_config() {
    local config_file="$1"
    log_info "Creating ThirdWeb RPC configuration: $config_file"
    
    mkdir -p "$(dirname "$config_file")"
    
    cat > "$config_file" <<'EOF'
# Besu Configuration for ThirdWeb RPC Nodes
# Optimized for ThirdWeb SDK and dApp integration

data-path="/data/besu"
genesis-file="/genesis/genesis.json"

# Network Configuration
network-id=138
p2p-host="0.0.0.0"
p2p-port=30303

# Consensus (RPC nodes don't participate)
miner-enabled=false

# Sync Configuration
sync-mode="FULL"
fast-sync-min-peers=2

# RPC Configuration (ThirdWeb-compatible APIs)
rpc-http-enabled=true
rpc-http-host="0.0.0.0"
rpc-http-port=8545
rpc-http-api=["ETH","NET","WEB3","DEBUG","TRACE"]
rpc-http-cors-origins=["*"]
rpc-http-host-allowlist=["*"]

# WebSocket RPC (recommended for ThirdWeb)
rpc-ws-enabled=true
rpc-ws-host="0.0.0.0"
rpc-ws-port=8546
rpc-ws-api=["ETH","NET","WEB3"]
rpc-ws-origins=["*"]

# Metrics
metrics-enabled=true
metrics-port=9545
metrics-host="0.0.0.0"
metrics-push-enabled=false

# Logging
logging="INFO"

# Permissioning
permissions-nodes-config-file-enabled=true
permissions-nodes-config-file="/permissions/permissions-nodes.toml"
permissions-accounts-config-file-enabled=false

# Transaction Pool (optimized for ThirdWeb transaction volume)
tx-pool-max-size=16384
tx-pool-price-bump=10
tx-pool-retention-hours=12

# Network Peering
bootnodes=[]

# Static Nodes (validators and other nodes)
static-nodes-file="/genesis/static-nodes.json"

# Discovery (enabled for redundancy)
discovery-enabled=true

# Privacy (disabled for public network)
privacy-enabled=false

# Gas Configuration (no fee cap for ThirdWeb compatibility)
rpc-tx-feecap="0x0"

# P2P Configuration (more peers for better connectivity)
max-peers=50

# GraphQL (optional, for advanced queries)
graphql-http-enabled=false

# JSON-RPC timeout (increased for ThirdWeb operations)
rpc-http-timeout=60
EOF

    log_success "ThirdWeb RPC configuration created"
}

# Main execution
main() {
    echo ""
    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    log_info "ThirdWeb RPC Node Setup Script"
    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""
    
    log_info "Target: $PROXMOX_HOST"
    log_info "Storage: $STORAGE"
    log_info "Template: $TEMPLATE"
    echo ""
    
    # Check SSH access
    if ! check_ssh_access; then
        exit 1
    fi
    
    echo ""
    log_info "This will create ${#THIRDWEB_RPC_NODES[@]} ThirdWeb RPC nodes:"
    for vmid in "${!THIRDWEB_RPC_NODES[@]}"; do
        IFS=':' read -r hostname ip description <<< "${THIRDWEB_RPC_NODES[$vmid]}"
        log_info "  • VMID $vmid: $hostname ($ip) - $description"
    done
    echo ""
    
    # Check for non-interactive mode
    if [[ "${NON_INTERACTIVE:-}" == "1" ]] || [[ ! -t 0 ]]; then
        log_info "Non-interactive mode: proceeding automatically"
    else
        read -p "Continue? (y/N): " -n 1 -r
        echo ""
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "Setup cancelled"
            exit 0
        fi
    fi
    
    local success_count=0
    local fail_count=0
    local skip_count=0
    
    echo ""
    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    log_info "Creating ThirdWeb RPC Containers"
    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""
    
    # Create containers
    for vmid in "${!THIRDWEB_RPC_NODES[@]}"; do
        IFS=':' read -r hostname ip description <<< "${THIRDWEB_RPC_NODES[$vmid]}"
        
        local exists=$(container_exists "$vmid")
        if [[ "$exists" == "exists" ]]; then
            log_warn "Container $vmid already exists, skipping creation..."
            skip_count=$((skip_count + 1))
        elif create_container "$vmid" "$hostname" "$ip" "$description"; then
            success_count=$((success_count + 1))
        else
            fail_count=$((fail_count + 1))
        fi
        echo ""
    done
    
    echo ""
    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    log_info "Configuring Besu RPC on Containers"
    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""
    
    # Setup Besu on each container
    for vmid in "${!THIRDWEB_RPC_NODES[@]}"; do
        IFS=':' read -r hostname ip description <<< "${THIRDWEB_RPC_NODES[$vmid]}"
        
        log_info "Setting up container $vmid..."
        if setup_besu_rpc "$vmid" "$hostname" "$ip"; then
            log_success "Container $vmid configured successfully"
        else
            log_error "Failed to configure container $vmid"
            fail_count=$((fail_count + 1))
        fi
        echo ""
    done
    
    # Summary
    echo ""
    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    log_info "Setup Summary"
    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""
    log_info "Created: $success_count"
    log_info "Skipped: $skip_count"
    log_info "Failed:  $fail_count"
    echo ""
    
    if [[ $fail_count -eq 0 ]]; then
        log_success "ThirdWeb RPC nodes setup completed!"
        echo ""
        log_info "Next steps:"
        log_info "1. Verify containers are running:"
        for vmid in "${!THIRDWEB_RPC_NODES[@]}"; do
            IFS=':' read -r hostname ip description <<< "${THIRDWEB_RPC_NODES[$vmid]}"
            log_info "   ssh root@$PROXMOX_HOST 'pct status $vmid'"
        done
        echo ""
        log_info "2. Start Besu services (if not auto-started):"
        for vmid in "${!THIRDWEB_RPC_NODES[@]}"; do
            IFS=':' read -r hostname ip description <<< "${THIRDWEB_RPC_NODES[$vmid]}"
            log_info "   ssh root@$PROXMOX_HOST 'pct exec $vmid -- systemctl start besu-rpc.service'"
        done
        echo ""
        log_info "3. Test RPC endpoints:"
        for vmid in "${!THIRDWEB_RPC_NODES[@]}"; do
            IFS=':' read -r hostname ip description <<< "${THIRDWEB_RPC_NODES[$vmid]}"
            log_info "   curl -X POST http://${ip}:8545 -H 'Content-Type: application/json' --data '{\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[],\"id\":1}'"
        done
        echo ""
        log_info "4. Configure ThirdWeb to use these RPC endpoints:"
        for vmid in "${!THIRDWEB_RPC_NODES[@]}"; do
            IFS=':' read -r hostname ip description <<< "${THIRDWEB_RPC_NODES[$vmid]}"
            log_info "   HTTP: http://${ip}:8545"
            log_info "   WebSocket: ws://${ip}:8546"
        done
    else
        log_warn "Some containers failed to setup. Check logs above."
    fi
}

# Run main function
main "$@"
