#!/usr/bin/env bash
# Comprehensive testing of bridge functionality for all 7 networks
# Performs actual contract calls and validations (not simulation)
# Usage: ./test-bridge-all-7-networks.sh [token]
# Example: ./test-bridge-all-7-networks.sh weth9

set -uo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SOURCE_PROJECT="/home/intlc/projects/smom-dbis-138"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
NC='\033[0m'

log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
log_test() { echo -e "${CYAN}[TEST]${NC} $1"; }
log_detail() { echo -e "${MAGENTA}[DETAIL]${NC} $1"; }

# Load environment variables
if [ -f "$SOURCE_PROJECT/.env" ]; then
    source "$SOURCE_PROJECT/.env"
else
    log_error ".env file not found in $SOURCE_PROJECT"
    exit 1
fi

# Configuration
RPC_URL="${RPC_URL_138:-http://192.168.11.250:8545}"
WETH9_ADDRESS="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
WETH10_ADDRESS="0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f"
WETH9_BRIDGE="${CCIPWETH9_BRIDGE_CHAIN138:-0x89dd12025bfCD38A168455A44B400e913ED33BE2}"
WETH10_BRIDGE="${CCIPWETH10_BRIDGE_CHAIN138:-0xe0E93247376aa097dB308B92e6Ba36bA015535D0}"

# Parse arguments
TOKEN="${1:-weth9}"

# All 7 destination chains (including Ethereum Mainnet)
declare -A CHAIN_SELECTORS=(
    ["BSC"]="11344663589394136015"
    ["Polygon"]="4051577828743386545"
    ["Avalanche"]="6433500567565415381"
    ["Base"]="15971525489660198786"
    ["Arbitrum"]="4949039107694359620"
    ["Optimism"]="3734403246176062136"
    ["Ethereum"]="5009297550715157269"
)

# Determine token and bridge
if [ "$TOKEN" = "weth9" ]; then
    TOKEN_ADDRESS="$WETH9_ADDRESS"
    BRIDGE_ADDRESS="$WETH9_BRIDGE"
    TOKEN_NAME="WETH9"
elif [ "$TOKEN" = "weth10" ]; then
    TOKEN_ADDRESS="$WETH10_ADDRESS"
    BRIDGE_ADDRESS="$WETH10_BRIDGE"
    TOKEN_NAME="WETH10"
else
    log_error "Invalid token: $TOKEN (use weth9 or weth10)"
    exit 1
fi

if [ -z "${PRIVATE_KEY:-}" ]; then
    log_error "PRIVATE_KEY not set in .env file"
    exit 1
fi

DEPLOYER=$(cast wallet address --private-key "$PRIVATE_KEY" 2>/dev/null || echo "")
if [ -z "$DEPLOYER" ]; then
    log_error "Failed to get deployer address"
    exit 1
fi

# Test amount for calculations (0.01 ETH)
TEST_AMOUNT_WEI="10000000000000000"
TEST_AMOUNT_ETH="0.01"

# Test counters
TOTAL_TESTS=0
PASSED_TESTS=0
FAILED_TESTS=0
WARNINGS=0

# Test result tracking
declare -A TEST_RESULTS=()

test_pass() {
    ((TOTAL_TESTS++))
    ((PASSED_TESTS++))
    TEST_RESULTS["$1"]="PASS"
    log_success "$1"
}

test_fail() {
    ((TOTAL_TESTS++))
    ((FAILED_TESTS++))
    TEST_RESULTS["$1"]="FAIL"
    log_error "$1"
}

test_warn() {
    ((TOTAL_TESTS++))
    ((WARNINGS++))
    TEST_RESULTS["$1"]="WARN"
    log_warn "$1"
}

log_info "========================================="
log_info "Comprehensive Bridge Testing"
log_info "========================================="
log_info ""
log_info "Configuration:"
log_info "  Token: $TOKEN_NAME"
log_info "  Token Address: $TOKEN_ADDRESS"
log_info "  Bridge Address: $BRIDGE_ADDRESS"
log_info "  Deployer: $DEPLOYER"
log_info "  RPC URL: $RPC_URL"
log_info "  Test Amount: $TEST_AMOUNT_ETH ETH"
log_info ""

# ============================================================================
# TEST SUITE 1: RPC Connectivity
# ============================================================================
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_test "TEST SUITE 1: RPC Connectivity"
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_info ""

# Test 1.1: RPC Connection
log_test "Test 1.1: RPC Connection"
BLOCK_NUMBER=$(timeout 10 cast block-number --rpc-url "$RPC_URL" 2>/dev/null || echo "")
if [ -n "$BLOCK_NUMBER" ] && [ "$BLOCK_NUMBER" != "" ] && [ "$BLOCK_NUMBER" != "0" ]; then
    test_pass "RPC connection successful (Block: $BLOCK_NUMBER)"
    log_detail "Current block number: $BLOCK_NUMBER"
else
    test_fail "RPC connection failed"
    log_error "Cannot connect to RPC: $RPC_URL"
    exit 1
fi
log_info ""

# Test 1.2: Chain ID
log_test "Test 1.2: Chain ID Verification"
CHAIN_ID=$(timeout 10 cast chain-id --rpc-url "$RPC_URL" 2>/dev/null || echo "")
if [ "$CHAIN_ID" = "138" ]; then
    test_pass "Chain ID correct: $CHAIN_ID"
else
    test_fail "Chain ID mismatch: expected 138, got $CHAIN_ID"
fi
log_info ""

# ============================================================================
# TEST SUITE 2: Contract Code Verification
# ============================================================================
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_test "TEST SUITE 2: Contract Code Verification"
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_info ""

# Test 2.1: Bridge Contract Code
log_test "Test 2.1: Bridge Contract Code Existence"
BRIDGE_CODE=$(timeout 10 cast code "$BRIDGE_ADDRESS" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
if [ -n "$BRIDGE_CODE" ] && [ "${#BRIDGE_CODE}" -gt 10 ]; then
    CODE_SIZE=$(( ${#BRIDGE_CODE} / 2 - 1 ))
    test_pass "Bridge contract code exists (${CODE_SIZE} bytes)"
    log_detail "Contract address: $BRIDGE_ADDRESS"
else
    test_fail "Bridge contract has no code or invalid"
fi
log_info ""

# Test 2.2: Token Contract Code
log_test "Test 2.2: Token Contract Code Existence"
TOKEN_CODE=$(timeout 10 cast code "$TOKEN_ADDRESS" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
if [ -n "$TOKEN_CODE" ] && [ "${#TOKEN_CODE}" -gt 10 ]; then
    CODE_SIZE=$(( ${#TOKEN_CODE} / 2 - 1 ))
    test_pass "Token contract code exists (${CODE_SIZE} bytes)"
    log_detail "Contract address: $TOKEN_ADDRESS"
else
    test_fail "Token contract has no code or invalid"
fi
log_info ""

# ============================================================================
# TEST SUITE 3: Account & Balance Verification
# ============================================================================
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_test "TEST SUITE 3: Account & Balance Verification"
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_info ""

# Test 3.1: ETH Balance
log_test "Test 3.1: ETH Balance Check"
ETH_BALANCE=$(timeout 10 cast balance "$DEPLOYER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
if [ -z "$ETH_BALANCE" ]; then
    ETH_BALANCE="0"
fi
ETH_BALANCE_ETH=$(echo "scale=6; $ETH_BALANCE / 1000000000000000000" | bc 2>/dev/null || echo "0")
if [ -z "$ETH_BALANCE_ETH" ]; then
    ETH_BALANCE_ETH="0"
fi
if [ -n "$ETH_BALANCE" ] && [ "$ETH_BALANCE" != "0" ]; then
    test_pass "ETH balance: $ETH_BALANCE_ETH ETH"
    log_detail "Balance in wei: $ETH_BALANCE"
else
    test_warn "ETH balance is zero or cannot be read"
fi
log_info ""

# Test 3.2: Token Balance
log_test "Test 3.2: $TOKEN_NAME Balance Check"
TOKEN_BALANCE=$(timeout 10 cast call "$TOKEN_ADDRESS" "balanceOf(address)" "$DEPLOYER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
if [ -z "$TOKEN_BALANCE" ]; then
    TOKEN_BALANCE="0"
fi
TOKEN_BALANCE_ETH=$(echo "scale=6; $TOKEN_BALANCE / 1000000000000000000" | bc 2>/dev/null || echo "0")
if [ -z "$TOKEN_BALANCE_ETH" ]; then
    TOKEN_BALANCE_ETH="0"
fi
if [ -n "$TOKEN_BALANCE" ]; then
    test_pass "$TOKEN_NAME balance: $TOKEN_BALANCE_ETH ETH"
    log_detail "Balance in wei: $TOKEN_BALANCE"
else
    test_warn "$TOKEN_NAME balance cannot be read"
fi
log_info ""

# Test 3.3: Bridge Allowance
log_test "Test 3.3: Bridge Allowance Check"
ALLOWANCE=$(timeout 10 cast call "$TOKEN_ADDRESS" "allowance(address,address)" "$DEPLOYER" "$BRIDGE_ADDRESS" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
if [ -z "$ALLOWANCE" ]; then
    ALLOWANCE="0"
fi
ALLOWANCE_ETH=$(echo "scale=6; $ALLOWANCE / 1000000000000000000" | bc 2>/dev/null || echo "0")
if [ -z "$ALLOWANCE_ETH" ]; then
    ALLOWANCE_ETH="0"
fi
if [ -n "$ALLOWANCE" ]; then
    test_pass "Bridge allowance: $ALLOWANCE_ETH ETH"
    log_detail "Allowance in wei: $ALLOWANCE"
    if [ "$ALLOWANCE" = "0" ]; then
        log_warn "Allowance is zero - approval will be needed for transfers"
    fi
else
    test_warn "Bridge allowance cannot be read"
fi
log_info ""

# ============================================================================
# TEST SUITE 4: Bridge Configuration - All 7 Networks
# ============================================================================
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_test "TEST SUITE 4: Bridge Destination Configuration (7 Networks)"
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_info ""

DESTINATIONS_CONFIGURED=0
declare -A DESTINATION_ADDRESSES=()
declare -A DESTINATION_STATUS=()

for chain in "${!CHAIN_SELECTORS[@]}"; do
    selector="${CHAIN_SELECTORS[$chain]}"
    
    log_test "Test 4.$((DESTINATIONS_CONFIGURED + 1)): $chain Destination Configuration"
    log_detail "Chain Selector: $selector"
    
    # Get destination address
    DEST_ADDR=$(timeout 10 cast call "$BRIDGE_ADDRESS" "destinations(uint64)" "$selector" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
    
    if [ -n "$DEST_ADDR" ] && ! echo "$DEST_ADDR" | grep -qE "^0x0+$" && ! echo "$DEST_ADDR" | grep -qE "^0x0000000000000000000000000000000000000000$"; then
        # Format address properly (remove leading zeros padding)
        DEST_ADDR_CLEAN=$(echo "$DEST_ADDR" | sed 's/^0x0*//' | sed 's/^$/0/' | sed 's/^/0x/')
        if [ "${#DEST_ADDR_CLEAN}" -lt 42 ]; then
            DEST_ADDR_CLEAN=$(printf "0x%040s" "${DEST_ADDR_CLEAN#0x}" | tr ' ' '0')
        fi
        DESTINATION_ADDRESSES["$chain"]="$DEST_ADDR_CLEAN"
        DESTINATION_STATUS["$chain"]="CONFIGURED"
        test_pass "$chain destination configured: $DEST_ADDR_CLEAN"
        ((DESTINATIONS_CONFIGURED++))
    else
        DESTINATION_STATUS["$chain"]="NOT_CONFIGURED"
        test_fail "$chain destination not configured or invalid"
        log_detail "Returned value: $DEST_ADDR"
    fi
    log_info ""
done

log_info "Summary: $DESTINATIONS_CONFIGURED/7 destinations configured"
log_info ""

# ============================================================================
# TEST SUITE 5: Fee Calculation - All 7 Networks
# ============================================================================
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_test "TEST SUITE 5: Fee Calculation Testing (7 Networks)"
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_info ""

FEES_CALCULATED=0
declare -A FEE_VALUES=()
declare -A FEE_STATUS=()

for chain in "${!CHAIN_SELECTORS[@]}"; do
    selector="${CHAIN_SELECTORS[$chain]}"
    
    log_test "Test 5.$((FEES_CALCULATED + 1)): $chain Fee Calculation"
    log_detail "Testing with amount: $TEST_AMOUNT_ETH ETH ($TEST_AMOUNT_WEI wei)"
    
    # Calculate fee
    FEE=$(timeout 10 cast call "$BRIDGE_ADDRESS" "calculateFee(uint64,uint256)" "$selector" "$TEST_AMOUNT_WEI" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
    
    if [ -n "$FEE" ] && [ "$FEE" != "0" ] && [ "$FEE" != "" ]; then
        FEE_ETH=$(echo "scale=10; $FEE / 1000000000000000000" | bc 2>/dev/null || echo "0")
        FEE_VALUES["$chain"]="$FEE"
        FEE_STATUS["$chain"]="SUCCESS"
        test_pass "$chain fee calculation: $FEE_ETH ETH ($FEE wei)"
        log_detail "Fee calculated successfully"
        ((FEES_CALCULATED++))
    else
        FEE_STATUS["$chain"]="FAILED"
        test_warn "$chain fee calculation returned 0 or error"
        log_detail "This may require LINK tokens or CCIP router configuration"
        log_detail "Returned value: $FEE"
    fi
    log_info ""
done

log_info "Summary: $FEES_CALCULATED/7 fee calculations successful"
log_info ""

# ============================================================================
# TEST SUITE 6: Contract Function Verification
# ============================================================================
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_test "TEST SUITE 6: Contract Function Verification"
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_info ""

# Test 6.1: destinations() function
log_test "Test 6.1: destinations() Function"
BSC_SELECTOR="${CHAIN_SELECTORS[BSC]}"
DEST_TEST=$(timeout 10 cast call "$BRIDGE_ADDRESS" "destinations(uint64)" "$BSC_SELECTOR" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
if [ -n "$DEST_TEST" ]; then
    test_pass "destinations() function accessible"
    log_detail "BSC destination: $DEST_TEST"
else
    test_fail "destinations() function call failed"
fi
log_info ""

# Test 6.2: calculateFee() function
log_test "Test 6.2: calculateFee() Function"
FEE_TEST=$(timeout 10 cast call "$BRIDGE_ADDRESS" "calculateFee(uint64,uint256)" "$BSC_SELECTOR" "$TEST_AMOUNT_WEI" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
if [ -n "$FEE_TEST" ]; then
    test_pass "calculateFee() function accessible"
    log_detail "BSC fee result: $FEE_TEST wei"
else
    test_fail "calculateFee() function call failed"
fi
log_info ""

# Test 6.3: Token balanceOf() function
log_test "Test 6.3: Token balanceOf() Function"
BALANCE_TEST=$(timeout 10 cast call "$TOKEN_ADDRESS" "balanceOf(address)" "$DEPLOYER" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
if [ -n "$BALANCE_TEST" ]; then
    test_pass "Token balanceOf() function accessible"
    log_detail "Balance result: $BALANCE_TEST wei"
else
    test_fail "Token balanceOf() function call failed"
fi
log_info ""

# Test 6.4: Token allowance() function
log_test "Test 6.4: Token allowance() Function"
ALLOWANCE_TEST=$(timeout 10 cast call "$TOKEN_ADDRESS" "allowance(address,address)" "$DEPLOYER" "$BRIDGE_ADDRESS" --rpc-url "$RPC_URL" 2>/dev/null || echo "0")
if [ -n "$ALLOWANCE_TEST" ]; then
    test_pass "Token allowance() function accessible"
    log_detail "Allowance result: $ALLOWANCE_TEST wei"
else
    test_fail "Token allowance() function call failed"
fi
log_info ""

# ============================================================================
# TEST SUITE 7: Gas Estimation (Read-Only)
# ============================================================================
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_test "TEST SUITE 7: Gas Estimation Testing"
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_info ""

# Test 7.1: Estimate gas for sendCrossChain (if allowance exists)
log_test "Test 7.1: Gas Estimation for sendCrossChain()"
if [ "$ALLOWANCE" != "0" ] && [ -n "$ALLOWANCE" ]; then
    BSC_SELECTOR="${CHAIN_SELECTORS[BSC]}"
    GAS_ESTIMATE=$(timeout 15 cast estimate "$BRIDGE_ADDRESS" "sendCrossChain(uint64,address,uint256)" "$BSC_SELECTOR" "$DEPLOYER" "$TEST_AMOUNT_WEI" --rpc-url "$RPC_URL" 2>/dev/null || echo "")
    if [ -n "$GAS_ESTIMATE" ] && [ "$GAS_ESTIMATE" != "0" ]; then
        test_pass "Gas estimation successful: $GAS_ESTIMATE gas units"
        log_detail "Estimated gas for BSC transfer"
    else
        test_warn "Gas estimation failed or returned 0"
        log_detail "This may indicate insufficient allowance or other issues"
    fi
else
    test_warn "Skipping gas estimation - allowance is zero"
    log_detail "Set allowance first to test gas estimation"
fi
log_info ""

# ============================================================================
# TEST SUITE 8: Chain Selector Validation
# ============================================================================
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_test "TEST SUITE 8: Chain Selector Validation"
log_test "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_info ""

SELECTORS_VALID=0
for chain in "${!CHAIN_SELECTORS[@]}"; do
    selector="${CHAIN_SELECTORS[$chain]}"
    log_test "Test 8.$((SELECTORS_VALID + 1)): $chain Selector Validation"
    
    if [ -n "$selector" ] && [[ "$selector" =~ ^[0-9]+$ ]] && [ "${#selector}" -ge 10 ]; then
        test_pass "$chain selector valid: $selector"
        log_detail "Selector format: numeric, ${#selector} digits"
        ((SELECTORS_VALID++))
    else
        test_fail "$chain selector invalid: $selector"
    fi
    log_info ""
done

log_info "Summary: $SELECTORS_VALID/7 chain selectors valid"
log_info ""

# ============================================================================
# FINAL SUMMARY REPORT
# ============================================================================
log_info "========================================="
log_info "TEST EXECUTION SUMMARY"
log_info "========================================="
log_info ""
log_info "Total Tests: $TOTAL_TESTS"
log_success "Passed: $PASSED_TESTS"
log_error "Failed: $FAILED_TESTS"
log_warn "Warnings: $WARNINGS"
log_info ""

# Calculate success rate
if [ "$TOTAL_TESTS" -gt 0 ]; then
    SUCCESS_RATE=$(echo "scale=2; ($PASSED_TESTS * 100) / $TOTAL_TESTS" | bc 2>/dev/null || echo "0")
    log_info "Success Rate: $SUCCESS_RATE%"
fi
log_info ""

# Detailed Results
log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_info "DETAILED RESULTS"
log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_info ""

log_info "Destination Configuration:"
for chain in "${!CHAIN_SELECTORS[@]}"; do
    status="${DESTINATION_STATUS[$chain]:-UNKNOWN}"
    addr="${DESTINATION_ADDRESSES[$chain]:-N/A}"
    if [ "$status" = "CONFIGURED" ]; then
        log_success "  $chain: $addr"
    else
        log_error "  $chain: NOT CONFIGURED"
    fi
done
log_info ""

log_info "Fee Calculation Status:"
for chain in "${!CHAIN_SELECTORS[@]}"; do
    status="${FEE_STATUS[$chain]:-UNKNOWN}"
    fee="${FEE_VALUES[$chain]:-N/A}"
    if [ "$status" = "SUCCESS" ]; then
        fee_eth=$(echo "scale=10; $fee / 1000000000000000000" | bc 2>/dev/null || echo "0")
        log_success "  $chain: $fee_eth ETH"
    else
        log_warn "  $chain: Failed or requires LINK"
    fi
done
log_info ""

# Final Status
log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
if [ "$FAILED_TESTS" -eq 0 ] && [ "$DESTINATIONS_CONFIGURED" -eq 7 ]; then
    log_success "✅ ALL CRITICAL TESTS PASSED"
    log_success "Bridge is fully configured and ready for all 7 networks"
elif [ "$DESTINATIONS_CONFIGURED" -eq 7 ]; then
    log_warn "⚠ Bridge configured but some tests had warnings"
    log_info "Review warnings above for details"
else
    log_error "✗ SOME CRITICAL TESTS FAILED"
    log_error "Bridge may not be fully configured for all networks"
fi
log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log_info ""

log_info "Next Steps:"
if [ "$ALLOWANCE" = "0" ] || [ -z "$ALLOWANCE" ]; then
    log_info "  1. Approve bridge to spend tokens (if needed)"
fi
if [ "$TOKEN_BALANCE" = "0" ] || [ -z "$TOKEN_BALANCE" ]; then
    log_info "  2. Wrap ETH to $TOKEN_NAME (if needed)"
fi
log_info "  3. Review fee calculation results (may need LINK tokens)"
log_info "  4. Execute bridge transfers when ready"
log_info ""

