#!/usr/bin/env bash
# Deploy WETH9/WETH10 + CCIP bridges (and optionally Cronos D-WIN W) to all blockchains
# unless a canonical/pre-existing deployment is already present in .env.
#
# Deploys:
#   - WETH9, WETH10, CCIPWETH9Bridge, CCIPWETH10Bridge (via DeployAll.s.sol) on each chain
#     where WETH9_<CHAIN> and WETH10_<CHAIN> are not both set.
#   - On Cronos (25): optionally ISO-4217 W system (USDW, EURW, ...) if not already deployed.
#   - With --deploy-c: cUSDT/cUSDC (and optional c*) on each chain where CUSDT_<CHAIN>/CUSDC_<CHAIN> unset (via DeployCompliantFiatTokensForChain.s.sol).
#   - With --deploy-cw: cWUSDT/cWUSDC on each chain where CWUSDT_<CHAIN> unset (via DeployCWTokens.s.sol; set CW_BRIDGE_ADDRESS or CW_BRIDGE_<CHAIN>).
#   - Chain 651940 (ALL Mainnet): env validation only (check AUSDT_ADDRESS_651940 set); no token deploy from this repo.
#
# Skips:
#   - Ethereum Mainnet (1): uses canonical WETH from .env (WETH9_MAINNET, WETH10_MAINNET).
#   - Any chain where both WETH9_* and WETH10_* are already set in .env.
#   - Chain 138: not in DeployAll; compliant tokens (c*) are deployed separately on 138.
#
# Usage:
#   cd smom-dbis-138 && ./scripts/deployment/deploy-tokens-and-weth-all-chains-skip-canonical.sh [OPTIONS]
#
# Options:
#   --dry-run              Print commands only; do not broadcast.
#   --chain 25 56 137      Deploy only to these chain IDs (default: all supported).
#   --no-iso4217           Do not deploy ISO-4217 W system on Cronos even if missing.
#   --iso4217-only         Only run Cronos ISO-4217 W deploy (skip DeployAll).
#   --deploy-c             Deploy cUSDT/cUSDC (and optional c*) on chains where CUSDT_<CHAIN>/CUSDC_<CHAIN> unset (skip 138, 1).
#   --deploy-cw            Deploy cWUSDT/cWUSDC on chains where CWUSDT_<CHAIN> unset; requires CW_BRIDGE_ADDRESS or CW_BRIDGE_<CHAIN> in .env.
#
# Requires: .env with PRIVATE_KEY; per-chain RPC and CCIP vars for chains you deploy to.
# See: docs/11-references/TOKENS_DEPLOYER_DEPLOYED_ON_OTHER_CHAINS.md

set -euo pipefail

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


DRY_RUN=false
CHAINS_FILTER=""
NO_ISO4217=false
ISO4217_ONLY=false
DEPLOY_C=false
DEPLOY_CW=false

while [[ $# -gt 0 ]]; do
  case "$1" in
    --dry-run)       DRY_RUN=true; shift ;;
    --no-iso4217)    NO_ISO4217=true; shift ;;
    --iso4217-only) ISO4217_ONLY=true; shift ;;
    --deploy-c)      DEPLOY_C=true; shift ;;
    --deploy-cw)     DEPLOY_CW=true; shift ;;
    --chain)
      shift
      CHAINS_FILTER="$*"
      break
      ;;
    *) shift ;;
  esac
done

# Chain ID : Name : RPC env var (primary)
# DeployAll.s.sol supports: 1, 25, 56, 137, 100, 43114, 8453, 42161, 10. 651940 = env validation only.
# Celo / Wemix are included here for c* / cW* deployment even though their WETH/bridge deploy
# flow is handled separately via deploy-bridges-config-ready-chains.sh.
ALL_CHAINS="1:Mainnet:ETH_MAINNET_RPC_URL 25:Cronos:CRONOS_RPC_URL 56:BSC:BSC_RPC_URL 137:Polygon:POLYGON_RPC_URL 100:Gnosis:GNOSIS_RPC_URL 43114:Avalanche:AVALANCHE_RPC_URL 8453:Base:BASE_RPC_URL 42161:Arbitrum:ARBITRUM_RPC_URL 10:Optimism:OPTIMISM_RPC_URL 42220:Celo:CELO_RPC 1111:Wemix:WEMIX_RPC 651940:ALL:CHAIN_651940_RPC"

# Fallback RPC env names (some scripts use different names)
fallback_rpc() {
  local chain_id="$1"
  local rpc_var="$2"
  local rpc="${!rpc_var:-}"
  if [[ -z "$rpc" ]]; then
    case "$chain_id" in
      1)   rpc="${ETHEREUM_MAINNET_RPC:-${ETH_MAINNET_RPC_URL:-}}";;
      25)  rpc="${CRONOS_RPC:-}";;
      56)  rpc="${BSC_RPC_URL:-}";;
      137) rpc="${POLYGON_MAINNET_RPC:-}";;
      100) rpc="${GNOSIS_RPC:-}";;
      43114) rpc="${AVALANCHE_RPC_URL:-}";;
      8453) rpc="${BASE_MAINNET_RPC:-}";;
      42161) rpc="${ARBITRUM_MAINNET_RPC:-}";;
      10)  rpc="${OPTIMISM_MAINNET_RPC:-}";;
      42220) rpc="${CELO_RPC:-${CELO_MAINNET_RPC:-}}";;
      1111) rpc="${WEMIX_RPC:-${WEMIX_MAINNET_RPC:-}}";;
      651940) rpc="${CHAIN_651940_RPC:-${ALL_MAINNET_RPC:-}}";;
    esac
  fi
  echo "$rpc"
}

is_canonical_present() {
  local weth9_var="$1"
  local weth10_var="$2"
  local w9="${!weth9_var:-}"
  local w10="${!weth10_var:-}"
  w9="${w9//0x/}"
  w10="${w10//0x/}"
  [[ -n "$w9" && "${#w9}" -ge 40 && "$w9" != "0000000000000000000000000000000000000000" ]] && \
  [[ -n "$w10" && "${#w10}" -ge 40 && "$w10" != "0000000000000000000000000000000000000000" ]] && return 0
  return 1
}

run_cmd() {
  if $DRY_RUN; then
    echo "  [DRY-RUN] $*"
  else
    eval "$@" || return 1
  fi
}

# ---------- DeployAll (WETH9, WETH10, CCIP bridges) per chain ----------
run_deploy_all() {
  local chain_id="$1"
  local name="$2"
  local rpc_var="$3"
  if [[ "$chain_id" == "651940" ]]; then
    echo "  Skip $name (chain 651940): DeployAll not supported; env validation only."
    return 0
  fi
  if [[ "$chain_id" == "42220" || "$chain_id" == "1111" ]]; then
    echo "  Skip $name (chain $chain_id): WETH/bridge deploy handled by deploy-bridges-config-ready-chains.sh; c*/cW* phases may still run."
    return 0
  fi
  local rpc
  rpc=$(fallback_rpc "$chain_id" "$rpc_var")
  if [[ -z "$rpc" ]]; then
    echo "  Skip $name (chain $chain_id): RPC not set ($rpc_var)."
    return 0
  fi

  local weth9_var="WETH9_MAINNET" weth10_var="WETH10_MAINNET"
  case "$chain_id" in
    1)   weth9_var="WETH9_MAINNET";   weth10_var="WETH10_MAINNET" ;;
    25)  weth9_var="WETH9_CRONOS";    weth10_var="WETH10_CRONOS" ;;
    56)  weth9_var="WETH9_BSC";       weth10_var="WETH10_BSC" ;;
    137) weth9_var="WETH9_POLYGON";   weth10_var="WETH10_POLYGON" ;;
    100) weth9_var="WETH9_GNOSIS";    weth10_var="WETH10_GNOSIS" ;;
    43114) weth9_var="WETH9_AVALANCHE"; weth10_var="WETH10_AVALANCHE" ;;
    8453) weth9_var="WETH9_BASE";      weth10_var="WETH10_BASE" ;;
    42161) weth9_var="WETH9_ARBITRUM"; weth10_var="WETH10_ARBITRUM" ;;
    10)  weth9_var="WETH9_OPTIMISM";   weth10_var="WETH10_OPTIMISM" ;;
    *)   echo "  Unsupported chain ID $chain_id"; return 1 ;;
  esac

  # Mainnet: use canonical WETH from .env; DeployAll only deploys CCIPLogger (placeholder). Skip to avoid requiring env.
  if [[ "$chain_id" == "1" ]]; then
    if is_canonical_present "$weth9_var" "$weth10_var"; then
      echo "  Skip $name (chain $chain_id): canonical WETH9/WETH10 already set."
      return 0
    fi
    echo "  Skip $name (chain $chain_id): set WETH9_MAINNET and WETH10_MAINNET in .env for canonical WETH; DeployAll on Mainnet does not deploy tokens."
    return 0
  fi

  if is_canonical_present "$weth9_var" "$weth10_var"; then
    echo "  Skip $name (chain $chain_id): WETH9/WETH10 already set in .env."
    return 0
  fi

  echo "  Deploying WETH9, WETH10, CCIP bridges on $name (chain $chain_id)..."
  local gas_opts="--legacy"
  run_cmd "forge script script/DeployAll.s.sol:DeployAll --rpc-url \"$rpc\" --chain-id \"$chain_id\" --broadcast --private-key \"\$PRIVATE_KEY\" $gas_opts -vvv" || true
  echo "  → Set WETH9_${name^^}, WETH10_${name^^}, CCIPWETH9_BRIDGE_${name^^}, CCIPWETH10_BRIDGE_${name^^} in .env from script output."
}

# ---------- ISO-4217 W (Cronos): deploy only if USDW not already deployed ----------
run_iso4217_cronos() {
  if $NO_ISO4217; then
    echo "  Skip Cronos ISO-4217 W (--no-iso4217)."
    return 0
  fi

  local rpc
  rpc=$(fallback_rpc 25 "CRONOS_RPC_URL")
  [[ -z "$rpc" ]] && rpc="${CRONOS_RPC:-}"
  if [[ -z "$rpc" ]]; then
    echo "  Skip Cronos ISO-4217 W: CRONOS_RPC_URL / CRONOS_RPC not set."
    return 0
  fi

  local usdw_addr="0x948690147D2e50ffe50C5d38C14125aD6a9FA036"
  local code_len
  code_len=$(cast code "$usdw_addr" --rpc-url "$rpc" 2>/dev/null | wc -c)
  if [[ -n "$code_len" && "$code_len" -gt 10 ]]; then
    echo "  Skip Cronos ISO-4217 W: USDW already deployed at $usdw_addr."
    return 0
  fi

  echo "  Deploying ISO-4217 W system on Cronos (25)..."
  run_cmd "forge script script/deploy/iso4217w/DeployISO4217WSystem.s.sol:DeployISO4217WSystem --rpc-url \"$rpc\" --chain-id 25 --broadcast --private-key \"\$PRIVATE_KEY\" --legacy -vvv" || true
  echo "  → Record MintController, TokenRegistry, USDW, EURW, ... addresses from output; add to .env / docs."
}

# ---------- c* (cUSDT, cUSDC) on other chains: DeployCompliantFiatTokensForChain ----------
run_deploy_c() {
  local chain_id="$1"
  local name="$2"
  local rpc_var="$3"
  [[ "$chain_id" == "138" || "$chain_id" == "1" ]] && return 0
  local rpc
  rpc=$(fallback_rpc "$chain_id" "$rpc_var")
  if [[ -z "$rpc" ]]; then return 0; fi
  local cusdt_var="CUSDT_${name^^}" cusdc_var="CUSDC_${name^^}"
  local cusdt_val="${!cusdt_var:-}" cusdc_val="${!cusdc_var:-}"
  cusdt_val="${cusdt_val//0x/}"; cusdc_val="${cusdc_val//0x/}"
  if [[ -n "$cusdt_val" && "${#cusdt_val}" -ge 40 ]] && [[ -n "$cusdc_val" && "${#cusdc_val}" -ge 40 ]]; then
    echo "  Skip c* on $name (chain $chain_id): CUSDT_${name^^} and CUSDC_${name^^} already set."
    return 0
  fi
  echo "  Deploying cUSDT/cUSDC on $name (chain $chain_id)..."
  run_cmd "forge script script/deploy/DeployCompliantFiatTokensForChain.s.sol:DeployCompliantFiatTokensForChain --rpc-url \"$rpc\" --chain-id \"$chain_id\" --broadcast --private-key \"\$PRIVATE_KEY\" --legacy -vvv" || true
  echo "  → Set CUSDT_${name^^}, CUSDC_${name^^} in .env from script output."
}

# ---------- cW* (all 12: cWUSDT, cWUSDC, cWEURC, cWEURT, cWGBPC, cWGBPT, cWAUDC, cWJPYC, cWCHFC, cWCADC, cWXAUC, cWXAUT): DeployCWTokens ----------
run_deploy_cw() {
  local chain_id="$1"
  local name="$2"
  local rpc_var="$3"
  local rpc
  rpc=$(fallback_rpc "$chain_id" "$rpc_var")
  if [[ -z "$rpc" ]]; then return 0; fi
  local bridge_var="CW_BRIDGE_${name^^}"
  local ccip_bridge_var="CCIPWETH9_BRIDGE_${name^^}"
  local bridge="${!bridge_var:-${CW_BRIDGE_ADDRESS:-}}"
  if [[ -z "$bridge" || "$bridge" == "0x0000000000000000000000000000000000000000" ]]; then
    bridge="${!ccip_bridge_var:-}"
  fi
  if [[ -z "$bridge" || "$bridge" == "0x"*"0000000000000000000000000000000000000000" ]]; then
    echo "  Skip cW* on $name (chain $chain_id): set CW_BRIDGE_ADDRESS / CW_BRIDGE_${name^^} or deploy/configure CCIPWETH9_BRIDGE_${name^^}."
    return 0
  fi
  local cw_var="CWUSDT_${name^^}"
  local cw_val="${!cw_var:-}"
  cw_val="${cw_val//0x/}"
  local deploy_opts=""
  if [[ -n "$cw_val" && "${#cw_val}" -ge 40 ]]; then
    echo "  Deploying remaining cW* (cWEURC..cWXAUT) on $name (chain $chain_id) (bridge $bridge)..."
    deploy_opts="DEPLOY_CWUSDT=0 DEPLOY_CWUSDC=0"
  else
    echo "  Deploying all cW* (12 tokens) on $name (chain $chain_id) (bridge $bridge)..."
  fi
  local gas_opt=""
  [[ "$chain_id" == "42161" && -n "${ARBITRUM_GAS_PRICE:-}" ]] && gas_opt="--with-gas-price ${ARBITRUM_GAS_PRICE}"
  run_cmd "${deploy_opts:+$deploy_opts }CW_BRIDGE_ADDRESS=$bridge forge script script/deploy/DeployCWTokens.s.sol:DeployCWTokens --rpc-url \"$rpc\" --chain-id \"$chain_id\" --broadcast --private-key \"\$PRIVATE_KEY\" --legacy ${gas_opt} -vvv" || true
  echo "  → Set CWUSDT_*, CWUSDC_*, CWEURC_*, CWEURT_*, CWGBPC_*, CWGBPT_*, CWAUDC_*, CWJPYC_*, CWCHFC_*, CWCADC_*, CWXAUC_*, CWXAUT_* in .env from script output."
}

# ---------- 651940 (ALL Mainnet): env validation only ----------
run_651940_validate() {
  local rpc
  rpc=$(fallback_rpc 651940 "CHAIN_651940_RPC")
  if [[ -z "$rpc" ]]; then
    echo "  Skip ALL (651940): CHAIN_651940_RPC not set."
    return 0
  fi
  local ausdt_var="AUSDT_ADDRESS_651940"
  local ausdt_val="${!ausdt_var:-}"
  if [[ -z "$ausdt_val" || "$ausdt_val" == "0x0000000000000000000000000000000000000000" ]]; then
    echo "  ALL (651940): Set AUSDT_ADDRESS_651940 in .env (ecosystem token; not deployed by this script)."
  else
    echo "  ALL (651940): AUSDT_ADDRESS_651940 set."
  fi
}

# ---------- Main ----------
echo "=============================================="
echo "Deploy tokens/WETH to all chains (skip canonical)"
echo "=============================================="
echo "  Dry-run: $DRY_RUN"
echo "  Chain filter: ${CHAINS_FILTER:-all}"
echo "  ISO-4217 on Cronos: $(! $NO_ISO4217 && ! $ISO4217_ONLY || $ISO4217_ONLY)"
echo "  Deploy c* (cUSDT/cUSDC): $DEPLOY_C"
echo "  Deploy cW* (cWUSDT/cWUSDC): $DEPLOY_CW"
echo ""

if [[ -z "${PRIVATE_KEY:-}" ]]; then
  echo "ERROR: PRIVATE_KEY not set in .env." >&2
  exit 1
fi

if ! $ISO4217_ONLY; then
  echo "--- DeployAll (WETH9, WETH10, CCIP bridges) per chain ---"
  for entry in $ALL_CHAINS; do
    chain_id="${entry%%:*}"; rest="${entry#*:}"
    name="${rest%%:*}"; rpc_var="${rest#*:}"
    if [[ -n "$CHAINS_FILTER" ]]; then
      echo "$CHAINS_FILTER" | grep -q "\b$chain_id\b" || continue
    fi
    run_deploy_all "$chain_id" "$name" "$rpc_var"
  done
  echo ""
fi

if ! $ISO4217_ONLY; then
  if [[ -z "$CHAINS_FILTER" ]] || echo "$CHAINS_FILTER" | grep -q "\b25\b"; then
    echo "--- Cronos: ISO-4217 W (USDW, EURW, ...) ---"
    run_iso4217_cronos
    echo ""
  fi
else
  echo "--- Cronos: ISO-4217 W only ---"
  run_iso4217_cronos
  echo ""
fi

if $DEPLOY_C; then
  echo "--- Deploy c* (cUSDT/cUSDC) per chain (skip 138, 1) ---"
  for entry in $ALL_CHAINS; do
    chain_id="${entry%%:*}"; rest="${entry#*:}"
    name="${rest%%:*}"; rpc_var="${rest#*:}"
    if [[ "$chain_id" == "651940" ]]; then continue; fi
    if [[ -n "$CHAINS_FILTER" ]]; then
      echo "$CHAINS_FILTER" | grep -q "\b$chain_id\b" || continue
    fi
    run_deploy_c "$chain_id" "$name" "$rpc_var"
  done
  echo ""
fi

if $DEPLOY_CW; then
  echo "--- Deploy cW* (cWUSDT/cWUSDC) per chain ---"
  for entry in $ALL_CHAINS; do
    chain_id="${entry%%:*}"; rest="${entry#*:}"
    name="${rest%%:*}"; rpc_var="${rest#*:}"
    if [[ "$chain_id" == "651940" ]]; then continue; fi
    if [[ -n "$CHAINS_FILTER" ]]; then
      echo "$CHAINS_FILTER" | grep -q "\b$chain_id\b" || continue
    fi
    run_deploy_cw "$chain_id" "$name" "$rpc_var"
  done
  echo ""
fi

echo "--- Chain 651940 (ALL Mainnet) env validation ---"
for entry in $ALL_CHAINS; do
  chain_id="${entry%%:*}"; rest="${entry#*:}"
  name="${rest%%:*}"; rpc_var="${rest#*:}"
  if [[ "$chain_id" != "651940" ]]; then continue; fi
  if [[ -n "$CHAINS_FILTER" ]]; then
    echo "$CHAINS_FILTER" | grep -q "\b651940\b" || continue
  fi
  run_651940_validate
  break
done
echo ""

echo "=============================================="
echo "Done. Update .env with deployed addresses; see TOKENS_DEPLOYER_DEPLOYED_ON_OTHER_CHAINS.md."
echo "=============================================="
