#!/usr/bin/env bash
# Audit live cross-network funding routes for Chain 138 WETH9.
#
# This script distinguishes:
# - configured destination mappings on Chain 138
# - practical first-hop routes that actually work with the current relay model
# - mainnet-hub destinations that become useful only after mainnet is funded
#
# Important:
# - Chain 138 uses a custom router that emits MessageSent events but does not
#   natively deliver into public-chain bridges.
# - A native-mapped destination on Chain 138 is therefore configuration signal,
#   not proof of a live direct route.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
cd "$PROJECT_ROOT"

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

need_var() {
  local name="$1"
  [[ -n "${!name:-}" ]] || {
    echo "Error: $name is required" >&2
    exit 1
  }
}

need_var PRIVATE_KEY
need_var RPC_URL_138
need_var ETHEREUM_MAINNET_RPC
need_var CCIPWETH9_BRIDGE_CHAIN138
need_var MAINNET_CCIP_WETH9_BRIDGE
need_var ETH_MAINNET_SELECTOR

DEPLOYER="$(cast wallet address "$PRIVATE_KEY" 2>/dev/null || true)"
[[ -n "$DEPLOYER" ]] || {
  echo "Error: could not derive deployer from PRIVATE_KEY" >&2
  exit 1
}

CHAIN138_SELECTOR_VALUE="${CHAIN138_SELECTOR:-138}"
CURRENT_138_WETH9="${CCIPWETH9_BRIDGE_CHAIN138,,}"
LEGACY_138_WETH9="${CCIPWETH9_BRIDGE_DIRECT_LEGACY:-0x971cD9D156f193df8051E48043C476e53ECd4693}"
LEGACY_138_WETH9="${LEGACY_138_WETH9,,}"
MAINNET_WETH9="$(cast call "$MAINNET_CCIP_WETH9_BRIDGE" 'weth9()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" | tail -n1)"
MAINNET_FEE_TOKEN="$(cast call "$MAINNET_CCIP_WETH9_BRIDGE" 'feeToken()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" | tail -n1)"

fmt_ether() {
  local raw="${1:-0}"
  raw="$(echo "$raw" | awk '{print $1}')"
  cast from-wei "$raw" ether 2>/dev/null || echo "$raw"
}

contains_true() {
  [[ "$1" == *", true)"* ]]
}

extract_addr() {
  echo "$1" | grep -oE '0x[a-fA-F0-9]{40}' | head -n1 | tr '[:upper:]' '[:lower:]'
}

extract_enabled_addr() {
  local raw="$1"
  local addr
  addr="$(extract_addr "$raw")"
  if contains_true "$raw" && [[ -n "$addr" ]]; then
    echo "$addr"
  else
    echo ""
  fi
}

query_dest() {
  local rpc="$1"
  local bridge="$2"
  local selector="$3"
  if [[ -z "$rpc" || -z "$bridge" || -z "$selector" ]]; then
    echo "UNSET"
    return 0
  fi
  cast call "$bridge" 'destinations(uint64)((uint64,address,bool))' "$selector" --rpc-url "$rpc" 2>/dev/null || echo "ERROR"
}

quote_fee_state() {
  local rpc="$1"
  local bridge="$2"
  local selector="$3"
  if [[ -z "$rpc" || -z "$bridge" || -z "$selector" ]]; then
    echo "n/a"
    return 0
  fi
  if cast call "$bridge" 'calculateFee(uint64,uint256)(uint256)' "$selector" 4000000000000000 --rpc-url "$rpc" >/dev/null 2>&1; then
    echo "quoted"
  else
    echo "blocked"
  fi
}

balance_of() {
  local rpc="$1"
  local token="$2"
  local wallet="$3"
  if [[ -z "$rpc" || -z "$token" || -z "$wallet" ]]; then
    echo "0"
    return 0
  fi
  cast call "$token" 'balanceOf(address)(uint256)' "$wallet" --rpc-url "$rpc" 2>/dev/null | awk '{print $1}' || echo "0"
}

native_balance() {
  local rpc="$1"
  if [[ -z "$rpc" ]]; then
    echo "0"
    return 0
  fi
  cast balance "$DEPLOYER" --rpc-url "$rpc" 2>/dev/null || echo "0"
}

configured_class() {
  local source_addr="$1"
  local expected_bridge="$2"
  if [[ -z "${expected_bridge,,}" ]]; then
    echo "deploy-first"
  elif [[ "$source_addr" == "${expected_bridge,,}" ]]; then
    echo "native-mapped"
  elif [[ -n "$source_addr" ]]; then
    echo "relay-or-other"
  else
    echo "disabled"
  fi
}

practical_route() {
  local name="$1"
  local hub_quote="$2"
  case "$name" in
    mainnet|bsc|avalanche) echo "relay-backed-first-hop" ;;
    wemix) echo "deploy-first" ;;
    *)
      if [[ "$hub_quote" == "blocked" ]]; then
        echo "mainnet-hub-blocked"
      else
        echo "via-mainnet-hub"
      fi
      ;;
  esac
}

relay_inventory_state() {
  local balance="$1"
  if [[ "$(echo "$balance > 0" | bc)" == "1" ]]; then
    echo "present"
  else
    echo "empty"
  fi
}

detail_line() {
  local name="$1"
  local configured="$2"
  local mainnet_to_remote="$3"
  local mainnet_quote="$4"
  local remote_to_138="$5"
  local relay_balance="$6"
  local source_addr="$7"

  local parts=()
  case "$configured" in
    native-mapped) parts+=("138 mapping matches native bridge") ;;
    relay-or-other) parts+=("138 mapping points at non-native receiver $source_addr") ;;
    deploy-first) parts+=("bridge not deployed in env") ;;
    *) parts+=("138 mapping missing or disabled") ;;
  esac

  if contains_true "$mainnet_to_remote"; then
    if [[ "$mainnet_quote" == "blocked" ]]; then
      parts+=("mainnet hub mapping enabled but source fee quote reverts")
    else
      parts+=("mainnet hub mapping enabled")
    fi
  else
    parts+=("mainnet hub mapping missing or disabled")
  fi

  local back_addr
  back_addr="$(extract_enabled_addr "$remote_to_138")"
  if [[ -n "$back_addr" ]]; then
    if [[ "$back_addr" == "$CURRENT_138_WETH9" ]]; then
      parts+=("return path points at current 138 bridge")
    elif [[ "$back_addr" == "$LEGACY_138_WETH9" ]]; then
      parts+=("return path still points at legacy 138 bridge")
    else
      parts+=("return path points at unexpected 138 bridge $back_addr")
    fi
  fi

  case "$(practical_route "$name" "$mainnet_quote")" in
    relay-backed-first-hop)
      parts+=("practical first hop")
      if [[ -n "$relay_balance" ]]; then
        parts+=("relay inventory $(relay_inventory_state "$relay_balance")")
      fi
      ;;
    via-mainnet-hub)
      parts+=("use after mainnet bootstrap")
      ;;
    mainnet-hub-blocked)
      parts+=("mainnet WETH9 public fan-out currently blocked at source bridge/router")
      ;;
    deploy-first)
      parts+=("deploy and seed before use")
      ;;
  esac

  local IFS='; '
  echo "${parts[*]}"
}

echo "=== Chain 138 Funding Route Audit (WETH9 rail) ==="
echo "Date: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
echo "Deployer: $DEPLOYER"
echo "Current Chain 138 WETH9 bridge: $CURRENT_138_WETH9"
echo "Legacy Chain 138 WETH9 bridge:  $LEGACY_138_WETH9"
echo "Mainnet WETH9 bridge:           ${MAINNET_CCIP_WETH9_BRIDGE,,}"
echo ""

printf '%-10s | %-14s | %-14s | %-14s | %-16s | %-16s | %-22s | %-14s\n' \
  "Chain" "Native" "Wrapped" "LINK" "138 mapping" "Mainnet hub" "Practical route" "Relay inv."
printf '%s\n' "--------------------------------------------------------------------------------------------------------------------------------------------"

CHAINS=(
  "mainnet|$ETHEREUM_MAINNET_RPC|$ETH_MAINNET_SELECTOR|$MAINNET_CCIP_WETH9_BRIDGE|$MAINNET_WETH9|$MAINNET_FEE_TOKEN|${CCIP_RELAY_BRIDGE_MAINNET:-}"
  "bsc|$BSC_MAINNET_RPC|$BSC_SELECTOR|$CCIPWETH9_BRIDGE_BSC|$WETH9_BSC|$LINK_TOKEN_BSC|0x886C6A4ABC064dbf74E7caEc460b7eeC31F1b78C"
  "avalanche|$AVALANCHE_MAINNET_RPC|$AVALANCHE_SELECTOR|$CCIPWETH9_BRIDGE_AVALANCHE|$WETH9_AVALANCHE|$LINK_TOKEN_AVALANCHE|0x3f8C409C6072a2B6a4Ff17071927bA70F80c725F"
  "gnosis|$GNOSIS_RPC|$GNOSIS_SELECTOR|$CCIPWETH9_BRIDGE_GNOSIS|$WETH9_GNOSIS|$LINK_TOKEN_GNOSIS|"
  "cronos|$CRONOS_RPC|$CRONOS_SELECTOR|$CCIPWETH9_BRIDGE_CRONOS|$WETH9_CRONOS|$LINK_TOKEN_CRONOS|"
  "celo|$CELO_RPC|${CELO_SELECTOR:-1346049177634351622}|$CCIPWETH9_BRIDGE_CELO|$WETH9_CELO|$LINK_TOKEN_CELO|"
  "polygon|$POLYGON_MAINNET_RPC|$POLYGON_SELECTOR|$CCIPWETH9_BRIDGE_POLYGON|$WETH9_POLYGON|$LINK_TOKEN_POLYGON|"
  "arbitrum|$ARBITRUM_MAINNET_RPC|$ARBITRUM_SELECTOR|$CCIPWETH9_BRIDGE_ARBITRUM|$WETH9_ARBITRUM|$LINK_TOKEN_ARBITRUM|"
  "optimism|$OPTIMISM_MAINNET_RPC|$OPTIMISM_SELECTOR|$CCIPWETH9_BRIDGE_OPTIMISM|$WETH9_OPTIMISM|$LINK_TOKEN_OPTIMISM|"
  "base|$BASE_MAINNET_RPC|$BASE_SELECTOR|$CCIPWETH9_BRIDGE_BASE|$WETH9_BASE|$LINK_TOKEN_BASE|"
  "wemix|$WEMIX_RPC|${WEMIX_SELECTOR:-5142893604156789321}|$CCIPWETH9_BRIDGE_WEMIX|$WETH9_WEMIX|$LINK_TOKEN_WEMIX|"
)

for entry in "${CHAINS[@]}"; do
  IFS='|' read -r name rpc selector expected_bridge wrapped_token link_token relay_bridge <<< "$entry"

  native_raw="$(native_balance "$rpc")"
  wrapped_raw="$(balance_of "$rpc" "$wrapped_token" "$DEPLOYER")"
  link_raw="$(balance_of "$rpc" "$link_token" "$DEPLOYER")"

  source_dest="$(query_dest "$RPC_URL_138" "$CCIPWETH9_BRIDGE_CHAIN138" "$selector")"
  source_addr="$(extract_enabled_addr "$source_dest")"
  mainnet_to_remote="$(query_dest "$ETHEREUM_MAINNET_RPC" "$MAINNET_CCIP_WETH9_BRIDGE" "$selector")"
  mainnet_quote="n/a"
  if [[ "$name" != "mainnet" ]]; then
    mainnet_quote="$(quote_fee_state "$ETHEREUM_MAINNET_RPC" "$MAINNET_CCIP_WETH9_BRIDGE" "$selector")"
  fi
  mainnet_hub_flag="disabled"
  if [[ "$name" == "mainnet" ]]; then
    mainnet_hub_flag="n/a"
  elif contains_true "$mainnet_to_remote"; then
    mainnet_hub_flag="enabled/$mainnet_quote"
  fi

  relay_inv="n/a"
  if [[ -n "$relay_bridge" && -n "$wrapped_token" ]]; then
    relay_inv="$(fmt_ether "$(balance_of "$rpc" "$wrapped_token" "$relay_bridge")")"
  fi

  printf '%-10s | %-14s | %-14s | %-14s | %-16s | %-16s | %-22s | %-14s\n' \
    "$name" \
    "$(fmt_ether "$native_raw")" \
    "$(fmt_ether "$wrapped_raw")" \
    "$(fmt_ether "$link_raw")" \
    "$(configured_class "$source_addr" "$expected_bridge")" \
    "$mainnet_hub_flag" \
    "$(practical_route "$name" "$mainnet_quote")" \
    "$relay_inv"
done

echo ""
echo "Detail Notes"
echo "------------"

for entry in "${CHAINS[@]}"; do
  IFS='|' read -r name rpc selector expected_bridge wrapped_token _link_token relay_bridge <<< "$entry"
  source_dest="$(query_dest "$RPC_URL_138" "$CCIPWETH9_BRIDGE_CHAIN138" "$selector")"
  source_addr="$(extract_enabled_addr "$source_dest")"
  mainnet_to_remote="$(query_dest "$ETHEREUM_MAINNET_RPC" "$MAINNET_CCIP_WETH9_BRIDGE" "$selector")"
  mainnet_quote="n/a"
  if [[ "$name" != "mainnet" ]]; then
    mainnet_quote="$(quote_fee_state "$ETHEREUM_MAINNET_RPC" "$MAINNET_CCIP_WETH9_BRIDGE" "$selector")"
  fi
  remote_to_138="$(query_dest "$rpc" "$expected_bridge" "$CHAIN138_SELECTOR_VALUE")"
  relay_balance=""
  if [[ -n "$relay_bridge" && -n "$wrapped_token" ]]; then
    relay_balance="$(balance_of "$rpc" "$wrapped_token" "$relay_bridge")"
  fi
  echo "- $name: $(detail_line "$name" "$(configured_class "$source_addr" "$expected_bridge")" "$mainnet_to_remote" "$mainnet_quote" "$remote_to_138" "$relay_balance" "${source_addr:-disabled}")"
done

echo ""
echo "Important"
echo "---------"
echo "- This audit intentionally uses the WETH9 rail. Live WETH10 destination mappings are currently drifted from env and the mainnet WETH10 bridge is not wired to the public-chain destinations."
echo "- 'native-mapped' means the live Chain 138 destination address matches the expected native bridge address."
echo "- Because Chain 138 uses a custom event-emitting router, 'native-mapped' is configuration signal only, not proof of a direct live first-hop route."
echo "- Practical first hops today are the relay-backed lanes. The other public chains are best treated as mainnet-hub destinations unless a relay is added for them."
