#!/bin/bash
# Configure Besu Nodes via Azure Run Command
# Uses Azure VM Run Command instead of SSH for private IP VMs

set -euo pipefail

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

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

echo "=========================================="
echo "Configure Besu Nodes via Azure Run Command"
echo "=========================================="
echo ""

# Get VM configuration from Terraform outputs
cd "$PHASE1_DIR"
# Use short region codes for resource groups (cus, eus, eus2, wus, wus2)
VM_CONFIG=$(terraform output -json 2>/dev/null | jq -r '.phase1_us_regions.value | to_entries[] | .key as $k | "\($k):az-p-\(if $k == "centralus" then "cus" elif $k == "eastus" then "eus" elif $k == "eastus2" then "eus2" elif $k == "westus" then "wus" elif $k == "westus2" then "wus2" else "\($k)" end)-rg-comp-001:\(.value.vm_names[0])"' || echo "")

# Build backend VMs map from Terraform outputs
declare -A BACKEND_VMS
while IFS=':' read -r region rg vm; do
    if [ -n "$region" ] && [ -n "$rg" ] && [ -n "$vm" ]; then
        BACKEND_VMS["$region"]="$rg:$vm"
    fi
done <<< "$VM_CONFIG"

# Fallback if Terraform outputs not available - use correct short codes
if [ ${#BACKEND_VMS[@]} -eq 0 ]; then
    declare -A BACKEND_VMS=(
        ["centralus"]="az-p-cus-rg-comp-001:az-p-cus-vm-besu-node-0"
        ["eastus"]="az-p-eus-rg-comp-001:az-p-eus-vm-besu-node-0"
        ["eastus2"]="az-p-eus2-rg-comp-001:az-p-eus2-vm-besu-node-0"
        ["westus"]="az-p-wus-rg-comp-001:az-p-wus-vm-besu-node-0"
        ["westus2"]="az-p-wus2-rg-comp-001:az-p-wus2-vm-besu-node-0"
    )
fi

# Verify resource groups exist
echo -e "${BLUE}Verifying resource groups...${NC}"
for region in "${!BACKEND_VMS[@]}"; do
    IFS=':' read -r resource_group vm_name <<< "${BACKEND_VMS[$region]}"
    if ! az group show --name "$resource_group" &>/dev/null; then
        echo -e "${YELLOW}Warning: Resource group $resource_group not found for $region${NC}"
    fi
done
echo ""

GENESIS_FILE="$PHASE1_DIR/config/genesis-138.json"
if [ ! -f "$GENESIS_FILE" ]; then
    echo -e "${RED}Error: Genesis file not found: $GENESIS_FILE${NC}"
    exit 1
fi

# Get genesis file content
GENESIS_CONTENT=$(cat "$GENESIS_FILE")

# Get storage URL for genesis
STORAGE_ACCOUNT=$(cd "$PHASE1_DIR" && terraform output -json 2>/dev/null | jq -r '.storage_accounts.value.backups | to_entries[0].value.backup_storage // empty' || echo "")
if [ -n "$STORAGE_ACCOUNT" ]; then
    GENESIS_URL="https://${STORAGE_ACCOUNT}.blob.core.windows.net/config/genesis-138.json"
    echo -e "${BLUE}Genesis URL: $GENESIS_URL${NC}"
else
    echo -e "${YELLOW}Warning: Could not determine storage account for genesis URL${NC}"
    GENESIS_URL=""
fi

echo ""

# Function to configure a single Besu node via Azure Run Command
configure_besu_node_azure() {
    local region=$1
    local resource_group=$2
    local vm_name=$3
    
    echo -e "${BLUE}========================================${NC}"
    echo -e "${BLUE}Configuring Besu Node: $region${NC}"
    echo -e "${BLUE}Resource Group: $resource_group${NC}"
    echo -e "${BLUE}VM: $vm_name${NC}"
    echo -e "${BLUE}========================================${NC}"
    echo ""
    
    # Create setup script content
    SETUP_SCRIPT=$(cat <<'SCRIPT_EOF'
#!/bin/bash
set -e

NODE_TYPE="besu-node"
NODE_INDEX="0"
REGION="${1:-}"

echo "Setting up Besu node: $NODE_TYPE-$NODE_INDEX in $REGION"

# Check if Docker is installed
if ! command -v docker &> /dev/null; then
    echo "Installing Docker..."
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    sudo apt-get update
    sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
    sudo systemctl enable docker
    sudo systemctl start docker
    sudo usermod -aG docker $USER
fi

# Check if Node.js is installed
if ! command -v node &> /dev/null; then
    echo "Installing Node.js 22 LTS..."
    if [ ! -d "$HOME/.nvm" ]; then
        curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
    fi
    export NVM_DIR="$HOME/.nvm"
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
    nvm install 22
    nvm use 22
    nvm alias default 22
fi

# Check if JDK 17 is installed
if ! command -v java &> /dev/null || ! java -version 2>&1 | grep -q "17"; then
    echo "Installing JDK 17..."
    sudo apt-get update
    sudo apt-get install -y openjdk-17-jdk
fi

# Create Besu directories
echo "Creating Besu directories..."
sudo mkdir -p /opt/besu/{data,config,keys,logs}
sudo chown -R $USER:$USER /opt/besu

# Download genesis file
if [ -n "${GENESIS_URL:-}" ]; then
    echo "Downloading genesis file from $GENESIS_URL..."
    curl -s "$GENESIS_URL" -o /opt/besu/config/genesis.json || echo "Failed to download genesis"
else
    echo "Warning: GENESIS_URL not set"
fi

# Create Besu configuration
cat > /opt/besu/config/besu-config.toml <<EOF
data-path="/opt/besu/data"
genesis-file="/opt/besu/config/genesis.json"
network-id=138
p2p-port=30303
rpc-http-enabled=true
rpc-http-host="0.0.0.0"
rpc-http-port=8545
rpc-http-cors-origins=["*"]
rpc-http-api=["ETH","NET","WEB3","ADMIN","DEBUG","TRACE","TXPOOL","PERSONAL","EOA","PERM","PLUGINS","QBFT","IBFT","CLIQUE","MINER"]
rpc-ws-enabled=true
rpc-ws-host="0.0.0.0"
rpc-ws-port=8546
rpc-ws-api=["ETH","NET","WEB3","ADMIN","DEBUG","TRACE","TXPOOL","PERSONAL","EOA","PERM","PLUGINS","QBFT","IBFT","CLIQUE","MINER"]
metrics-enabled=true
metrics-host="0.0.0.0"
metrics-port=9545
metrics-category-enabled=["blockchain","jvm","process","peers","rpc"]
logging="INFO"
log-destination="FILE"
log-file="/opt/besu/logs/besu.log"
EOF

# Create docker-compose.yml
cat > /opt/besu/docker-compose.yml <<EOF
version: '3.8'
services:
  besu:
    image: hyperledger/besu:23.10.0
    container_name: besu-besu-node-0
    restart: unless-stopped
    user: "$USER"
    volumes:
      - /opt/besu/data:/data
      - /opt/besu/config:/config
      - /opt/besu/keys:/keys:ro
      - /opt/besu/logs:/logs
    ports:
      - "9545:9545"
      - "30303:30303"
      - "30303:30303/udp"
      - "8545:8545"
      - "8546:8546"
    command:
      - /opt/besu/bin/besu
      - --config-file=/config/besu-config.toml
    environment:
      - BESU_OPTS=-Xmx4g -Xms4g
    networks:
      - besu-network
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    healthcheck:
      test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:9545/metrics"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 120s
networks:
  besu-network:
    driver: bridge
EOF

# Create systemd service
sudo tee /etc/systemd/system/besu.service > /dev/null <<EOF
[Unit]
Description=Besu Node Service
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/besu
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
Restart=on-failure
RestartSec=10
User=$USER
Group=$USER
[Install]
WantedBy=multi-user.target
EOF

# Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable besu.service

echo "✓ Besu setup complete"
SCRIPT_EOF
)
    
    # Execute via Azure Run Command
    echo -e "${YELLOW}Executing setup via Azure Run Command...${NC}"
    
    # First, download genesis file if URL available
    if [ -n "$GENESIS_URL" ]; then
        echo -e "${YELLOW}Downloading genesis file...${NC}"
        GENESIS_OUTPUT=$(az vm run-command invoke \
            --resource-group "$resource_group" \
            --name "$vm_name" \
            --command-id RunShellScript \
            --scripts "export GENESIS_URL='$GENESIS_URL' && curl -s '$GENESIS_URL' -o /tmp/genesis.json && sudo mkdir -p /opt/besu/config && sudo cp /tmp/genesis.json /opt/besu/config/genesis.json && sudo chown besuadmin:besuadmin /opt/besu/config/genesis.json && echo 'Genesis downloaded successfully'" \
            --output json 2>&1)
        
        if echo "$GENESIS_OUTPUT" | grep -q "Genesis downloaded successfully"; then
            echo -e "${GREEN}✓ Genesis downloaded${NC}"
        else
            echo -e "${YELLOW}⚠ Genesis download may have failed${NC}"
            echo "$GENESIS_OUTPUT" | grep -E "(stdout|stderr|message)" | head -5
        fi
    fi
    
    # Execute main setup script
    echo -e "${YELLOW}Executing Besu setup...${NC}"
    SETUP_OUTPUT=$(az vm run-command invoke \
        --resource-group "$resource_group" \
        --name "$vm_name" \
        --command-id RunShellScript \
        --scripts "$SETUP_SCRIPT" \
        --parameters "$region" \
        --output json 2>&1)
    
    if echo "$SETUP_OUTPUT" | grep -q "Besu setup complete"; then
        echo -e "${GREEN}✓ Setup completed${NC}"
    else
        echo -e "${RED}Error: Setup may have failed${NC}"
        echo "$SETUP_OUTPUT" | grep -E "(stdout|stderr|message|error)" | head -10
        return 1
    fi
    
    # Start Besu service
    echo -e "${YELLOW}Starting Besu service...${NC}"
    START_OUTPUT=$(az vm run-command invoke \
        --resource-group "$resource_group" \
        --name "$vm_name" \
        --command-id RunShellScript \
        --scripts "sudo systemctl start besu.service && sleep 5 && sudo systemctl status besu.service --no-pager | head -10" \
        --output json 2>&1)
    
    echo "$START_OUTPUT" | grep -E "(Active|running|failed)" | head -5 || echo "Service status check completed"
    
    # Verify Besu is running
    echo -e "${YELLOW}Verifying Besu is running...${NC}"
    sleep 10
    VERIFY_OUTPUT=$(az vm run-command invoke \
        --resource-group "$resource_group" \
        --name "$vm_name" \
        --command-id RunShellScript \
        --scripts "docker ps | grep besu || echo 'Besu not running'" \
        --output json 2>&1)
    
    if echo "$VERIFY_OUTPUT" | grep -q "besu"; then
        echo -e "${GREEN}✓ Besu is running${NC}"
    else
        echo -e "${YELLOW}⚠ Besu may not be running yet${NC}"
    fi
    
    echo -e "${GREEN}✓ Configuration complete for $region${NC}"
    echo ""
}

# Main execution
echo -e "${BLUE}Starting configuration of ${#BACKEND_VMS[@]} Besu nodes via Azure Run Command...${NC}"
echo ""

SUCCESS_COUNT=0
FAILED_REGIONS=()

for region in "${!BACKEND_VMS[@]}"; do
    IFS=':' read -r resource_group vm_name <<< "${BACKEND_VMS[$region]}"
    
    if configure_besu_node_azure "$region" "$resource_group" "$vm_name"; then
        ((SUCCESS_COUNT++))
    else
        FAILED_REGIONS+=("$region")
    fi
    
    echo ""
done

# Summary
echo "=========================================="
echo "Configuration Summary"
echo "=========================================="
echo -e "${GREEN}Successfully configured: $SUCCESS_COUNT/${#BACKEND_VMS[@]} nodes${NC}"

if [ ${#FAILED_REGIONS[@]} -gt 0 ]; then
    echo -e "${RED}Failed regions:${NC}"
    for region in "${FAILED_REGIONS[@]}"; do
        echo -e "${RED}  - $region${NC}"
    done
fi

echo ""
echo -e "${BLUE}Next steps:${NC}"
echo "1. Verify all nodes are running"
echo "2. Test RPC endpoints"
echo "3. Check logs"
echo ""

if [ $SUCCESS_COUNT -eq ${#BACKEND_VMS[@]} ]; then
    echo -e "${GREEN}✓ All Besu nodes configured successfully!${NC}"
    exit 0
else
    echo -e "${YELLOW}⚠ Some nodes failed to configure. Review errors above.${NC}"
    if [ $SUCCESS_COUNT -gt 0 ]; then
        exit 0  # Partial success
    else
        exit 1  # Complete failure
    fi
fi

