#!/usr/bin/env bash
# Deploy official DODO DVM (DVMFactory + deps) to Chain 138 via DODOEX/contractV2 Truffle,
# then deploy DVMFactoryAdapter (createDVM -> createDODOVendingMachine) via Forge and update .env.
# Requires: smom-dbis-138/.env with PRIVATE_KEY, RPC_URL_138
#
# Notes:
# - The vendored DODO V2 tree contains both Solidity 0.6.9 and 0.8.x sources.
#   Truffle uses a single configured compiler, so this script temporarily hides the
#   unrelated 0.8.x contracts during compile/migrate, then restores them on exit.
# - Use --compile-only to verify the official DVM stack compiles cleanly before broadcast.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
DODO_DIR="$PROJECT_ROOT/lib/dodo-contractV2"
COMPILE_ONLY=false
TRUFFLE_RESET=false
HIDDEN_ROOT="$DODO_DIR/.chain138-dvm-solc-excludes"
declare -a HIDDEN_SOL_FILES=()

usage() {
  cat <<'EOF'
Usage: deploy-official-dvm-chain138.sh [--compile-only] [--reset]

Options:
  --compile-only   Compile the official DODO V2 DVM stack in DVM-only mode, then exit.
  --reset          Pass --reset to truffle migrate.
EOF
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --compile-only)
      COMPILE_ONLY=true
      shift
      ;;
    --reset)
      TRUFFLE_RESET=true
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "Unknown argument: $1" >&2
      usage >&2
      exit 1
      ;;
  esac
done

prepare_dvm_only_sources() {
  local rel_path
  rm -rf "$HIDDEN_ROOT"
  mkdir -p "$HIDDEN_ROOT"

  while IFS= read -r rel_path; do
    [[ -z "$rel_path" ]] && continue
    mkdir -p "$HIDDEN_ROOT/$(dirname "$rel_path")"
    mv "$DODO_DIR/$rel_path" "$HIDDEN_ROOT/$rel_path"
    HIDDEN_SOL_FILES+=("$rel_path")
  done < <(
    cd "$DODO_DIR" &&
      find contracts -type f -name '*.sol' -print0 |
      xargs -0 grep -El 'pragma solidity (\^?0\.8|>=0\.8)' |
      sort
  )

  if [[ ${#HIDDEN_SOL_FILES[@]} -gt 0 ]]; then
    echo "Temporarily hiding ${#HIDDEN_SOL_FILES[@]} Solidity 0.8.x sources for Chain 138 DVM-only compile..."
  fi
}

restore_hidden_sources() {
  local rel_path
  if [[ -d "$HIDDEN_ROOT" ]]; then
    while IFS= read -r rel_path; do
      [[ -z "$rel_path" ]] && continue
      mkdir -p "$DODO_DIR/$(dirname "$rel_path")"
      mv "$HIDDEN_ROOT/$rel_path" "$DODO_DIR/$rel_path"
    done < <(cd "$HIDDEN_ROOT" && find contracts -type f -name '*.sol' | sort)
    rm -rf "$HIDDEN_ROOT"
  fi
}

trap restore_hidden_sources EXIT

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

if [[ ! -f .env ]]; then
  echo "ERROR: .env not found" >&2
  exit 1
fi
set -a
source .env
set +a

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

# Ensure DODO submodule has deps and compiles
if [[ ! -d "$DODO_DIR/node_modules" ]]; then
  echo "Installing DODO contractV2 dependencies..."
  (cd "$DODO_DIR" && npm install)
fi

# Export for Truffle (privKey without 0x for HDWalletProvider if needed)
export privKey="${PRIVATE_KEY#0x}"
export RPC_URL_138
export GAS_PRICE_138="${GAS_PRICE_138:-1000000000}"

prepare_dvm_only_sources

echo "=== Compiling official DODO V2 DVM-only subset for Chain 138 ==="
(cd "$DODO_DIR" && rm -rf build/contracts && npx truffle compile)

if [[ "$COMPILE_ONLY" == "true" ]]; then
  echo "DODO V2 DVM-only compile completed successfully."
  exit 0
fi

TRUFFLE_RESET_ARGS=()
if [[ "$TRUFFLE_RESET" == "true" ]]; then
  TRUFFLE_RESET_ARGS+=(--reset)
fi

# Deploy Migrations (required for Truffle), then DVM stack only
echo "=== Running Truffle migration 1 (Migrations) on Chain 138 ==="
(cd "$DODO_DIR" && npx truffle migrate -f 1 --to 1 --network chain138 "${TRUFFLE_RESET_ARGS[@]}") || true

echo "=== Running Truffle migration 9 (DVM stack) on Chain 138 ==="
(cd "$DODO_DIR" && npx truffle migrate -f 9 --to 9 --network chain138 "${TRUFFLE_RESET_ARGS[@]}")

# Parse DVMFactory address from Truffle build (network id 138 as string or number)
DVM_FACTORY_ADDRESS=$(cd "$DODO_DIR" && node -e "
const fs = require('fs');
const path = require('path');
const buildPath = path.join(__dirname, 'build', 'contracts', 'DVMFactory.json');
if (!fs.existsSync(buildPath)) process.exit(1);
const j = JSON.parse(fs.readFileSync(buildPath, 'utf8'));
const n = j.networks || {};
const addr = n['138']?.address || n[138]?.address;
if (!addr) process.exit(1);
console.log(addr);
" 2>/dev/null) || true
if [[ -z "$DVM_FACTORY_ADDRESS" ]]; then
  echo "Could not read DVMFactory from build. If you already deployed, set DODO_DVM_FACTORY and run:" >&2
  echo "  DODO_DVM_FACTORY=<dvm_factory_address> forge script script/dex/DeployDVMFactoryAdapter.s.sol:DeployDVMFactoryAdapter --rpc-url \$RPC_URL_138 --broadcast --private-key \$PRIVATE_KEY --legacy" >&2
  exit 1
fi

echo "DVMFactory deployed at: $DVM_FACTORY_ADDRESS"
echo "=== Deploying DVMFactoryAdapter (createDVM wrapper) via Forge ==="
export DODO_DVM_FACTORY="$DVM_FACTORY_ADDRESS"
forge script script/dex/DeployDVMFactoryAdapter.s.sol:DeployDVMFactoryAdapter \
  --rpc-url "$RPC_URL_138" --broadcast --private-key "$PRIVATE_KEY" --legacy

# Extract adapter address from broadcast (or script output)
ADAPTER_BROADCAST="$PROJECT_ROOT/broadcast/DeployDVMFactoryAdapter.s.sol/138/run-latest.json"
ADAPTER_ADDRESS=$(
  node -e "
const fs = require('fs');
const path = process.argv[1];
if (!fs.existsSync(path)) process.exit(1);
const j = JSON.parse(fs.readFileSync(path, 'utf8'));
const tx = (j.transactions || []).find((entry) => entry.contractName === 'DVMFactoryAdapter' && entry.contractAddress);
if (!tx) process.exit(1);
console.log(tx.contractAddress);
" "$ADAPTER_BROADCAST" 2>/dev/null
) || true
if [[ -z "$ADAPTER_ADDRESS" ]]; then
  echo "Set DODO_VENDING_MACHINE_ADDRESS to the DVMFactoryAdapter address printed above."
  exit 0
fi

echo "DVMFactoryAdapter at: $ADAPTER_ADDRESS"
echo "Updating .env DODO_VENDING_MACHINE_ADDRESS=$ADAPTER_ADDRESS"
if grep -q '^DODO_VENDING_MACHINE_ADDRESS=' .env; then
  sed -i "s|^DODO_VENDING_MACHINE_ADDRESS=.*|DODO_VENDING_MACHINE_ADDRESS=$ADAPTER_ADDRESS|" .env
else
  echo "DODO_VENDING_MACHINE_ADDRESS=$ADAPTER_ADDRESS" >> .env
fi
echo "Done. Run scripts/deployment/run-pmm-and-pools.sh to deploy DODOPMMIntegration with the official DVM."
