#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SMOM_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
ENV_FILE="$SMOM_ROOT/.env"
CONFIG_JSON="${POOL_CONFIG_JSON:-$SMOM_ROOT/config/chain138-pmm-pools.json}"
ORIG_RPC_URL_138="${RPC_URL_138-}"
ORIG_RPC_URL="${RPC_URL-}"
ORIG_DODO_PMM_INTEGRATION_ADDRESS="${DODO_PMM_INTEGRATION_ADDRESS-}"
ORIG_DODO_PMM_INTEGRATION="${DODO_PMM_INTEGRATION-}"
ORIG_DODO_PMM_PROVIDER_ADDRESS="${DODO_PMM_PROVIDER_ADDRESS-}"
ORIG_DODO_PMM_PROVIDER="${DODO_PMM_PROVIDER-}"
ORIG_PRIVATE_KEY="${PRIVATE_KEY-}"
ORIG_DRY_RUN="${DRY_RUN-}"
ORIG_CHAIN_GAS_PRICE="${CHAIN_GAS_PRICE-}"
ORIG_TX_TIMEOUT_SECONDS="${TX_TIMEOUT_SECONDS-}"
ORIG_POST_CREATE_POLL_SECONDS="${POST_CREATE_POLL_SECONDS-}"
ORIG_POST_CREATE_POLL_INTERVAL="${POST_CREATE_POLL_INTERVAL-}"
ORIG_CREATE_POOL_GAS_LIMIT="${CREATE_POOL_GAS_LIMIT-}"
ORIG_REGISTER_POOL_GAS_LIMIT="${REGISTER_POOL_GAS_LIMIT-}"

if [[ -f "$SMOM_ROOT/scripts/lib/deployment/dotenv.sh" ]]; then
  # shellcheck disable=SC1091
  source "$SMOM_ROOT/scripts/lib/deployment/dotenv.sh"
  load_deployment_env --repo-root "$SMOM_ROOT"
elif [[ -f "$ENV_FILE" ]]; then
  had_nounset=0
  if [[ $- == *u* ]]; then
    had_nounset=1
    set +u
  fi
  set -a
  # shellcheck disable=SC1090
  source "$ENV_FILE"
  set +a
  (( had_nounset )) && set -u
fi

[[ -n "$ORIG_RPC_URL_138" ]] && RPC_URL_138="$ORIG_RPC_URL_138"
[[ -n "$ORIG_RPC_URL" ]] && RPC_URL="$ORIG_RPC_URL"
[[ -n "$ORIG_DODO_PMM_INTEGRATION_ADDRESS" ]] && DODO_PMM_INTEGRATION_ADDRESS="$ORIG_DODO_PMM_INTEGRATION_ADDRESS"
[[ -n "$ORIG_DODO_PMM_INTEGRATION" ]] && DODO_PMM_INTEGRATION="$ORIG_DODO_PMM_INTEGRATION"
[[ -n "$ORIG_DODO_PMM_PROVIDER_ADDRESS" ]] && DODO_PMM_PROVIDER_ADDRESS="$ORIG_DODO_PMM_PROVIDER_ADDRESS"
[[ -n "$ORIG_DODO_PMM_PROVIDER" ]] && DODO_PMM_PROVIDER="$ORIG_DODO_PMM_PROVIDER"
[[ -n "$ORIG_PRIVATE_KEY" ]] && PRIVATE_KEY="$ORIG_PRIVATE_KEY"
[[ -n "$ORIG_DRY_RUN" ]] && DRY_RUN="$ORIG_DRY_RUN"
[[ -n "$ORIG_CHAIN_GAS_PRICE" ]] && CHAIN_GAS_PRICE="$ORIG_CHAIN_GAS_PRICE"
[[ -n "$ORIG_TX_TIMEOUT_SECONDS" ]] && TX_TIMEOUT_SECONDS="$ORIG_TX_TIMEOUT_SECONDS"
[[ -n "$ORIG_POST_CREATE_POLL_SECONDS" ]] && POST_CREATE_POLL_SECONDS="$ORIG_POST_CREATE_POLL_SECONDS"
[[ -n "$ORIG_POST_CREATE_POLL_INTERVAL" ]] && POST_CREATE_POLL_INTERVAL="$ORIG_POST_CREATE_POLL_INTERVAL"
[[ -n "$ORIG_CREATE_POOL_GAS_LIMIT" ]] && CREATE_POOL_GAS_LIMIT="$ORIG_CREATE_POOL_GAS_LIMIT"
[[ -n "$ORIG_REGISTER_POOL_GAS_LIMIT" ]] && REGISTER_POOL_GAS_LIMIT="$ORIG_REGISTER_POOL_GAS_LIMIT"

RPC_URL_138="${RPC_URL_138:-${RPC_URL:-http://192.168.11.211:8545}}"
if [[ -n "$ORIG_DODO_PMM_INTEGRATION_ADDRESS" ]]; then
  DODO_PMM_INTEGRATION_ADDRESS="$ORIG_DODO_PMM_INTEGRATION_ADDRESS"
else
  DODO_PMM_INTEGRATION_ADDRESS="${CHAIN_138_DODO_PMM_INTEGRATION:-0x86ADA6Ef91A3B450F89f2b751e93B1b7A3218895}"
fi
if [[ -n "$ORIG_DODO_PMM_PROVIDER_ADDRESS" ]]; then
  DODO_PMM_PROVIDER_ADDRESS="$ORIG_DODO_PMM_PROVIDER_ADDRESS"
else
  DODO_PMM_PROVIDER_ADDRESS="${CHAIN_138_DODO_PMM_PROVIDER:-0x3f729632E9553EBacCdE2e9b4c8F2B285b014F2e}"
fi
DRY_RUN="${DRY_RUN:-0}"

[[ -f "$CONFIG_JSON" ]] || { echo "POOL_CONFIG_JSON not found: $CONFIG_JSON" >&2; exit 1; }
command -v jq >/dev/null 2>&1 || { echo "jq is required" >&2; exit 1; }
command -v cast >/dev/null 2>&1 || { echo "cast is required" >&2; exit 1; }
[[ -n "$DODO_PMM_INTEGRATION_ADDRESS" ]] || { echo "DODO_PMM_INTEGRATION_ADDRESS not set" >&2; exit 1; }
[[ -n "$DODO_PMM_PROVIDER_ADDRESS" ]] || { echo "DODO_PMM_PROVIDER_ADDRESS not set" >&2; exit 1; }
if [[ "$DRY_RUN" != "1" ]]; then
  require_private_key_env || exit 1
fi
CHAIN_GAS_PRICE="${CHAIN_GAS_PRICE:-1000000000}"
TX_TIMEOUT_SECONDS="${TX_TIMEOUT_SECONDS:-120}"
POST_CREATE_POLL_SECONDS="${POST_CREATE_POLL_SECONDS:-20}"
POST_CREATE_POLL_INTERVAL="${POST_CREATE_POLL_INTERVAL:-1}"
CREATE_POOL_GAS_LIMIT="${CREATE_POOL_GAS_LIMIT:-900000}"
REGISTER_POOL_GAS_LIMIT="${REGISTER_POOL_GAS_LIMIT:-300000}"

LP_FEE="${LP_FEE_RATE:-$(jq -r '.defaults.lpFeeRate' "$CONFIG_JSON")}"
INITIAL_PRICE="${INITIAL_PRICE:-$(jq -r '.defaults.initialPrice' "$CONFIG_JSON")}"
K_FACTOR="${K_FACTOR:-$(jq -r '.defaults.kFactor' "$CONFIG_JSON")}"
ENABLE_TWAP="${ENABLE_TWAP:-$(jq -r '.defaults.enableTwap' "$CONFIG_JSON")}"

declare -A TOKENS=()
while IFS=$'\t' read -r sym addr; do
  TOKENS["$sym"]="$addr"
done < <(jq -r '.tokens | to_entries[] | [.key, .value] | @tsv' "$CONFIG_JSON")

mapfile -t C_STARS < <(jq -r '.groups.cStarSymbols[]' "$CONFIG_JSON")
mapfile -t OFFICIALS < <(jq -r '.groups.officialStableSymbols[]' "$CONFIG_JSON")
WETH_SYMBOL="$(jq -r '.groups.wethSymbol' "$CONFIG_JSON")"
DEPLOY_CSTAR_CSTAR="$(jq -r '.groups.deploy.cStarVsCStar' "$CONFIG_JSON")"
DEPLOY_CSTAR_OFFICIAL="$(jq -r '.groups.deploy.cStarVsOfficial' "$CONFIG_JSON")"
DEPLOY_CSTAR_WETH="$(jq -r '.groups.deploy.cStarVsWeth' "$CONFIG_JSON")"
DEPLOY_OFFICIAL_WETH="$(jq -r '.groups.deploy.officialVsWeth' "$CONFIG_JSON")"

declare -A SEEN=()
DESIRED_PAIRS=()

add_pair() {
  local base_sym="$1" quote_sym="$2"
  local base="${TOKENS[$base_sym]:-}"
  local quote="${TOKENS[$quote_sym]:-}"
  local key="${base_sym}|${quote_sym}"

  [[ -n "$base" && -n "$quote" ]] || return 0
  [[ "$base" != "0x0000000000000000000000000000000000000000" ]] || return 0
  [[ "$quote" != "0x0000000000000000000000000000000000000000" ]] || return 0
  [[ -z "${SEEN[$key]:-}" ]] || return 0

  SEEN["$key"]=1
  DESIRED_PAIRS+=("${base_sym}|${base}|${quote_sym}|${quote}")
}

if [[ "$DEPLOY_CSTAR_CSTAR" == "true" ]]; then
  for ((i=0; i<${#C_STARS[@]}; i++)); do
    for ((j=i+1; j<${#C_STARS[@]}; j++)); do
      add_pair "${C_STARS[$i]}" "${C_STARS[$j]}"
    done
  done
fi

if [[ "$DEPLOY_CSTAR_OFFICIAL" == "true" ]]; then
  for cstar in "${C_STARS[@]}"; do
    for official in "${OFFICIALS[@]}"; do
      add_pair "$cstar" "$official"
    done
  done
fi

if [[ "$DEPLOY_CSTAR_WETH" == "true" ]]; then
  for cstar in "${C_STARS[@]}"; do
    add_pair "$cstar" "$WETH_SYMBOL"
  done
fi

if [[ "$DEPLOY_OFFICIAL_WETH" == "true" ]]; then
  for official in "${OFFICIALS[@]}"; do
    add_pair "$official" "$WETH_SYMBOL"
  done
fi

while IFS=$'\t' read -r base_sym quote_sym; do
  add_pair "$base_sym" "$quote_sym"
done < <(jq -r '.explicitPairs[]? | [.baseSymbol, .quoteSymbol] | @tsv' "$CONFIG_JSON")
while IFS=$'\t' read -r base_sym quote_sym; do
  add_pair "$base_sym" "$quote_sym"
done < <(jq -r '.plannedPairs[]? | [.baseSymbol, .quoteSymbol] | @tsv' "$CONFIG_JSON")

zero_addr='0x0000000000000000000000000000000000000000'
created=0
registered=0
skipped_existing=0
failed=0
CURRENT_NONCE=""

if [[ "$DRY_RUN" != "1" ]]; then
  DEPLOYER_ADDRESS="$(derive_deployer_address || true)"
  [[ -n "$DEPLOYER_ADDRESS" ]] || { echo "ERROR: Could not derive DEPLOYER_ADDRESS from PRIVATE_KEY." >&2; exit 1; }
fi

rpc_call() {
  local to="$1" data="$2"
  local payload
  payload=$(printf '{"jsonrpc":"2.0","method":"eth_call","params":[{"to":"%s","data":"%s"},"latest"],"id":1}' "$to" "$data")
  curl -s -X POST "$RPC_URL_138" -H 'Content-Type: application/json' --data "$payload"
}

json_result() {
  sed -n 's/.*"result":"\([^"]*\)".*/\1/p'
}

hex_to_addr() {
  local value="${1#0x}"
  if [[ ${#value} -lt 40 ]]; then
    echo "$zero_addr"
    return 0
  fi
  printf '0x%s\n' "${value: -40}"
}

pool_for() {
  local calldata result
  calldata="$(cast calldata "pools(address,address)" "$1" "$2" 2>/dev/null || true)"
  [[ -n "$calldata" ]] || { echo "$zero_addr"; return 0; }
  result="$(rpc_call "$DODO_PMM_INTEGRATION_ADDRESS" "$calldata" | json_result)"
  [[ -n "$result" ]] || { echo "$zero_addr"; return 0; }
  hex_to_addr "$result"
}

provider_pool_for() {
  local calldata result
  calldata="$(cast calldata "pools(address,address)" "$1" "$2" 2>/dev/null || true)"
  [[ -n "$calldata" ]] || { echo "$zero_addr"; return 0; }
  result="$(rpc_call "$DODO_PMM_PROVIDER_ADDRESS" "$calldata" | json_result)"
  [[ -n "$result" ]] || { echo "$zero_addr"; return 0; }
  hex_to_addr "$result"
}

send_tx() {
  local to="$1"
  shift
  local attempts nonce output rc
  for attempts in 1 2 3; do
    nonce="$(cast nonce "$DEPLOYER_ADDRESS" --block pending --rpc-url "$RPC_URL_138" 2>/dev/null || true)"
    [[ -n "$nonce" ]] || {
      echo "Failed to fetch pending nonce for deployer" >&2
      return 1
    }
    set +e
    output="$(cast send "$to" "$@" \
      --rpc-url "$RPC_URL_138" \
      --private-key "$PRIVATE_KEY" \
      --legacy \
      --gas-price "$CHAIN_GAS_PRICE" \
      --nonce "$nonce" \
      --confirmations 1 \
      --timeout "$TX_TIMEOUT_SECONDS" \
      -q 2>&1)"
    rc=$?
    set -e
    if (( rc == 0 )); then
      return 0
    fi
    if [[ "$output" == *"Nonce too low"* || "$output" == *"Replacement transaction underpriced"* ]]; then
      sleep 1
      continue
    fi
    printf '%s\n' "$output" >&2
    return "$rc"
  done
  printf '%s\n' "$output" >&2
  return 1
}

wait_for_pool() {
  local base="$1" quote="$2"
  local max_polls poll current
  max_polls=$((POST_CREATE_POLL_SECONDS / POST_CREATE_POLL_INTERVAL))
  (( max_polls < 1 )) && max_polls=1
  for ((poll=0; poll<max_polls; poll++)); do
    current="$(pool_for "$base" "$quote")"
    if [[ -n "$current" && "$current" != "$zero_addr" ]]; then
      printf '%s\n' "$current"
      return 0
    fi
    sleep "$POST_CREATE_POLL_INTERVAL"
  done
  printf '%s\n' "$zero_addr"
  return 1
}

register_pair() {
  local base="$1" quote="$2" pool="$3" label="$4"
  if [[ -z "$pool" || "$pool" == "$zero_addr" ]]; then
    echo "  FAIL register $label -> zero pool address"
    ((failed++)) || true
    return 1
  fi
  if [[ "$DRY_RUN" == "1" ]]; then
    echo "  [DRY] would ensure provider registration for $label -> $pool (both directions)"
    ((registered++)) || true
    return 0
  fi
  if send_tx "$DODO_PMM_PROVIDER_ADDRESS" "registerPool(address,address,address)" "$base" "$quote" "$pool" --gas-limit "$REGISTER_POOL_GAS_LIMIT" \
    && send_tx "$DODO_PMM_PROVIDER_ADDRESS" "registerPool(address,address,address)" "$quote" "$base" "$pool" --gas-limit "$REGISTER_POOL_GAS_LIMIT"; then
    echo "  OK register $label -> $pool"
    ((registered++)) || true
    return 0
  fi
  echo "  FAIL register $label -> $pool"
  ((failed++)) || true
  return 1
}

echo "=== Chain 138 PMM Desired-State Sync ==="
echo "Config:       $CONFIG_JSON"
echo "Integration:  $DODO_PMM_INTEGRATION_ADDRESS"
echo "Provider:     $DODO_PMM_PROVIDER_ADDRESS"
echo "RPC:          $RPC_URL_138"
echo "Dry run:      $DRY_RUN"
echo "Desired pairs:${#DESIRED_PAIRS[@]}"
echo ""

for pair in "${DESIRED_PAIRS[@]}"; do
  IFS='|' read -r base_sym base quote_sym quote <<< "$pair"
  label="${base_sym}/${quote_sym}"
  existing_pool="$(pool_for "$base" "$quote")"
  provider_pool="$(provider_pool_for "$base" "$quote")"
  if [[ -n "$existing_pool" && "$existing_pool" != "$zero_addr" ]]; then
    echo "SKIP create $label (exists: $existing_pool)"
    ((skipped_existing++)) || true
    if [[ -n "$provider_pool" && "${provider_pool,,}" == "${existing_pool,,}" ]]; then
      echo "  OK provider already registered for $label -> $existing_pool"
      ((registered++)) || true
    else
      register_pair "$base" "$quote" "$existing_pool" "$label" || true
    fi
    continue
  fi

  if [[ -n "$provider_pool" && "$provider_pool" != "$zero_addr" ]]; then
    echo "BLOCKER create $label (provider already points to existing pool $provider_pool, but integration has no pool record)"
    echo "  Repair requires importing the existing pool into DODOPMMIntegration with importExistingPool(...)."
    ((failed++)) || true
    continue
  fi

  if [[ "$DRY_RUN" == "1" ]]; then
    echo "[DRY] would create $label"
    ((created++)) || true
    continue
  fi

  if send_tx "$DODO_PMM_INTEGRATION_ADDRESS" "createPool(address,address,uint256,uint256,uint256,bool)" \
      "$base" "$quote" "$LP_FEE" "$INITIAL_PRICE" "$K_FACTOR" "$ENABLE_TWAP" --gas-limit "$CREATE_POOL_GAS_LIMIT"; then
    new_pool="$(wait_for_pool "$base" "$quote")"
    if [[ -z "$new_pool" || "$new_pool" == "$zero_addr" ]]; then
      echo "FAIL create $label (tx confirmed but integration still reports zero pool address)"
      ((failed++)) || true
      continue
    fi
    echo "OK create $label -> $new_pool"
    ((created++)) || true
    register_pair "$base" "$quote" "$new_pool" "$label" || true
  else
    echo "FAIL create $label"
    ((failed++)) || true
  fi
done

echo ""
echo "Summary:"
echo "  Created:    $created"
echo "  Registered: $registered"
echo "  Existing:   $skipped_existing"
echo "  Failed:     $failed"
