#!/usr/bin/env bash

set -e

# Generate Genesis for ChainID 138 with proper QBFT extraData
# This script uses Besu's operator generate-blockchain-config to create a proper genesis file

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../lib/init.sh"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
CONFIG_DIR="$PROJECT_ROOT/config"
KEYS_DIR="$PROJECT_ROOT/keys"
VALIDATORS_DIR="$KEYS_DIR/validators"
OUTPUT_DIR="$PROJECT_ROOT/config/generated"


# Configuration
CHAIN_ID=138
BLOCK_PERIOD=2
EPOCH_LENGTH=30000
REQUEST_TIMEOUT=10
GAS_LIMIT="0x1c9c380"
NUM_VALIDATORS=${1:-4}

log_success "Generating genesis for ChainID ${CHAIN_ID} with proper QBFT extraData"

# Check if Besu is installed
if ! command -v besu &> /dev/null; then
    log_error "Error: Besu CLI not found. Please install Besu."
    echo "Visit: https://besu.hyperledger.org/en/stable/HowTo/Get-Started/Installation-Options/"
    exit 1
fi

# Create directories
mkdir -p "$VALIDATORS_DIR"
mkdir -p "$OUTPUT_DIR"
mkdir -p "$CONFIG_DIR"

# Create genesis configuration file for Besu operator
cat > "$CONFIG_DIR/genesis-config.json" <<EOF
{
  "genesis": {
    "config": {
      "chainId": ${CHAIN_ID},
      "berlinBlock": 0,
      "londonBlock": 0,
      "istanbulBlock": 0,
      "qbft": {
        "blockperiodseconds": ${BLOCK_PERIOD},
        "epochlength": ${EPOCH_LENGTH},
        "requesttimeoutseconds": ${REQUEST_TIMEOUT}
      }
    },
    "nonce": "0x0",
    "timestamp": "0x$(printf '%x' $(date +%s))",
    "gasLimit": "${GAS_LIMIT}",
    "difficulty": "0x1",
    "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
    "coinbase": "0x0000000000000000000000000000000000000000",
    "alloc": {
      "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb": {
        "balance": "0xde0b6b3a7640000"
      }
    }
  },
  "blockchain": {
    "nodes": {
      "generate": true,
      "count": ${NUM_VALIDATORS}
    }
  }
}
EOF

log_warn "Generating validator keys and genesis using Besu operator..."

# Generate blockchain configuration using Besu operator
besu operator generate-blockchain-config \
  --config-file="$CONFIG_DIR/genesis-config.json" \
  --to="$OUTPUT_DIR" \
  --private-key-file-name=key.priv

if [ $? -ne 0 ]; then
    log_error "Error: Failed to generate blockchain configuration"
    echo "Please ensure Besu is properly installed and the configuration file is valid"
    exit 1
fi

# Copy generated files
log_warn "Copying generated files..."

# Copy genesis file
if [ -f "$OUTPUT_DIR/genesis.json" ]; then
    cp "$OUTPUT_DIR/genesis.json" "$CONFIG_DIR/genesis.json"
    log_success "✓ Genesis file generated: $CONFIG_DIR/genesis.json"
else
    log_error "Error: Genesis file not found in output directory"
    exit 1
fi

# Copy validator keys
if [ -d "$OUTPUT_DIR/keys" ]; then
    cp -r "$OUTPUT_DIR/keys"/* "$VALIDATORS_DIR/"
    log_success "✓ Validator keys copied to: $VALIDATORS_DIR"
fi

# Extract validator addresses from genesis
log_warn "Extracting validator information..."

# Get validator addresses from genesis file
VALIDATOR_ADDRESSES=$(jq -r '.extraData' "$CONFIG_DIR/genesis.json" | xxd -r -p | tail -c +33 | head -c $((NUM_VALIDATORS * 20)) | xxd -p -c 20 | sed 's/../0x&/g')

log_success "Validator addresses:"
echo "$VALIDATOR_ADDRESSES"

# Verify genesis file
log_warn "Verifying genesis file..."

# Check chain ID
GENESIS_CHAIN_ID=$(jq -r '.config.chainId' "$CONFIG_DIR/genesis.json")
if [ "$GENESIS_CHAIN_ID" != "$CHAIN_ID" ]; then
    log_error "Error: Chain ID mismatch. Expected ${CHAIN_ID}, got ${GENESIS_CHAIN_ID}"
    exit 1
fi

# Check extraData is not empty
EXTRA_DATA=$(jq -r '.extraData' "$CONFIG_DIR/genesis.json")
if [ "$EXTRA_DATA" = "0x" ] || [ -z "$EXTRA_DATA" ]; then
    log_error "Error: extraData is empty. QBFT configuration may be invalid"
    exit 1
fi

log_success "✓ Genesis file verified"
log_success "✓ Chain ID: ${GENESIS_CHAIN_ID}"
log_success "✓ ExtraData: ${EXTRA_DATA:0:50}..."

# Create static-nodes.json template
log_warn "Creating static-nodes.json template..."

# Note: static-nodes.json will need to be populated with actual enode addresses
# after nodes are deployed and enode addresses are known
cat > "$CONFIG_DIR/static-nodes.json.template" <<EOF
[
  // Add enode addresses here after deployment
  // Format: "enode://<public-key>@<ip>:30303"
]
EOF

log_success "Setup complete!"
log_warn "Next steps:"
echo "1. Review genesis.json: $CONFIG_DIR/genesis.json"
echo "2. Store validator keys securely (Azure Key Vault for production)"
echo "3. Deploy infrastructure using Terraform"
echo "4. Update static-nodes.json with actual enode addresses after deployment"
echo "5. Deploy Kubernetes resources"
