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

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
PROJECT_ROOT="$(cd "$REPO_ROOT/.." && pwd)"
BUNDLE_JSON="$REPO_ROOT/config/gas-pmm-execution-bundle.json"
OUT_DIR="$PROJECT_ROOT/reports/status"
OUT_JSON="$OUT_DIR/gas-pmm-execution-bundle-latest.json"
OUT_MD="$OUT_DIR/gas-pmm-execution-bundle-latest.md"

source "$REPO_ROOT/scripts/lib/deployment/dotenv.sh"
load_deployment_env --repo-root "$REPO_ROOT"

mkdir -p "$OUT_DIR"

json_escape() {
  jq -Rn --arg v "${1:-}" '$v'
}

resolve_env_from_list() {
  local joined="${1:-}"
  local value=""
  local key
  [[ -z "$joined" ]] && return 0
  IFS='|' read -r -a keys <<< "$joined"
  for key in "${keys[@]}"; do
    if [[ -n "${!key:-}" ]]; then
      value="${!key}"
      break
    fi
  done
  printf '%s' "$value"
}

hex_to_addr() {
  local value="${1#0x}"
  [[ ${#value} -ge 40 ]] || return 1
  printf '0x%s\n' "${value: -40}"
}

code_status() {
  local rpc="$1"
  local address="$2"
  if [[ -z "$rpc" || -z "$address" ]]; then
    printf 'missing'
    return
  fi
  local code=""
  code="$(timeout 12s cast code --rpc-url "$rpc" "$address" 2>/dev/null || true)"
  if [[ -n "$code" && "$code" != "0x" ]]; then
    printf 'has_code'
  else
    printf 'no_code'
  fi
}

symbol_call() {
  local rpc="$1"
  local address="$2"
  local value
  value="$(timeout 8s cast call --rpc-url "$rpc" "$address" "symbol()(string)" 2>/dev/null || true)"
  value="${value#\"}"
  value="${value%\"}"
  printf '%s' "$value"
}

normalize_key() {
  printf '%s' "$1" | tr '[:lower:]- ' '[:upper:]__'
}

append_finding() {
  local finding="$1"
  if [[ -n "$FINDINGS_JOINED" ]]; then
    FINDINGS_JOINED+="|$finding"
  else
    FINDINGS_JOINED="$finding"
  fi
}

emit_findings_json() {
  local joined="${1:-}"
  if [[ -z "$joined" ]]; then
    printf '[]'
    return
  fi
  jq -Rn --arg joined "$joined" '$joined | split("|") | map(select(length > 0))'
}

rollout_order_json="$(jq -c '[.chains[] | {chainId, network}]' "$BUNDLE_JSON")"
generated_at="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"

json_file="$(mktemp)"
md_file="$(mktemp)"

{
  echo "{"
  echo "  \"generatedAt\": $(json_escape "$generated_at"),"
  echo "  \"bundle\": $(jq '.bundleName' "$BUNDLE_JSON"),"
  echo "  \"description\": $(jq '.description' "$BUNDLE_JSON"),"
  echo "  \"poolDefaults\": $(jq '.poolDefaults' "$BUNDLE_JSON"),"
  echo "  \"rolloutOrder\": $rollout_order_json,"
  echo "  \"chains\": ["
} >"$json_file"

{
  echo "# Gas PMM Execution Bundle"
  echo
  echo "Generated at: \`$generated_at\`"
  echo
  echo "This bundle covers the remaining \`22\` planned gas-family DODO PMM rows across \`11\` public chains."
  echo
  echo "Execution posture:"
  echo
  echo "- Each chain has two target pools: wrapped-native self-quote and wrapped-native versus stable."
  echo "- The current expected pool addresses are still scaffold slots, so \`no_code\` is the normal pre-deploy state."
  echo "- Stable-quote pool creation needs a fresh \`STABLE_PRICE_1E18\` input at execution time."
  echo "- Wrapped-native quote defaults in this bundle use the repo's canonical or documented live contracts instead of the old \`0xaa...\` placeholders."
  echo "- The deploy step reuses the legacy integration constructor slots; those seed addresses are only deployment anchors, while the gas pairs themselves are created through generic \`createPool(...)\` calls."
} >"$md_file"

first_chain=1
chain_count=0
ready_count=0
blocked_count=0

while IFS= read -r chain_row; do
  chain_id="$(jq -r '.chainId' <<<"$chain_row")"
  network="$(jq -r '.network' <<<"$chain_row")"
  chain_key="$(jq -r '.chainKey' <<<"$chain_row")"
  rpc_envs_joined="$(jq -r '.rpcEnv | join("|")' <<<"$chain_row")"
  integration_env="$(jq -r '.integrationEnv' <<<"$chain_row")"
  dvm_envs_joined="$(jq -r '.dodoVendingMachineEnv | join("|")' <<<"$chain_row")"

  rpc="$(resolve_env_from_list "$rpc_envs_joined")"
  integration="${!integration_env:-}"
  dvm="$(resolve_env_from_list "$dvm_envs_joined")"

  base_symbol="$(jq -r '.baseToken.symbol' <<<"$chain_row")"
  base_address="$(jq -r '.baseToken.address' <<<"$chain_row")"

  wrapped_symbol="$(jq -r '.wrappedNativeQuote.symbol' <<<"$chain_row")"
  wrapped_envs_joined="$(jq -r '.wrappedNativeQuote.env | join("|")' <<<"$chain_row")"
  wrapped_default="$(jq -r '.wrappedNativeQuote.default' <<<"$chain_row")"
  wrapped_note="$(jq -r '.wrappedNativeQuote.note' <<<"$chain_row")"
  wrapped_address="$(resolve_env_from_list "$wrapped_envs_joined")"
  wrapped_address="${wrapped_address:-$wrapped_default}"

  stable_symbol="$(jq -r '.stableQuote.symbol' <<<"$chain_row")"
  stable_envs_joined="$(jq -r '.stableQuote.env | join("|")' <<<"$chain_row")"
  stable_default="$(jq -r '.stableQuote.default' <<<"$chain_row")"
  stable_note="$(jq -r '.stableQuote.note' <<<"$chain_row")"
  stable_address="$(resolve_env_from_list "$stable_envs_joined")"
  stable_address="${stable_address:-$stable_default}"

  integration_status="$(code_status "$rpc" "$integration")"
  dvm_status="$(code_status "$rpc" "$dvm")"
  base_status="$(code_status "$rpc" "$base_address")"
  wrapped_status="$(code_status "$rpc" "$wrapped_address")"
  stable_status="$(code_status "$rpc" "$stable_address")"

  wrapped_pair_row="$(jq -c '.pairs[] | select(.quoteSymbol == $quote)' --arg quote "$wrapped_symbol" <<<"$chain_row")"
  stable_pair_row="$(jq -c '.pairs[] | select(.quoteSymbol == $quote)' --arg quote "$stable_symbol" <<<"$chain_row")"
  wrapped_pair_name="$(jq -r '.pair' <<<"$wrapped_pair_row")"
  stable_pair_name="$(jq -r '.pair' <<<"$stable_pair_row")"
  wrapped_pool_expected="$(jq -r '.expectedPoolAddress' <<<"$wrapped_pair_row")"
  stable_pool_expected="$(jq -r '.expectedPoolAddress' <<<"$stable_pair_row")"
  wrapped_pool_status="$(code_status "$rpc" "$wrapped_pool_expected")"
  stable_pool_status="$(code_status "$rpc" "$stable_pool_expected")"

  FINDINGS_JOINED=""
  [[ -z "$rpc" ]] && append_finding "missing_rpc"
  [[ "$dvm_status" != "has_code" ]] && append_finding "missing_or_invalid_dodo_vending_machine"
  [[ "$base_status" != "has_code" ]] && append_finding "gas_mirror_base_missing_or_no_code"
  [[ "$wrapped_status" != "has_code" ]] && append_finding "wrapped_native_quote_missing_or_no_code"
  [[ "$stable_status" != "has_code" ]] && append_finding "stable_quote_missing_or_no_code"
  if [[ -n "$integration" && "$integration_status" == "no_code" ]]; then
    append_finding "integration_env_set_but_no_code"
  fi
  if [[ -z "$integration" || "$integration_status" != "has_code" ]]; then
    append_finding "integration_needs_deploy"
  fi
  [[ "$wrapped_pool_status" != "has_code" ]] && append_finding "wrapped_native_pool_not_live"
  [[ "$stable_pool_status" != "has_code" ]] && append_finding "stable_quote_pool_not_live"

  readiness="blocked"
  if [[ -n "$rpc" && "$dvm_status" == "has_code" && "$base_status" == "has_code" && "$wrapped_status" == "has_code" && "$stable_status" == "has_code" ]]; then
    readiness="ready_for_execution"
  fi
  if [[ "$readiness" == "ready_for_execution" ]]; then
    ready_count=$((ready_count + 1))
  else
    blocked_count=$((blocked_count + 1))
  fi
  chain_count=$((chain_count + 1))

  normalized_chain_key="$(normalize_key "$chain_key")"
  forge_profile="default"
  if [[ "$chain_id" == "25" ]]; then
    forge_profile="cronos_legacy"
  fi
  dvm_primary_env="$(jq -r '.dodoVendingMachineEnv[0]' <<<"$chain_row")"

  deploy_cmd=$(cat <<EOF
cd $REPO_ROOT
DODO_VENDING_MACHINE_ADDRESS=\${$dvm_primary_env:-$dvm} \\
OFFICIAL_USDT_ADDRESS=$stable_address \\
OFFICIAL_USDC_ADDRESS=$wrapped_address \\
COMPLIANT_USDT_ADDRESS=$base_address \\
COMPLIANT_USDC_ADDRESS=$base_address \\
FOUNDRY_PROFILE=$forge_profile \\
forge script script/dex/DeployDODOPMMIntegration.s.sol:DeployDODOPMMIntegration \\
  --rpc-url $rpc \\
  --chain-id $chain_id \\
  --broadcast \\
  --private-key "\$PRIVATE_KEY" \\
  -vvv
jq -r '.transactions[] | select(.transactionType=="CREATE" and .contractName=="DODOPMMIntegration") | .contractAddress' \\
  broadcast/DeployDODOPMMIntegration.s.sol/$chain_id/run-latest.json
EOF
)

  create_cmd=$(cat <<EOF
cd $REPO_ROOT
INTEGRATION_ADDRESS=\${$integration_env:-REPLACE_WITH_DEPLOYED_INTEGRATION}
LP_FEE_RATE=\${LP_FEE_RATE:-3}
SELF_QUOTE_PRICE_1E18=1000000000000000000
STABLE_PRICE_1E18=\${STABLE_PRICE_1E18:-REPLACE_WITH_LIVE_${normalized_chain_key}_GAS_PRICE_1E18}
K_FACTOR=\${K_FACTOR:-500000000000000000}
ENABLE_TWAP=\${ENABLE_TWAP:-true}

cast send "\$INTEGRATION_ADDRESS" \\
  "createPool(address,address,uint256,uint256,uint256,bool)" \\
  $base_address \\
  $wrapped_address \\
  "\$LP_FEE_RATE" \\
  "\$SELF_QUOTE_PRICE_1E18" \\
  "\$K_FACTOR" \\
  "\$ENABLE_TWAP" \\
  --rpc-url $rpc \\
  --private-key "\$PRIVATE_KEY" \\
  --legacy \\
  -vv

cast send "\$INTEGRATION_ADDRESS" \\
  "createPool(address,address,uint256,uint256,uint256,bool)" \\
  $base_address \\
  $stable_address \\
  "\$LP_FEE_RATE" \\
  "\$STABLE_PRICE_1E18" \\
  "\$K_FACTOR" \\
  "\$ENABLE_TWAP" \\
  --rpc-url $rpc \\
  --private-key "\$PRIVATE_KEY" \\
  --legacy \\
  -vv
EOF
)

  verify_cmd=$(cat <<EOF
cast code --rpc-url $rpc $wrapped_pool_expected
cast code --rpc-url $rpc $stable_pool_expected
cast call --rpc-url $rpc \${$integration_env:-REPLACE_WITH_DEPLOYED_INTEGRATION} 'pools(address,address)(address)' $base_address $wrapped_address
cast call --rpc-url $rpc \${$integration_env:-REPLACE_WITH_DEPLOYED_INTEGRATION} 'pools(address,address)(address)' $base_address $stable_address
EOF
)

  if [[ $first_chain -eq 0 ]]; then
    echo "," >>"$json_file"
  fi
  first_chain=0

  cat >>"$json_file" <<EOF
    {
      "chainId": $chain_id,
      "network": $(json_escape "$network"),
      "chainKey": $(json_escape "$chain_key"),
      "rpc": $(json_escape "$rpc"),
      "readiness": $(json_escape "$readiness"),
      "blockingFindings": $(emit_findings_json "$FINDINGS_JOINED"),
      "integrationEnv": $(json_escape "$integration_env"),
      "integrationAddress": $(json_escape "$integration"),
      "integrationStatus": $(json_escape "$integration_status"),
      "dodoVendingMachine": {
        "envCandidates": $(jq '.dodoVendingMachineEnv' <<<"$chain_row"),
        "address": $(json_escape "$dvm"),
        "status": $(json_escape "$dvm_status")
      },
      "baseToken": {
        "symbol": $(json_escape "$base_symbol"),
        "address": $(json_escape "$base_address"),
        "status": $(json_escape "$base_status"),
        "symbolOnChain": $(json_escape "$(symbol_call "$rpc" "$base_address")")
      },
      "wrappedNativeQuote": {
        "symbol": $(json_escape "$wrapped_symbol"),
        "envCandidates": $(jq '.wrappedNativeQuote.env' <<<"$chain_row"),
        "address": $(json_escape "$wrapped_address"),
        "default": $(json_escape "$wrapped_default"),
        "status": $(json_escape "$wrapped_status"),
        "symbolOnChain": $(json_escape "$(symbol_call "$rpc" "$wrapped_address")"),
        "note": $(json_escape "$wrapped_note")
      },
      "stableQuote": {
        "symbol": $(json_escape "$stable_symbol"),
        "envCandidates": $(jq '.stableQuote.env' <<<"$chain_row"),
        "address": $(json_escape "$stable_address"),
        "default": $(json_escape "$stable_default"),
        "status": $(json_escape "$stable_status"),
        "symbolOnChain": $(json_escape "$(symbol_call "$rpc" "$stable_address")"),
        "note": $(json_escape "$stable_note")
      },
      "pairs": [
        {
          "pair": $(json_escape "$wrapped_pair_name"),
          "expectedPoolAddress": $(json_escape "$wrapped_pool_expected"),
          "poolCodeStatus": $(json_escape "$wrapped_pool_status"),
          "executionPriceMode": "self_quote_fixed_1e18"
        },
        {
          "pair": $(json_escape "$stable_pair_name"),
          "expectedPoolAddress": $(json_escape "$stable_pool_expected"),
          "poolCodeStatus": $(json_escape "$stable_pool_status"),
          "executionPriceMode": "live_stable_spot_required"
        }
      ],
      "commands": {
        "deployIntegration": $(json_escape "$deploy_cmd"),
        "createPools": $(json_escape "$create_cmd"),
        "verifyPools": $(json_escape "$verify_cmd")
      }
    }
EOF

  {
    echo
    echo "## $network ($chain_id)"
    echo
    echo "Readiness: \`$readiness\`"
    echo
    echo "| Item | Address | Status |"
    echo "| --- | --- | --- |"
    echo "| DODO vending machine | \`${dvm:-unset}\` | \`$dvm_status\` |"
    echo "| Integration env \`$integration_env\` | \`${integration:-unset}\` | \`$integration_status\` |"
    echo "| $base_symbol | \`$base_address\` | \`$base_status\` |"
    echo "| $wrapped_symbol | \`$wrapped_address\` | \`$wrapped_status\` |"
    echo "| $stable_symbol | \`$stable_address\` | \`$stable_status\` |"
    echo "| Pool $wrapped_pair_name | \`$wrapped_pool_expected\` | \`$wrapped_pool_status\` |"
    echo "| Pool $stable_pair_name | \`$stable_pool_expected\` | \`$stable_pool_status\` |"
    echo
    echo "Blocking findings:"
    if [[ -n "$FINDINGS_JOINED" ]]; then
      IFS='|' read -r -a findings_array <<< "$FINDINGS_JOINED"
      for finding in "${findings_array[@]}"; do
        echo "- \`$finding\`"
      done
    else
      echo "- None"
    fi
    echo
    echo "Quote token notes:"
    echo
    echo "- $wrapped_symbol: $wrapped_note"
    echo "- $stable_symbol: $stable_note"
    echo
    echo "Deploy integration:"
    echo
    echo '```bash'
    echo "$deploy_cmd"
    echo '```'
    echo
    echo "Create pools:"
    echo
    echo '```bash'
    echo "$create_cmd"
    echo '```'
    echo
    echo "Verify pools:"
    echo
    echo '```bash'
    echo "$verify_cmd"
    echo '```'
  } >>"$md_file"
done < <(jq -c '.chains[]' "$BUNDLE_JSON")

{
  echo
  echo "  ],"
  echo "  \"summary\": {"
  echo "    \"chains\": $chain_count,"
  echo "    \"pairs\": $((chain_count * 2)),"
  echo "    \"readyForExecution\": $ready_count,"
  echo "    \"blocked\": $blocked_count"
  echo "  }"
  echo "}"
} >>"$json_file"

jq . "$json_file" >"$OUT_JSON"
mv "$md_file" "$OUT_MD"
rm -f "$json_file"

echo "Wrote:"
echo "  $OUT_JSON"
echo "  $OUT_MD"
