#!/usr/bin/env bash
# Optimize Besu Validator and Sentry nodes to fix warnings and improve performance
# Addresses: CORS errors, thread blocking, performance issues

set -euo pipefail

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

# Proxmox host configuration
PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.10}"

# Node definitions
VALIDATORS=(1000 1001 1002 1003 1004)
SENTRIES=(1500 1501 1502 1503)

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"; }

# Function to create optimized validator config
create_optimized_validator_config() {
    local vmid=$1
    local ip=$2
    
    cat <<EOF
# Besu Configuration for Validator Nodes (Optimized)
data-path="/data/besu"
genesis-file="/etc/besu/genesis.json"

network-id=138
p2p-host="${ip}"
p2p-port=30303

# QBFT Consensus
miner-enabled=false
miner-coinbase="0x0000000000000000000000000000000000000000"

sync-mode="FULL"

# RPC Configuration (with proper CORS for validators)
rpc-http-enabled=true
rpc-http-host="0.0.0.0"
rpc-http-port=8545
rpc-http-api=["ETH","NET","ADMIN","QBFT"]
# CORS: Only allow specific origins or disable if not needed externally
rpc-http-cors-origins=["http://localhost","http://127.0.0.1","http://192.168.11.0/24"]
rpc-ws-enabled=false

# 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="/etc/besu/permissions-nodes.toml"
permissions-accounts-config-file-enabled=false

# Transaction Pool (using default settings - legacy options not compatible with this Besu version)

# Static Nodes
static-nodes-file="/etc/besu/static-nodes.json"

# Discovery
discovery-enabled=true

# Privacy
privacy-enabled=false

# Network (optimized)
max-peers=25

# Performance optimizations
# Reduce thread blocking by optimizing database operations
pruning-enabled=false
pruning-blocks-retained=1024
EOF
}

# Function to create optimized sentry config
create_optimized_sentry_config() {
    local vmid=$1
    local ip=$2
    
    cat <<EOF
# Besu Configuration for Sentry Nodes (Optimized)
data-path="/data/besu"
genesis-file="/etc/besu/genesis.json"

network-id=138
p2p-host="${ip}"
p2p-port=30303

miner-enabled=false

sync-mode="FULL"

# RPC Configuration (with proper CORS)
rpc-http-enabled=true
rpc-http-host="0.0.0.0"
rpc-http-port=8545
rpc-http-api=["ETH","NET","WEB3","ADMIN"]
# CORS: Restrict to known origins instead of wildcard
rpc-http-cors-origins=["http://localhost","http://127.0.0.1","http://192.168.11.0/24"]

rpc-ws-enabled=true
rpc-ws-host="0.0.0.0"
rpc-ws-port=8546
rpc-ws-api=["ETH","NET","WEB3"]
rpc-ws-origins=["http://localhost","http://127.0.0.1","http://192.168.11.0/24"]

# 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="/etc/besu/permissions-nodes.toml"

# Transaction Pool (using default settings - legacy options not compatible with this Besu version)

# Static Nodes
static-nodes-file="/etc/besu/static-nodes.json"

# Discovery
discovery-enabled=true

# Privacy
privacy-enabled=false

# Network (optimized)
max-peers=25

# Performance optimizations
pruning-enabled=false
pruning-blocks-retained=1024
EOF
}

# Function to create optimized systemd service
create_optimized_service() {
    local service_name=$1
    local config_file=$2
    
    cat <<EOF
[Unit]
Description=Hyperledger Besu Node (Optimized)
After=network.target
Wants=network-online.target

[Service]
Type=simple
User=besu
Group=besu
WorkingDirectory=/opt/besu

# Optimized JVM settings to reduce thread blocking
# Increased heap and optimized GC for better performance
# Note: BESU_OPTS is used by Besu, JAVA_OPTS is for general JVM options
Environment="BESU_OPTS=-Xmx6g -Xms6g"
# Vert.x thread pool optimization (passed via system properties)
Environment="JAVA_OPTS=-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:G1HeapRegionSize=16m -XX:+ParallelRefProcEnabled -XX:InitiatingHeapOccupancyPercent=45 -XX:ConcGCThreads=4 -XX:ParallelGCThreads=4 -XX:+UseStringDeduplication -Dvertx.eventLoopPoolSize=4 -Dvertx.workerPoolSize=20 -Dvertx.blockedThreadCheckInterval=5000"

# ExecStart
ExecStart=/opt/besu/bin/besu \\
    --config-file=${config_file}

# Restart
Restart=always
RestartSec=10

# Resource limits (increased for better performance)
LimitNOFILE=131072
LimitNPROC=65536

# CPU and memory limits (adjust based on available resources)
CPUQuota=400%
MemoryMax=8G
MemoryHigh=7G

# Security
NoNewPrivileges=true
PrivateTmp=true

# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=besu-${service_name}

# OOM killer adjustment
OOMScoreAdjust=-500

[Install]
WantedBy=multi-user.target
EOF
}

# Function to apply configuration to a node
apply_config() {
    local vmid=$1
    local node_type=$2
    local ip=$3
    
    log_info "Optimizing ${node_type} node VMID $vmid (IP: $ip)..."
    
    # Check if container is running
    local status=$(ssh -o StrictHostKeyChecking=accept-new -i ~/.ssh/id_ed25519_proxmox "root@${PROXMOX_HOST}" \
        "pct status $vmid 2>/dev/null" | awk '{print $2}' || echo "unknown")
    
    if [ "$status" != "running" ]; then
        log_warn "Container $vmid is not running (status: $status), skipping..."
        return 1
    fi
    
    # Create optimized config
    if [ "$node_type" == "validator" ]; then
        local config_content=$(create_optimized_validator_config "$vmid" "$ip")
        local config_file="/etc/besu/config-validator.toml"
        local service_name="besu-validator"
    else
        local config_content=$(create_optimized_sentry_config "$vmid" "$ip")
        local config_file="/etc/besu/config-sentry.toml"
        local service_name="besu-sentry"
    fi
    
    # Backup existing config
    log_info "Backing up existing configuration..."
    ssh -o StrictHostKeyChecking=accept-new -i ~/.ssh/id_ed25519_proxmox "root@${PROXMOX_HOST}" \
        "pct exec $vmid -- cp $config_file ${config_file}.backup.$(date +%Y%m%d_%H%M%S) 2>/dev/null || true"
    
    # Write new config using base64 encoding to avoid issues with special characters
    log_info "Writing optimized configuration..."
    echo "$config_content" | base64 | ssh -o StrictHostKeyChecking=accept-new -i ~/.ssh/id_ed25519_proxmox "root@${PROXMOX_HOST}" \
        "pct exec $vmid -- bash -c 'base64 -d > $config_file'"
    
    # Create optimized systemd service
    log_info "Updating systemd service..."
    local service_content=$(create_optimized_service "$service_name" "$config_file")
    
    # Write service file using base64 encoding
    echo "$service_content" | base64 | ssh -o StrictHostKeyChecking=accept-new -i ~/.ssh/id_ed25519_proxmox "root@${PROXMOX_HOST}" \
        "pct exec $vmid -- bash -c 'base64 -d > /etc/systemd/system/${service_name}.service'"
    
    # Verify service file was written
    local file_exists=$(ssh -o StrictHostKeyChecking=accept-new -i ~/.ssh/id_ed25519_proxmox "root@${PROXMOX_HOST}" \
        "pct exec $vmid -- test -f /etc/systemd/system/${service_name}.service && echo 'yes' || echo 'no'")
    
    if [ "$file_exists" != "yes" ]; then
        log_error "Failed to write service file for VMID $vmid"
        return 1
    fi
    
    # Reload systemd and restart service
    log_info "Reloading systemd and restarting service..."
    ssh -o StrictHostKeyChecking=accept-new -i ~/.ssh/id_ed25519_proxmox "root@${PROXMOX_HOST}" \
        "pct exec $vmid -- bash -c 'systemctl daemon-reload && systemctl stop ${service_name}.service 2>/dev/null; sleep 3; systemctl start ${service_name}.service'"
    
    # Wait a bit and check status
    sleep 5
    local service_status=$(ssh -o StrictHostKeyChecking=accept-new -i ~/.ssh/id_ed25519_proxmox "root@${PROXMOX_HOST}" \
        "pct exec $vmid -- systemctl is-active ${service_name}.service 2>/dev/null" || echo "unknown")
    
    if [ "$service_status" == "active" ]; then
        log_success "VMID $vmid: Service restarted successfully"
    else
        log_warn "VMID $vmid: Service status is $service_status (may still be starting)"
    fi
    
    return 0
}

# Main execution
echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║  OPTIMIZING BESU VALIDATOR AND SENTRY NODES                 ║${NC}"
echo -e "${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"
echo ""

# Node IP mappings
declare -A NODE_IPS=(
    [1000]="192.168.11.100"
    [1001]="192.168.11.101"
    [1002]="192.168.11.102"
    [1003]="192.168.11.103"
    [1004]="192.168.11.104"
    [1500]="192.168.11.150"
    [1501]="192.168.11.151"
    [1502]="192.168.11.152"
    [1503]="192.168.11.153"
)

# Optimize validators
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${BLUE}Optimizing Validator Nodes${NC}"
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
echo ""

for vmid in "${VALIDATORS[@]}"; do
    apply_config "$vmid" "validator" "${NODE_IPS[$vmid]}"
    echo ""
done

# Optimize sentries
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${BLUE}Optimizing Sentry Nodes${NC}"
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
echo ""

for vmid in "${SENTRIES[@]}"; do
    apply_config "$vmid" "sentry" "${NODE_IPS[$vmid]}"
    echo ""
done

echo -e "${GREEN}✅ Optimization complete!${NC}"
echo ""
echo "Summary of optimizations applied:"
echo "  ✓ CORS configuration fixed (restricted origins instead of wildcard)"
echo "  ✓ JVM settings optimized (increased heap, better GC tuning)"
echo "  ✓ Vert.x thread pool optimized (reduced blocking)"
echo "  ✓ Resource limits increased"
echo "  ✓ Performance tuning parameters added"
echo ""
echo "Note: Services have been restarted. Monitor logs for improvements."
