#!/usr/bin/env bash
# Practical fix for enode URLs: Extract first 128 chars and map to correct IPs
# Based on Besu requirements: enode IDs must be exactly 128 hex characters

set -euo pipefail

PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.10}"
WORK_DIR="/tmp/fix-enodes-$$"
mkdir -p "$WORK_DIR"

cleanup() { rm -rf "$WORK_DIR"; }
trap cleanup EXIT

# Container IP mapping
declare -A CONTAINER_IPS=(
    [106]="192.168.11.13"  # besu-validator-1
    [107]="192.168.11.14"  # besu-validator-2
    [108]="192.168.11.15"  # besu-validator-3
    [109]="192.168.11.16"  # besu-validator-4
    [110]="192.168.11.18"  # besu-validator-5
    [111]="192.168.11.19"  # besu-sentry-2
    [112]="192.168.11.20"  # besu-sentry-3
    [113]="192.168.11.21"  # besu-sentry-4
    [114]="192.168.11.22"  # besu-sentry-5
    [115]="192.168.11.23"  # besu-rpc-1
    [116]="192.168.11.24"  # besu-rpc-2
    [117]="192.168.11.25"  # besu-rpc-3
)

# 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}[WARNING]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }

# Extract and fix enodes from a container's current static-nodes.json
extract_and_fix_enodes() {
    local vmid="$1"
    local container_ip="${CONTAINER_IPS[$vmid]}"
    
    log_info "Processing container $vmid ($container_ip)..."
    
    # Get current static-nodes.json
    local current_json
    current_json=$(ssh -o StrictHostKeyChecking=accept-new "root@${PROXMOX_HOST}" \
        "pct exec $vmid -- cat /etc/besu/static-nodes.json 2>/dev/null" || echo '[]')
    
    if [[ "$current_json" == "[]" ]] || [[ -z "$current_json" ]]; then
        log_warn "Container $vmid: No static-nodes.json found"
        return 1
    fi
    
    # Extract node IDs (first 128 chars) and create corrected enodes
    python3 << PYEOF
import json
import re

try:
    static_nodes = json.loads('''$current_json''')
except:
    static_nodes = []

fixed_enodes = []
node_ids_seen = set()

for i, enode in enumerate(static_nodes):
    # Extract hex part
    match = re.search(r'enode://([a-fA-F0-9]+)@', enode)
    if not match:
        continue
    
    full_hex = match.group(1).lower()
    # Take first 128 chars (removes trailing zeros padding)
    node_id = full_hex[:128]
    
    if len(node_id) != 128:
        print(f"SKIP: Node ID {i+1} has length {len(node_id)}, not 128", file=sys.stderr)
        continue
    
    # Validate hex
    if not re.match(r'^[0-9a-f]{128}$', node_id):
        print(f"SKIP: Node ID {i+1} contains invalid hex", file=sys.stderr)
        continue
    
    # Map first 5 to validator IPs (106-110), others keep original IP for now
    if i < 5:
        vmid_map = 106 + i
        if vmid_map in ${!CONTAINER_IPS[@]}:
            ip = "${CONTAINER_IPS[$vmid_map]}"
        else:
            # Extract original IP
            ip_match = re.search(r'@([0-9.]+):', enode)
            ip = ip_match.group(1) if ip_match else "$container_ip"
    else:
        # Extract original IP
        ip_match = re.search(r'@([0-9.]+):', enode)
        ip = ip_match.group(1) if ip_match else "$container_ip"
    
    fixed_enode = f"enode://{node_id}@{ip}:30303"
    
    # Avoid duplicates
    if node_id not in node_ids_seen:
        fixed_enodes.append(fixed_enode)
        node_ids_seen.add(node_id)

# Save to file
with open('$WORK_DIR/static-nodes-${vmid}.json', 'w') as f:
    json.dump(fixed_enodes, f, indent=2)

print(f"Fixed {len(fixed_enodes)} enode URLs for container $vmid")
PYEOF

    return 0
}

# Generate corrected permissions-nodes.toml from all containers
generate_permissions_toml() {
    log_info "Generating corrected permissions-nodes.toml..."
    
    # Collect all unique enodes from all containers
    python3 << 'PYEOF'
import json
import re
import glob

all_enodes = set()

# Read all fixed static-nodes.json files
for json_file in glob.glob('$WORK_DIR/static-nodes-*.json'):
    try:
        with open(json_file, 'r') as f:
            enodes = json.load(f)
            for enode in enodes:
                all_enodes.add(enode)
    except:
        pass

# Sort for consistency
sorted_enodes = sorted(all_enodes)

# Generate TOML
toml_content = """# Node Permissioning Configuration
# Lists nodes that are allowed to connect to this node
# Generated from actual container enodes (first 128 chars of node IDs)
# All validators, sentries, and RPC nodes are included

nodes-allowlist=[
"""

for enode in sorted_enodes:
    toml_content += f'  "{enode}",\n'

# Remove trailing comma
toml_content = toml_content.rstrip(',\n') + '\n]'

with open('$WORK_DIR/permissions-nodes.toml', 'w') as f:
    f.write(toml_content)

print(f"Generated permissions-nodes.toml with {len(sorted_enodes)} unique nodes")
PYEOF

    log_success "Generated permissions-nodes.toml"
}

# Deploy corrected files
deploy_files() {
    log_info "Deploying corrected files to all containers..."
    
    # First, copy permissions-nodes.toml to host
    scp -o StrictHostKeyChecking=accept-new \
        "$WORK_DIR/permissions-nodes.toml" \
        "root@${PROXMOX_HOST}:/tmp/permissions-nodes-fixed.toml"
    
    for vmid in 106 107 108 109 110 111 112 113 114 115 116 117; do
        if ! ssh -o StrictHostKeyChecking=accept-new "root@${PROXMOX_HOST}" \
            "pct status $vmid 2>/dev/null | grep -q running"; then
            log_warn "Container $vmid: not running, skipping"
            continue
        fi
        
        log_info "Deploying to container $vmid..."
        
        # Copy static-nodes.json (container-specific)
        if [[ -f "$WORK_DIR/static-nodes-${vmid}.json" ]]; then
            scp -o StrictHostKeyChecking=accept-new \
                "$WORK_DIR/static-nodes-${vmid}.json" \
                "root@${PROXMOX_HOST}:/tmp/static-nodes-${vmid}.json"
            
            ssh -o StrictHostKeyChecking=accept-new "root@${PROXMOX_HOST}" << REMOTE_SCRIPT
pct push $vmid /tmp/static-nodes-${vmid}.json /etc/besu/static-nodes.json
pct exec $vmid -- chown besu:besu /etc/besu/static-nodes.json
rm -f /tmp/static-nodes-${vmid}.json
REMOTE_SCRIPT
        fi
        
        # Copy permissions-nodes.toml (same for all)
        ssh -o StrictHostKeyChecking=accept-new "root@${PROXMOX_HOST}" << REMOTE_SCRIPT
pct push $vmid /tmp/permissions-nodes-fixed.toml /etc/besu/permissions-nodes.toml
pct exec $vmid -- chown besu:besu /etc/besu/permissions-nodes.toml
REMOTE_SCRIPT
        
        log_success "Container $vmid: files deployed"
    done
    
    # Cleanup
    ssh -o StrictHostKeyChecking=accept-new "root@${PROXMOX_HOST}" \
        "rm -f /tmp/permissions-nodes-fixed.toml"
}

# Main
main() {
    echo "╔════════════════════════════════════════════════════════════════╗"
    echo "║         FIX ENODE CONFIGS (EXTRACT FIRST 128 CHARS)            ║"
    echo "╚════════════════════════════════════════════════════════════════╝"
    echo ""
    
    # Process all containers
    for vmid in 106 107 108 109 110 111 112 113 114 115 116 117; do
        extract_and_fix_enodes "$vmid" || true
    done
    
    generate_permissions_toml
    
    echo ""
    log_info "Preview of generated files:"
    echo ""
    echo "=== static-nodes.json (container 106) ==="
    cat "$WORK_DIR/static-nodes-106.json" 2>/dev/null | head -10 || echo "Not generated"
    echo ""
    echo "=== permissions-nodes.toml (first 20 lines) ==="
    cat "$WORK_DIR/permissions-nodes.toml" | head -20
    echo ""
    
    read -p "Deploy corrected files to all containers? [y/N]: " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        deploy_files
        log_success "All files deployed!"
        log_info "Next: Restart Besu services on all containers"
    else
        log_info "Files available in $WORK_DIR for review"
    fi
}

main "$@"
