#!/usr/bin/env bash
# E2E live test: lock on 138 -> submit claim on mainnet -> (after 30 min) finalize -> release bond.
# Run from a host that can reach RPC_URL_138. Requires .env in smom-dbis-138 repo root.
# Best: cd /path/to/smom-dbis-138 then ./scripts/deployment/run-e2e-trustless-live-test.sh
#
# Usage:
#   ./scripts/deployment/run-e2e-trustless-live-test.sh          # run step 1 (lock), then print steps 2–3
#   ./scripts/deployment/run-e2e-trustless-live-test.sh get-deposit-id <LOCK_TX_HASH>  # print DEPOSIT_ID from lock tx
#   DEPOSIT_ID=0x... AMOUNT_WEI=1000000000000000 ./scripts/deployment/run-e2e-trustless-live-test.sh claim  # run step 2 only
#   DEPOSIT_ID=0x... ./scripts/deployment/run-e2e-trustless-live-test.sh finalize  # run step 3 only
set -euo pipefail
# Resolve repo root from script path so this works from any cwd (use full path to script when invoking)
SCRIPT_PATH="${BASH_SOURCE[0]}"
[[ -z "$SCRIPT_PATH" ]] && SCRIPT_PATH="$0"
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
# 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
if [[ ! -d "$REPO_ROOT" ]]; then
  echo "Error: REPO_ROOT not found: $REPO_ROOT. Run from smom-dbis-138 repo, e.g. cd /path/to/smom-dbis-138 && ./scripts/deployment/run-e2e-trustless-live-test.sh"
  exit 1
fi
cd "$REPO_ROOT" || { echo "Error: cannot cd to $REPO_ROOT"; exit 1; }

# Use _MAINNET variants if unsuffixed not set (for .env that only has _MAINNET)
export BOND_MANAGER="${BOND_MANAGER:-${BOND_MANAGER_MAINNET:-}}"
export CHALLENGE_MANAGER="${CHALLENGE_MANAGER:-${CHALLENGE_MANAGER_MAINNET:-}}"
export INBOX_ETH="${INBOX_ETH:-${INBOX_ETH_MAINNET:-}}"
export LOCKBOX_138="${LOCKBOX_138:-}"
export RPC_URL_138="${RPC_URL_138:-${CHAIN_138_RPC_URL:-}}"
export ETHEREUM_MAINNET_RPC="${ETHEREUM_MAINNET_RPC:-}"

# Require key and RPCs so we fail with a clear message instead of "Invalid params"
require_private_key_env || exit 1
RECIPIENT="$(derive_deployer_address || true)"
[[ -n "$RECIPIENT" ]] || { echo "ERROR: Could not derive DEPLOYER_ADDRESS from PRIVATE_KEY." >&2; exit 1; }
NONCE=$(cast keccak "e2e-$(date +%s)" | tr -d '\n\r')
# 0.001 ether in wei
AMOUNT_WEI="${AMOUNT_WEI:-1000000000000000}"

case "${1:-}" in
  get-deposit-id)
    [[ -n "${RPC_URL_138:-}" ]] || { echo "RPC_URL_138 not set"; exit 1; }
    LOCK_TX="${2:-}"
    [[ -n "$LOCK_TX" ]] || { echo "Usage: $0 get-deposit-id <LOCK_TX_HASH>"; exit 1; }
    # Deposit event: first indexed param is depositId (topics[1])
    DEPOSIT_ID_HEX=$(cast receipt "$LOCK_TX" --rpc-url "$RPC_URL_138" -j 2>/dev/null | jq -r '.logs[0].topics[1] // empty')
    if [[ -z "$DEPOSIT_ID_HEX" ]]; then
      echo "No Deposit log in tx or jq failed. Try: cast logs $LOCK_TX \"Deposit(uint256,address,uint256,address,bytes32,address,uint256)\" --rpc-url \$RPC_URL_138"
      exit 1
    fi
    # cast expects uint256 as decimal or 0x; topics are 32-byte hex (0x + 64 chars)
    echo "$DEPOSIT_ID_HEX"
    exit 0
    ;;
  claim)
    [[ -n "${ETHEREUM_MAINNET_RPC:-}" ]] || { echo "ETHEREUM_MAINNET_RPC not set"; exit 1; }
    [[ -n "${INBOX_ETH:-}" && -n "${BOND_MANAGER:-}" ]] || { echo "INBOX_ETH and BOND_MANAGER must be set for claim"; exit 1; }
    if [[ -z "${DEPOSIT_ID:-}" ]]; then
      echo "Set DEPOSIT_ID (from step 1 lock tx Deposit event). Example: DEPOSIT_ID=0x... $0 claim"
      echo "To get DEPOSIT_ID from lock tx: cast logs <LOCK_TX_HASH> \"Deposit(uint256,address,uint256,address,bytes32,address,uint256)\" --rpc-url \$RPC_URL_138"
      echo "  Use the first decoded arg (depositId) as DEPOSIT_ID. Do NOT use AMOUNT_WEI as DEPOSIT_ID."
      exit 1
    fi
    # Avoid common mistake: DEPOSIT_ID must be the event's depositId (large/hash), not the amount
    if [[ "${DEPOSIT_ID:-}" == "1000000000000000" ]] || [[ "${DEPOSIT_ID:-}" == "$AMOUNT_WEI" ]]; then
      echo "Error: DEPOSIT_ID looks like AMOUNT_WEI (0.001 ether). Set DEPOSIT_ID to the depositId from the Deposit event, not the amount."
      exit 1
    fi
    BOND=$(cast call "$BOND_MANAGER" "getRequiredBond(uint256)(uint256)" "$AMOUNT_WEI" --rpc-url "$ETHEREUM_MAINNET_RPC")
    # cast may append " [1e18]" etc.; use only the numeric part for --value
    BOND="${BOND%% *}"
    echo "BOND (required for claim): $BOND wei"
    cast send "$INBOX_ETH" "submitClaim(uint256,address,uint256,address,bytes)" \
      "$DEPOSIT_ID" 0x0000000000000000000000000000000000000000 "$AMOUNT_WEI" "$RECIPIENT" 0x \
      --value "$BOND" --rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"
    echo "Claim submitted. Wait ~30 min then run: DEPOSIT_ID=$DEPOSIT_ID $0 finalize"
    exit 0
    ;;
  finalize)
    [[ -n "${ETHEREUM_MAINNET_RPC:-}" ]] || { echo "ETHEREUM_MAINNET_RPC not set"; exit 1; }
    [[ -n "${CHALLENGE_MANAGER:-}" && -n "${BOND_MANAGER:-}" ]] || { echo "CHALLENGE_MANAGER and BOND_MANAGER must be set for finalize"; exit 1; }
    if [[ -z "${DEPOSIT_ID:-}" ]]; then
      echo "Set DEPOSIT_ID. Example: DEPOSIT_ID=0x... $0 finalize"
      exit 1
    fi
    cast send "$CHALLENGE_MANAGER" "finalizeClaim(uint256)" "$DEPOSIT_ID" \
      --rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"
    cast send "$BOND_MANAGER" "releaseBond(uint256)" "$DEPOSIT_ID" \
      --rpc-url "$ETHEREUM_MAINNET_RPC" --private-key "$PRIVATE_KEY"
    echo "Finalized and bond released."
    exit 0
    ;;
esac

# Step 1: Lock on 138
[[ -n "${RPC_URL_138:-}" ]] || { echo "RPC_URL_138 not set (required for lock on 138)"; exit 1; }
[[ -n "${LOCKBOX_138:-}" ]] || { echo "LOCKBOX_138 not set in .env"; exit 1; }
# Fail fast if RPC is not Chain 138 (avoids -32602 Invalid params from wrong chain)
CHAIN_ID=$(curl -s -m 5 -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' "$RPC_URL_138" 2>/dev/null | sed -n 's/.*"result":"\([^"]*\)".*/\1/p')
if [[ "$CHAIN_ID" != "0x8a" && "$CHAIN_ID" != "0x8A" ]]; then
  echo "Error: RPC_URL_138 ($RPC_URL_138) returned chainId=$CHAIN_ID; expected 0x8a (138). Fix .env and retry."
  exit 1
fi
echo "Step 1: Lock 0.001 ether on Chain 138 (LOCKBOX_138=$LOCKBOX_138)"
echo "RECIPIENT=$RECIPIENT NONCE=$NONCE"
# Use explicit --gas-limit to avoid eth_estimateGas -32602 Invalid params on some Chain 138 (Besu) nodes
cast send "$LOCKBOX_138" "depositNative(address,bytes32)" "$RECIPIENT" "$NONCE" \
  --value 0.001ether --rpc-url "$RPC_URL_138" --private-key "$PRIVATE_KEY" \
  --legacy --gas-price "${GAS_PRICE_138:-1000000000}" --gas-limit "${GAS_LIMIT_138:-200000}"
echo ""
echo "Get DEPOSIT_ID from the lock tx (run with the tx hash from above):"
echo "  export DEPOSIT_ID=\$(./scripts/deployment/run-e2e-trustless-live-test.sh get-deposit-id <LOCK_TX_HASH>)"
echo "  AMOUNT_WEI=$AMOUNT_WEI $0 claim"
echo "Or manually: cast logs <LOCK_TX_HASH> \"Deposit(uint256,address,uint256,address,bytes32,address,uint256)\" --rpc-url \$RPC_URL_138 (use first decoded arg)"
echo "Note: DEPOSIT_ID is the event's depositId, NOT the amount. Required bond for 0.001 ether is 1 ETH (min bond)."
