#!/usr/bin/env python3
"""
Fix enode URLs in static-nodes.json and permissions-nodes.toml

This script fixes the critical issues identified:
1. Invalid enode public key length (trailing zeros padding)
2. IP address mismatches between static-nodes.json and permissions-nodes.toml
3. Ensures all enode IDs are exactly 128 hex characters

Usage:
    python3 fix-enode-config.py [container_vmid]

If vmid provided, fixes files in that container.
Otherwise, generates corrected files for all containers.
"""

import json
import re
import sys
import subprocess

# Container IP mapping (VMID -> IP)
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
}

def normalize_node_id(node_id_hex):
    """
    Normalize node ID to exactly 128 hex characters.
    
    Ethereum node IDs must be exactly 128 hex chars (64 bytes).
    This function:
    - Removes trailing zeros (padding)
    - Pads with leading zeros if needed to reach 128 chars
    - Truncates to 128 chars if longer
    """
    # Remove '0x' prefix if present
    node_id_hex = node_id_hex.lower().replace('0x', '')
    
    # Remove trailing zeros (these are invalid padding)
    node_id_hex = node_id_hex.rstrip('0')
    
    # Pad with leading zeros to reach 128 chars if needed
    if len(node_id_hex) < 128:
        node_id_hex = '0' * (128 - len(node_id_hex)) + node_id_hex
    elif len(node_id_hex) > 128:
        # If longer, take first 128 (shouldn't happen, but handle it)
        node_id_hex = node_id_hex[:128]
    
    return node_id_hex

def extract_node_id_from_enode(enode_url):
    """Extract and normalize node ID from enode URL."""
    match = re.search(r'enode://([a-fA-F0-9]+)@', enode_url)
    if not match:
        return None
    
    node_id_raw = match.group(1)
    return normalize_node_id(node_id_raw)

def create_enode_url(node_id, ip, port=30303):
    """Create properly formatted enode URL."""
    if len(node_id) != 128:
        raise ValueError(f"Node ID must be exactly 128 chars, got {len(node_id)}: {node_id[:32]}...")
    return f"enode://{node_id}@{ip}:{port}"

def fix_static_nodes_json(current_file_content, validator_ips):
    """
    Fix static-nodes.json to contain only validator enodes with correct IPs.
    
    Args:
        current_file_content: Current static-nodes.json content (JSON string)
        validator_ips: List of (node_id, ip) tuples for validators
    """
    enodes = []
    for node_id, ip in validator_ips:
        enode = create_enode_url(node_id, ip)
        enodes.append(enode)
    
    return json.dumps(enodes, indent=2)

def fix_permissions_nodes_toml(current_file_content, all_node_ips):
    """
    Fix permissions-nodes.toml to contain all nodes with correct IPs.
    
    Args:
        current_file_content: Current permissions-nodes.toml content
        all_node_ips: List of (node_id, ip) tuples for all nodes
    """
    # Extract the header/comment
    lines = current_file_content.split('\n')
    header_lines = []
    for line in lines:
        if line.strip().startswith('#') or line.strip() == '':
            header_lines.append(line)
        elif 'nodes-allowlist' in line:
            break
    
    # Build the allowlist
    allowlist_lines = ['nodes-allowlist=[']
    for node_id, ip in all_node_ips:
        enode = create_enode_url(node_id, ip)
        allowlist_lines.append(f'  "{enode}",')
    # Remove trailing comma from last entry
    if allowlist_lines:
        allowlist_lines[-1] = allowlist_lines[-1].rstrip(',')
    allowlist_lines.append(']')
    
    return '\n'.join(header_lines) + '\n' + '\n'.join(allowlist_lines)

# Node IDs from source static-nodes.json (these are the 5 validators)
# Note: These may need adjustment - one appears to be 126 chars, we'll normalize
SOURCE_VALIDATOR_NODE_IDS = [
    '889ba317e10114a035ef82248a26125fbc00b1cd65fb29a2106584dddd025aa3dda14657bc423e5e8bf7d91a9858e85a',
    '2a827fcff14e548b761d18d0d7177745799d880be5ac54fb17d73aa06b105559527c97fec09005ac050e1363f16cb052',
    'aeec2f2f7ee15da9bdbf11261d1d1e5526d2d1ca03d66393e131cc70dcea856a9a01ef3488031b769025447e36e14f4e',
    '0f647faab18eb3cd1a334ddf397011af768b3311400923b670d9536f5a937aa04071801de095100142da03b233adb5db',
    '037c0feeb799e7e98bc99f7c21b8993254cc48f3251c318b211a76aa40d9c373da8c0a1df60804b327b43a222940ebf',  # 126 chars - needs padding
]

def main():
    print("=" * 70)
    print("Fixing Enode URLs in Besu Configuration Files")
    print("=" * 70)
    print()
    
    # Normalize validator node IDs
    normalized_validators = []
    for i, node_id_raw in enumerate(SOURCE_VALIDATOR_NODE_IDS):
        node_id = normalize_node_id(node_id_raw)
        vmid = 106 + i  # Validators are 106-110
        if vmid in CONTAINER_IPS:
            ip = CONTAINER_IPS[vmid]
            normalized_validators.append((node_id, ip))
            print(f"Validator {vmid} ({ip}):")
            print(f"  Original: {node_id_raw[:64]}... (len={len(node_id_raw)})")
            print(f"  Normalized: {node_id[:64]}... (len={len(node_id)})")
            print(f"  Enode: {create_enode_url(node_id, ip)}")
            print()
    
    # For now, we'll use the same 5 validators for static-nodes.json
    # and permissions-nodes.toml (this is a simplified version)
    # In production, you'd want all nodes in permissions-nodes.toml
    
    # Generate corrected static-nodes.json
    static_nodes_json = fix_static_nodes_json("", normalized_validators)
    print("Generated static-nodes.json:")
    print(static_nodes_json)
    print()
    
    # For permissions-nodes.toml, we need all nodes
    # For now, use the same validators (you may want to add more)
    permissions_toml = fix_permissions_nodes_toml(
        "# Node Permissioning Configuration\n# Lists nodes that are allowed to connect to this node\n\n",
        normalized_validators
    )
    print("Generated permissions-nodes.toml:")
    print(permissions_toml[:500] + "..." if len(permissions_toml) > 500 else permissions_toml)
    print()
    
    print("=" * 70)
    print("IMPORTANT: This is a template. You need to:")
    print("1. Verify node IDs match actual Besu node keys")
    print("2. Add all nodes (validators, sentries, RPC) to permissions-nodes.toml")
    print("3. Copy corrected files to all containers")
    print("=" * 70)

if __name__ == "__main__":
    main()
