#!/usr/bin/env bash

# Calculate CREATE2 deployment parameters given target address and bytecode
# This script uses Python to reverse-calculate or find the salt/deployer combination

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
cd "$PROJECT_ROOT"
# Load .env via dotenv (RPC CR/LF trim). Fallback: raw source.
if [[ -f "$SCRIPT_DIR/../lib/deployment/dotenv.sh" ]]; then
  # shellcheck disable=SC1090
  source "$SCRIPT_DIR/../lib/deployment/dotenv.sh"
  load_deployment_env --repo-root "${PROJECT_ROOT:-$REPO_ROOT}"
elif [[ -n "${PROJECT_ROOT:-}" && -f "$PROJECT_ROOT/.env" ]]; then
  set -a
  # shellcheck disable=SC1090
  source "$PROJECT_ROOT/.env"
  set +a
elif [[ -n "${REPO_ROOT:-}" && -f "$REPO_ROOT/.env" ]]; then
  set -a
  # shellcheck disable=SC1090
  source "$REPO_ROOT/.env"
  set +a
fi

# Load environment

TARGET_WETH9="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
TARGET_WETH10="0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F"

# Standard CREATE2 deployer
CREATE2_DEPLOYER="0x4e59b44847b379578588920cA78FbF26c0B4956C"

echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🔍 Calculate CREATE2 Parameters"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""

# Check if contracts are compiled
if [ ! -d "out/WETH.sol" ] || [ ! -d "out/WETH10.sol" ]; then
    echo "📦 Compiling contracts..."
    forge build --force > /dev/null 2>&1
fi

echo "📋 Target Addresses:"
echo "   WETH9:  $TARGET_WETH9"
echo "   WETH10: $TARGET_WETH10"
echo ""

echo "🔍 Calculating CREATE2 parameters..."
echo ""
echo "Since CREATE2 is a one-way function, we need to:"
echo "  1. Try common deployers (standard CREATE2 deployer, genesis addresses)"
echo "  2. Try common salts (0, 1, chain ID, contract name, etc.)"
echo "  3. Calculate forward and see if we get the target address"
echo ""

python3 << 'EOF'
import json
import hashlib
from eth_utils import to_checksum_address, keccak, encode_hex

# Target addresses
TARGET_WETH9 = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
TARGET_WETH10 = "0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F"

# Known deployers to try
DEPLOYERS = [
    "0x4e59b44847b379578588920cA78FbF26c0B4956C",  # Standard CREATE2 deployer
    "0x0742D35CC6634c0532925A3b844bc9E7595f0Beb",  # Genesis address
    "0xa55A4B57A91561e9df5a883D4883Bd4b1a7C4882",  # Genesis address
]

def calculate_create2_address(deployer, salt, bytecode_hash):
    """Calculate CREATE2 address: keccak256(0xff ++ deployer ++ salt ++ bytecode_hash)[12:]"""
    deployer_bytes = bytes.fromhex(deployer[2:])
    if isinstance(salt, int):
        salt_bytes = salt.to_bytes(32, 'big')
    else:
        salt_bytes = bytes.fromhex(salt[2:]) if salt.startswith('0x') else salt.encode()
    
    if isinstance(bytecode_hash, str):
        bytecode_hash_bytes = bytes.fromhex(bytecode_hash[2:] if bytecode_hash.startswith('0x') else bytecode_hash)
    else:
        bytecode_hash_bytes = bytecode_hash
    
    data = b'\xff' + deployer_bytes + salt_bytes + bytecode_hash_bytes
    hash_result = keccak(data)
    address = '0x' + hash_result.hex()[-40:]
    return to_checksum_address(address)

def load_bytecode_hash(contract_name):
    """Load bytecode hash from compiled artifacts"""
    import os
    artifacts_path = f"out/{contract_name}.sol/{contract_name}.json"
    if not os.path.exists(artifacts_path):
        # Try alternative path
        artifacts_path = f"out/{contract_name}/{contract_name}.sol/{contract_name}.json"
    
    if os.path.exists(artifacts_path):
        with open(artifacts_path, 'r') as f:
            artifact = json.load(f)
            bytecode = artifact.get('bytecode', {}).get('object', '')
            if bytecode:
                # Calculate hash of bytecode
                bytecode_bytes = bytes.fromhex(bytecode[2:])
                return keccak(bytecode_bytes)
    
    return None

def find_salt_for_target(target_address, contract_name, deployers):
    """Try to find salt that produces target address"""
    print(f"\n🔍 Finding salt for {contract_name} at {target_address}...")
    
    bytecode_hash = load_bytecode_hash(contract_name)
    if not bytecode_hash:
        print(f"   ⚠️  Could not load bytecode for {contract_name}")
        return None, None
    
    print(f"   📦 Bytecode hash: {encode_hex(bytecode_hash)}")
    
    # Common salts to try
    common_salts = [
        (0, "Zero"),
        (1, "One"),
        (138, "Chain ID"),
        ("WETH9" if "WETH" in contract_name else "WETH10", "Contract name"),
        ("WETH", "WETH"),
        ("Wrapped Ether", "Full name"),
    ]
    
    # Add keccak hashes of strings
    import hashlib
    for i in range(10):
        salt_str = f"{contract_name}{i}"
        salt_bytes = hashlib.sha3_256(salt_str.encode()).digest()
        salt_int = int.from_bytes(salt_bytes, 'big')
        common_salts.append((salt_int, f"Keccak256('{salt_str}')"))
    
    for deployer in deployers:
        print(f"\n   🎯 Trying deployer: {deployer}")
        
        # Try common salts
        for salt_value, salt_desc in common_salts:
            try:
                if isinstance(salt_value, int):
                    salt_bytes = salt_value.to_bytes(32, 'big')
                else:
                    salt_bytes = hashlib.sha3_256(salt_value.encode()).digest()
                
                computed = calculate_create2_address(deployer, salt_bytes, bytecode_hash)
                
                if computed.lower() == target_address.lower():
                    print(f"   ✅ FOUND! Salt: {salt_desc} = {salt_value}")
                    print(f"      Deployer: {deployer}")
                    print(f"      Computed: {computed}")
                    return deployer, salt_bytes.hex()
            except Exception as e:
                continue
        
        # Try sequential salts (first 1000)
        print(f"   🔍 Brute-forcing first 1000 sequential salts...")
        for i in range(1000):
            salt_bytes = i.to_bytes(32, 'big')
            try:
                computed = calculate_create2_address(deployer, salt_bytes, bytecode_hash)
                if computed.lower() == target_address.lower():
                    print(f"   ✅ FOUND! Salt: {i}")
                    print(f"      Deployer: {deployer}")
                    print(f"      Computed: {computed}")
                    return deployer, salt_bytes.hex()
            except:
                continue
            
            if i % 100 == 0 and i > 0:
                print(f"      Checked {i} salts...", end='\r')
        
        print(f"      Checked 1000 salts - not found")
    
    return None, None

# Find parameters for WETH9
deployer9, salt9 = find_salt_for_target(TARGET_WETH9, "WETH", DEPLOYERS)

if deployer9 and salt9:
    print(f"\n✅ WETH9 Parameters Found:")
    print(f"   Deployer: {deployer9}")
    print(f"   Salt: 0x{salt9}")
    print(f"   Use these in your deployment script!")
else:
    print(f"\n❌ Could not find WETH9 parameters")
    print(f"   You may need to:")
    print(f"   1. Check if a different deployer was used")
    print(f"   2. Try more salt values")
    print(f"   3. Verify the bytecode matches what was used in genesis.json")

# Find parameters for WETH10
print("\n" + "="*60)
deployer10, salt10 = find_salt_for_target(TARGET_WETH10, "WETH10", DEPLOYERS)

if deployer10 and salt10:
    print(f"\n✅ WETH10 Parameters Found:")
    print(f"   Deployer: {deployer10}")
    print(f"   Salt: 0x{salt10}")
    print(f"   Use these in your deployment script!")
else:
    print(f"\n❌ Could not find WETH10 parameters")
    print(f"   You may need to:")
    print(f"   1. Check if a different deployer was used")
    print(f"   2. Try more salt values")
    print(f"   3. Verify the bytecode matches what was used in genesis.json")

EOF

echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "✅ Calculation Complete"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "💡 Note: If parameters were found, use them with vm.startPrank"
echo "   or vm.startBroadcast to impersonate the deployer address."
echo ""

