#!/usr/bin/env bash
# Deploy contracts in parallel where dependencies allow
# Uses .env file for configuration

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../lib/init.sh"
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 variables
if [ ! -f .env ]; then
    log_error "Error: .env file not found"
    echo "Please create .env file with required variables"
    exit 1
fi

source .env

# Check required variables
if [ -z "$PRIVATE_KEY" ]; then
    log_error "Error: PRIVATE_KEY not set in .env"
    exit 1
fi

if [ -z "$RPC_URL" ]; then
    log_error "Error: RPC_URL not set in .env"
    exit 1
fi

# Verify RPC endpoint is accessible
log_warn "Verifying RPC endpoint..."
if ! curl -s -X POST "$RPC_URL" -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' > /dev/null 2>&1; then
    log_error "Error: RPC endpoint is not accessible"
    exit 1
fi

log_success "✅ RPC endpoint is accessible"

# Export variables for parallel execution
export PRIVATE_KEY
export RPC_URL
export CCIP_ROUTER="${CCIP_ROUTER:-}"
export CCIP_FEE_TOKEN="${CCIP_FEE_TOKEN:-0x0000000000000000000000000000000000000000}"
export ORACLE_DESCRIPTION="${ORACLE_DESCRIPTION:-ETH/USD Price Feed}"
export ORACLE_HEARTBEAT="${ORACLE_HEARTBEAT:-60}"
export ORACLE_DEVIATION_THRESHOLD="${ORACLE_DEVIATION_THRESHOLD:-50}"

# Function to update .env file
update_env() {
    local key=$1
    local value=$2
    if grep -q "^${key}=" .env; then
        sed -i "s|^${key}=.*|${key}=${value}|" .env
    else
        echo "${key}=${value}" >> .env
    fi
    log_success "✅ Updated .env: ${key}=${value}"
}

# Function to extract deployed address from forge output
extract_address() {
    local output=$1
    echo "$output" | grep -oE "0x[a-fA-F0-9]{40}" | tail -1 || echo ""
}

log_success "=== Starting Parallel Contract Deployment ==="

# Phase 1: Independent contracts (can be deployed in parallel)
log_warn "Phase 1: Deploying independent contracts in parallel..."

# Deploy Multicall, WETH9, and WETH10 in parallel
{
    log_warn "Deploying Multicall..."
    MULTICALL_OUTPUT=$(forge_scoped script script/DeployMulticall.s.sol:DeployMulticall \
        --rpc-url "$RPC_URL" \
        --broadcast \
        --private-key "$PRIVATE_KEY" \
        --verify 2>&1)
    MULTICALL_ADDRESS=$(extract_address "$MULTICALL_OUTPUT")
    if [ -n "$MULTICALL_ADDRESS" ]; then
        update_env "MULTICALL_ADDRESS" "$MULTICALL_ADDRESS"
        log_success "✅ Multicall deployed at: $MULTICALL_ADDRESS"
    fi
} &
MULTICALL_PID=$!

{
    log_warn "Deploying WETH9..."
    WETH9_OUTPUT=$(forge_scoped script script/DeployWETH.s.sol:DeployWETH \
        --rpc-url "$RPC_URL" \
        --broadcast \
        --private-key "$PRIVATE_KEY" \
        --verify 2>&1)
    WETH9_ADDRESS=$(extract_address "$WETH9_OUTPUT")
    if [ -n "$WETH9_ADDRESS" ]; then
        update_env "WETH9_ADDRESS" "$WETH9_ADDRESS"
        log_success "✅ WETH9 deployed at: $WETH9_ADDRESS"
    fi
} &
WETH9_PID=$!

{
    log_warn "Deploying WETH10..."
    WETH10_OUTPUT=$(forge_scoped script script/DeployWETH10.s.sol:DeployWETH10 \
        --rpc-url "$RPC_URL" \
        --broadcast \
        --private-key "$PRIVATE_KEY" \
        --verify 2>&1)
    WETH10_ADDRESS=$(extract_address "$WETH10_OUTPUT")
    if [ -n "$WETH10_ADDRESS" ]; then
        update_env "WETH10_ADDRESS" "$WETH10_ADDRESS"
        log_success "✅ WETH10 deployed at: $WETH10_ADDRESS"
    fi
} &
WETH10_PID=$!

# Wait for Phase 1 to complete
wait $MULTICALL_PID
wait $WETH9_PID
wait $WETH10_PID

# Reload .env to get deployed addresses
source .env

# Phase 2: CCIP Router (if needed)
if [ -z "$CCIP_ROUTER" ] || [ "$CCIP_ROUTER" = "0x0000000000000000000000000000000000000000" ]; then
    log_warn "Phase 2: Deploying CCIP Router..."
    CCIP_ROUTER_OUTPUT=$(forge_scoped script script/DeployCCIPRouter.s.sol:DeployCCIPRouter \
        --sig "run(address,uint256,uint256)" \
        "$CCIP_FEE_TOKEN" \
        "1000000000000000" \
        "1000000000" \
        --rpc-url "$RPC_URL" \
        --broadcast \
        --private-key "$PRIVATE_KEY" \
        --verify 2>&1)
    CCIP_ROUTER=$(extract_address "$CCIP_ROUTER_OUTPUT")
    if [ -n "$CCIP_ROUTER" ]; then
        update_env "CCIP_ROUTER" "$CCIP_ROUTER"
        log_success "✅ CCIP Router deployed at: $CCIP_ROUTER"
    fi
else
    log_success "✅ CCIP Router already configured: $CCIP_ROUTER"
fi

# Reload .env
source .env

# Phase 3: Bridge contracts (can be deployed in parallel if dependencies are met)
if [ "${DEPLOY_BRIDGES:-true}" = "true" ] && [ -n "$CCIP_ROUTER" ] && [ -n "$WETH9_ADDRESS" ] && [ -n "$WETH10_ADDRESS" ]; then
    log_warn "Phase 3: Deploying CCIP bridges in parallel..."
    
    {
        log_warn "Deploying CCIPWETH9Bridge..."
        export CCIP_ROUTER WETH9_ADDRESS CCIP_FEE_TOKEN
        BRIDGE9_OUTPUT=$(forge_scoped script script/DeployCCIPWETH9Bridge.s.sol:DeployCCIPWETH9Bridge \
            --rpc-url "$RPC_URL" \
            --broadcast \
            --private-key "$PRIVATE_KEY" \
            --verify 2>&1)
        CCIPWETH9BRIDGE_ADDRESS=$(extract_address "$BRIDGE9_OUTPUT")
        if [ -n "$CCIPWETH9BRIDGE_ADDRESS" ]; then
            update_env "CCIPWETH9BRIDGE_ADDRESS" "$CCIPWETH9BRIDGE_ADDRESS"
            log_success "✅ CCIPWETH9Bridge deployed at: $CCIPWETH9BRIDGE_ADDRESS"
        fi
    } &
    BRIDGE9_PID=$!
    
    {
        log_warn "Deploying CCIPWETH10Bridge..."
        export CCIP_ROUTER WETH10_ADDRESS CCIP_FEE_TOKEN
        BRIDGE10_OUTPUT=$(forge_scoped script script/DeployCCIPWETH10Bridge.s.sol:DeployCCIPWETH10Bridge \
            --rpc-url "$RPC_URL" \
            --broadcast \
            --private-key "$PRIVATE_KEY" \
            --verify 2>&1)
        CCIPWETH10BRIDGE_ADDRESS=$(extract_address "$BRIDGE10_OUTPUT")
        if [ -n "$CCIPWETH10BRIDGE_ADDRESS" ]; then
            update_env "CCIPWETH10BRIDGE_ADDRESS" "$CCIPWETH10BRIDGE_ADDRESS"
            log_success "✅ CCIPWETH10Bridge deployed at: $CCIPWETH10BRIDGE_ADDRESS"
        fi
    } &
    BRIDGE10_PID=$!
    
    wait $BRIDGE9_PID
    wait $BRIDGE10_PID
else
    log_warn "⚠️  Bridge deployment skipped (DEPLOY_BRIDGES=false or missing dependencies)"
fi

# Phase 4: Oracle and MultiSig (can be deployed in parallel if MultiSig owners are set)
log_warn "Phase 4: Deploying Oracle and MultiSig in parallel..."

# Deploy Oracle (independent)
{
    export ORACLE_DESCRIPTION ORACLE_HEARTBEAT ORACLE_DEVIATION_THRESHOLD
    ORACLE_OUTPUT=$(forge_scoped script script/DeployOracle.s.sol:DeployOracle \
        --rpc-url "$RPC_URL" \
        --broadcast \
        --private-key "$PRIVATE_KEY" \
        --verify 2>&1)
    
    # Extract addresses (Oracle deploys both aggregator and proxy)
    ORACLE_AGGREGATOR_ADDRESS=$(echo "$ORACLE_OUTPUT" | grep -i "Aggregator" | grep -oE "0x[a-fA-F0-9]{40}" | head -1)
    ORACLE_PROXY_ADDRESS=$(echo "$ORACLE_OUTPUT" | grep -i "Proxy" | grep -oE "0x[a-fA-F0-9]{40}" | tail -1)
    
    if [ -n "$ORACLE_AGGREGATOR_ADDRESS" ]; then
        update_env "ORACLE_AGGREGATOR_ADDRESS" "$ORACLE_AGGREGATOR_ADDRESS"
        log_success "✅ Oracle Aggregator deployed at: $ORACLE_AGGREGATOR_ADDRESS"
    fi
    if [ -n "$ORACLE_PROXY_ADDRESS" ]; then
        update_env "ORACLE_PROXY_ADDRESS" "$ORACLE_PROXY_ADDRESS"
        log_success "✅ Oracle Proxy deployed at: $ORACLE_PROXY_ADDRESS"
    fi
} &
ORACLE_PID=$!

# Deploy MultiSig (independent if owners are set)
if [ -z "$MULTISIG_OWNERS" ]; then
    log_warn "⚠️  MULTISIG_OWNERS not set. Skipping MultiSig deployment."
    log_warn "Set MULTISIG_OWNERS in .env (comma-separated addresses) to deploy."
    MULTISIG_PID=""
else
    {
        export OWNERS="$MULTISIG_OWNERS"
        MULTISIG_OUTPUT=$(forge_scoped script script/DeployMultiSig.s.sol:DeployMultiSig \
            --rpc-url "$RPC_URL" \
            --broadcast \
            --private-key "$PRIVATE_KEY" \
            --verify 2>&1)
        MULTISIG_ADDRESS=$(extract_address "$MULTISIG_OUTPUT")
        if [ -n "$MULTISIG_ADDRESS" ]; then
            update_env "MULTISIG_ADDRESS" "$MULTISIG_ADDRESS"
            log_success "✅ MultiSig deployed at: $MULTISIG_ADDRESS"
        fi
    } &
    MULTISIG_PID=$!
fi

# Wait for parallel deployments to complete
wait $ORACLE_PID
if [ -n "$MULTISIG_PID" ]; then
    wait $MULTISIG_PID
fi

# Reload .env to get all new addresses
source .env

# Final summary
log_success "=== Deployment Summary ==="
source .env
log_success "Multicall: ${MULTICALL_ADDRESS:-N/A}"
log_success "WETH9: ${WETH9_ADDRESS:-N/A}"
log_success "WETH10: ${WETH10_ADDRESS:-N/A}"
log_success "CCIP Router: ${CCIP_ROUTER:-N/A}"
log_success "CCIPWETH9Bridge: ${CCIPWETH9BRIDGE_ADDRESS:-N/A}"
log_success "CCIPWETH10Bridge: ${CCIPWETH10BRIDGE_ADDRESS:-N/A}"
log_success "Oracle Aggregator: ${ORACLE_AGGREGATOR_ADDRESS:-N/A}"
log_success "Oracle Proxy: ${ORACLE_PROXY_ADDRESS:-N/A}"
log_success "MultiSig: ${MULTISIG_ADDRESS:-N/A}"
log_success ""
log_success "=== Parallel Deployment Complete ==="
log_success "All addresses have been updated in .env file"
