#!/usr/bin/env bash
# Complete CCIP bridge configuration for Config-Ready chains (Gnosis, Celo, Wemix).
# - Adds each chain as destination on Chain 138 bridges (138 → Gnosis/Celo/Wemix).
# - Adds Chain 138 as destination on each chain's bridges (Gnosis/Celo/Wemix → 138).
# Requires: bridge addresses and RPCs in .env; PRIVATE_KEY; CHAIN138_SELECTOR for step 2.
# Usage: ./scripts/deployment/complete-config-ready-chains.sh
#        DRY_RUN=1 ./scripts/deployment/complete-config-ready-chains.sh  # print commands only

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
[[ -f "$SCRIPT_DIR/../lib/init.sh" ]] && source "$SCRIPT_DIR/../lib/init.sh" 2>/dev/null || true
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
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"
elif [[ -f "$PROJECT_ROOT/.env" ]]; then
  set -a
  # shellcheck disable=SC1090
  source "$PROJECT_ROOT/.env"
  set +a
fi

# Chain selectors (decimal, for addDestination(uint64,address))
ETH_MAINNET_SELECTOR="${ETH_MAINNET_SELECTOR:-5009297550715157269}"
GNOSIS_SELECTOR="${GNOSIS_SELECTOR:-465200170687744372}"
CRONOS_SELECTOR="${CRONOS_SELECTOR:-1456215246176062136}"
CELO_SELECTOR="${CELO_SELECTOR:-1346049177634351622}"
WEMIX_SELECTOR="${WEMIX_SELECTOR:-5142893604156789321}"
CHAIN138_SELECTOR="${CHAIN138_SELECTOR:-}"

# Prefer LAN/core RPC for 138 when set (matches fund / deploy scripts).
CHAIN138_RPC="${RPC_URL_138:-${CHAIN138_RPC:-${RPC_URL:-https://rpc-core.d-bis.org}}}"
CHAIN138_RPC="${CHAIN138_RPC//$'\r'/}"
CHAIN138_RPC="${CHAIN138_RPC//$'\n'/}"
# Align with fund-ccip-bridges-with-link.sh / .env.example (MAINNET_RPC aliases).
GNOSIS_RPC="${GNOSIS_RPC:-${GNOSIS_MAINNET_RPC:-https://rpc.gnosischain.com}}"
CRONOS_RPC="${CRONOS_RPC:-${CRONOS_RPC_URL:-https://evm.cronos.org}}"
CELO_RPC="${CELO_RPC:-${CELO_MAINNET_RPC:-https://forno.celo.org}}"
WEMIX_RPC="${WEMIX_RPC:-${WEMIX_MAINNET_RPC:-https://api.wemix.com}}"

# Chain 138 bridge addresses (required)
WETH9_138="${CCIPWETH9_BRIDGE_CHAIN138:-}"
WETH10_138="${CCIPWETH10_BRIDGE_CHAIN138:-}"

# Config-ready chain bridge addresses (optional; if set, we configure them)
WETH9_GNOSIS="${CCIPWETH9_BRIDGE_GNOSIS:-}"
WETH10_GNOSIS="${CCIPWETH10_BRIDGE_GNOSIS:-}"
WETH9_CRONOS="${CCIPWETH9_BRIDGE_CRONOS:-}"
WETH10_CRONOS="${CCIPWETH10_BRIDGE_CRONOS:-}"
WETH9_CELO="${CCIPWETH9_BRIDGE_CELO:-}"
WETH10_CELO="${CCIPWETH10_BRIDGE_CELO:-}"
WETH9_WEMIX="${CCIPWETH9_BRIDGE_WEMIX:-}"
WETH10_WEMIX="${CCIPWETH10_BRIDGE_WEMIX:-}"

# Besu eth_call via `cast call` can return -32602; lowercase 20-byte addresses avoids some failures on sends.
WETH9_138="${WETH9_138,,}"
WETH10_138="${WETH10_138,,}"

DRY_RUN="${DRY_RUN:-0}"

log_info "=== Config-Ready Chains Completion (Gnosis, Cronos, Celo, Wemix) ==="

if [[ -z "$WETH9_138" || -z "$WETH10_138" ]]; then
  echo "Error: Chain 138 bridge addresses not set. Set in .env: CCIPWETH9_BRIDGE_CHAIN138, CCIPWETH10_BRIDGE_CHAIN138" >&2
  exit 1
fi

if ! require_private_key_env; then
  exit 1
fi

# Custom CCIPRouter on Chain 138 (smom-dbis-138/contracts/ccip/CCIPRouter.sol) maintains an allowlist.
# If a selector is missing, bridge.calculateFee / ccipSend revert with CCIPRouter: chain not supported.
CCIP_ROUTER="${CCIP_ROUTER:-}"

# cast send often exits 0 even when the receipt shows status 0 (revert). Parse human receipt output.
report_cast_send_result() {
  local _out="$1"
  if echo "$_out" | grep -qE 'status[[:space:]]+0[[:space:]]+\(failed\)'; then
    log_warn "  On-chain revert (mined, status=0)"
    echo "    $_out" >&2
  elif echo "$_out" | grep -qE 'status[[:space:]]+1[[:space:]]+\(success\)'; then
    log_success "  OK (mined)"
    [[ -n "$_out" ]] && echo "    $_out"
  elif echo "$_out" | grep -qiE 'Error:|revert|Failed|timeout|null response|invalid nonce'; then
    log_warn "  RPC / client failure (non-fatal)"
    echo "    $_out" >&2
  elif echo "$_out" | grep -q 'transactionHash'; then
    log_success "  OK (submitted; verify receipt if status line missing)"
    [[ -n "$_out" ]] && echo "    $_out"
  else
    log_warn "  Ambiguous cast output (non-fatal)"
    echo "    $_out" >&2
  fi
}

run_or_echo() {
  if [[ "$DRY_RUN" = "1" ]]; then
    echo "  [DRY RUN] $*"
  else
    local _out
    if _out=$(eval "$*" 2>&1); then
      report_cast_send_result "$_out"
    else
      log_warn "  Failed (non-fatal)"
      echo "    $_out" >&2
    fi
  fi
}

ensure_router_supports_selector() {
  local label="$1"
  local selector="$2"
  [[ -z "$CCIP_ROUTER" || -z "$selector" ]] && return 0
  local rout="${CCIP_ROUTER,,}"
  local supported
  supported=$(cast call "$rout" "supportedChains(uint64)(bool)" "$selector" --rpc-url "$CHAIN138_RPC" 2>/dev/null || echo "false")
  if [[ "$supported" != "true" ]]; then
    echo "  CCIP router: enabling chain selector for $label ($selector)..."
    run_or_echo "cast send $rout \"addSupportedChain(uint64)\" $selector --rpc-url $CHAIN138_RPC --private-key \$PRIVATE_KEY --legacy --gas-limit 250000 --gas-price 2000000000"
  else
    echo "  CCIP router: $label selector already supported ($selector)"
  fi
}

configure_chain_138_destination() {
  local label="$1"
  local selector="$2"
  local addr9="$3"
  local addr10="$4"

  if [[ -z "$addr9" && -z "$addr10" ]]; then
    echo "  Skip $label (no bridge addresses in .env)"
    return 0
  fi

  echo "  Configuring Chain 138 → $label..."
  if [[ -n "$addr9" ]]; then
    run_or_echo "cast send $WETH9_138 \"addDestination(uint64,address)\" $selector ${addr9,,} --rpc-url $CHAIN138_RPC --private-key \$PRIVATE_KEY --legacy --gas-limit 250000 --gas-price 2000000000"
  fi
  if [[ -n "$addr10" ]]; then
    run_or_echo "cast send $WETH10_138 \"addDestination(uint64,address)\" $selector ${addr10,,} --rpc-url $CHAIN138_RPC --private-key \$PRIVATE_KEY --legacy --gas-limit 250000 --gas-price 2000000000"
  fi
}

configure_remote_chain_destination() {
  local label="$1"
  local rpc="$2"
  local addr9="$3"
  local addr10="$4"

  if [[ -z "$addr9" && -z "$addr10" ]]; then
    echo "  Skip $label (no bridge addresses)"
    return 0
  fi

  echo "  Configuring $label → Chain 138..."
  if [[ -n "$addr9" ]]; then
    run_or_echo "cast send ${addr9,,} \"addDestination(uint64,address)\" $CHAIN138_SELECTOR $WETH9_138 --rpc-url $rpc --private-key \$PRIVATE_KEY --legacy --gas-limit 400000"
  fi
  if [[ -n "$addr10" ]]; then
    run_or_echo "cast send ${addr10,,} \"addDestination(uint64,address)\" $CHAIN138_SELECTOR $WETH10_138 --rpc-url $rpc --private-key \$PRIVATE_KEY --legacy --gas-limit 400000"
  fi
}

# ---- Step 0: CCIPRouter allowlist (must precede bridge fee quotes / sends) ----
echo ""
echo "Step 0: CCIP router on Chain 138 → allowlist selectors (Gnosis, Cronos, Celo, Wemix)"
if [[ -n "$CCIP_ROUTER" ]]; then
  ensure_router_supports_selector "Gnosis" "$GNOSIS_SELECTOR"
  ensure_router_supports_selector "Cronos" "$CRONOS_SELECTOR"
  ensure_router_supports_selector "Celo" "$CELO_SELECTOR"
  ensure_router_supports_selector "Wemix" "$WEMIX_SELECTOR"
else
  echo "  Skip (CCIP_ROUTER not set in .env)"
fi

# ---- Step A: On Chain 138, add Gnosis/Cronos/Celo/Wemix as destinations ----
echo ""
echo "Step A: Chain 138 bridges → add Gnosis, Cronos, Celo, Wemix as destinations"

configure_chain_138_destination "Gnosis" "$GNOSIS_SELECTOR" "$WETH9_GNOSIS" "$WETH10_GNOSIS"
configure_chain_138_destination "Cronos" "$CRONOS_SELECTOR" "$WETH9_CRONOS" "$WETH10_CRONOS"
configure_chain_138_destination "Celo" "$CELO_SELECTOR" "$WETH9_CELO" "$WETH10_CELO"
configure_chain_138_destination "Wemix" "$WEMIX_SELECTOR" "$WETH9_WEMIX" "$WETH10_WEMIX"

# ---- Step B: On Gnosis/Cronos/Celo/Wemix, add Chain 138 as destination ----
if [[ -z "$CHAIN138_SELECTOR" ]]; then
  echo ""
  echo "Step B: Skipped (CHAIN138_SELECTOR not set in .env). Set it to configure remote chains → Chain 138."
  echo "  Example: CHAIN138_SELECTOR=<decimal from CCIP Router getChainSelector()>"
else
  echo ""
  echo "Step B: Gnosis/Cronos/Celo/Wemix bridges → add Chain 138 as destination"

  configure_remote_chain_destination "Gnosis" "$GNOSIS_RPC" "$WETH9_GNOSIS" "$WETH10_GNOSIS"
  configure_remote_chain_destination "Cronos" "$CRONOS_RPC" "$WETH9_CRONOS" "$WETH10_CRONOS"
  configure_remote_chain_destination "Celo" "$CELO_RPC" "$WETH9_CELO" "$WETH10_CELO"
  configure_remote_chain_destination "Wemix" "$WEMIX_RPC" "$WETH9_WEMIX" "$WETH10_WEMIX"
fi

echo ""
log_success "Config-ready chains script finished."
echo "  Next: Fund each remote bridge with LINK (see docs/07-ccip/CONFIG_READY_CHAINS_COMPLETION_RUNBOOK.md)."
