#!/usr/bin/env bash
# Lightweight bootstrap for red-team / evaluator use.
# Starts only Anvil + deploys contracts. No ponder, no webapp, no txnbot.
#
# Environment overrides:
#   CANDIDATE   Path to a .push3 file. When set, the push3-transpiler is
#               invoked to regenerate OptimizerV3Push3Lib.sol, then the
#               deployed Optimizer UUPS proxy is upgraded to OptimizerV3
#               (which delegates to the regenerated lib).
#   RPC_URL     Anvil RPC endpoint (default: http://localhost:8545)
set -euo pipefail

REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
ONCHAIN_DIR="$REPO_ROOT/onchain"
RPC_URL="${RPC_URL:-http://localhost:8545}"
CAST="$HOME/.foundry/bin/cast"
FORGE="$HOME/.foundry/bin/forge"
CANDIDATE="${CANDIDATE:-}"

log() { echo "[bootstrap-light] $*"; }
die() { log "ERROR: $*" >&2; exit 1; }

# 1. Start Anvil (docker)
log "Starting Anvil..."
cd "$REPO_ROOT"
sudo docker compose down -v 2>/dev/null || true
sudo docker compose up -d anvil
for i in $(seq 1 30); do
  $CAST chain-id --rpc-url "$RPC_URL" 2>/dev/null && break
  sleep 1
done
$CAST chain-id --rpc-url "$RPC_URL" >/dev/null 2>&1 || die "Anvil not responding"
log "Anvil running"

# 2. Clear ERC-4337 code from well-known addresses (fork safety)
DEPLOYER=$($CAST wallet address --mnemonic "test test test test test test test test test test test junk" 2>/dev/null)
log "Clearing code from deployer ($DEPLOYER) + feeDest"
$CAST rpc --rpc-url "$RPC_URL" anvil_setCode "$DEPLOYER" "0x" 2>/dev/null || true
$CAST rpc --rpc-url "$RPC_URL" anvil_setCode "0xf6a3eef9088A255c32b6aD2025f83E57291D9011" "0x" 2>/dev/null || true

# 3. Push3 candidate injection (optional)
#    When CANDIDATE is set, transpile the .push3 file into OptimizerV3Push3.sol,
#    then regenerate OptimizerV3Push3Lib.sol so that OptimizerV3 (which delegates
#    to the lib) will use the candidate logic after the proxy upgrade in step 6.
if [[ -n "$CANDIDATE" ]]; then
  [[ -f "$CANDIDATE" ]] || die "CANDIDATE file not found: $CANDIDATE"
  log "Transpiling candidate: $CANDIDATE"

  TRANSPILER_DIR="$REPO_ROOT/tools/push3-transpiler"
  TRANSPILER_OUT="$ONCHAIN_DIR/src/OptimizerV3Push3.sol"

  # Ensure transpiler deps are installed
  if [[ ! -d "$TRANSPILER_DIR/node_modules" ]]; then
    (cd "$TRANSPILER_DIR" && npm install --silent) || die "transpiler npm install failed"
  fi

  # Transpile Push3 → standalone OptimizerV3Push3.sol
  (cd "$TRANSPILER_DIR" && npx tsx src/index.ts "$CANDIDATE" "$TRANSPILER_OUT") \
    || die "push3-transpiler failed"

  # Regenerate OptimizerV3Push3Lib.sol from the transpiler output.
  # Extracts the calculateParams function body and wraps it in a library.
  python3 - "$TRANSPILER_OUT" "$ONCHAIN_DIR/src/OptimizerV3Push3Lib.sol" <<'PYEOF' || die "lib generation failed"
import sys

with open(sys.argv[1]) as f:
    push3 = f.read()

# Extract function body (everything between the first { after calculateParams and its closing })
fn_start = push3.find("function calculateParams")
if fn_start == -1:
    sys.exit("calculateParams not found in transpiler output")
brace_start = push3.find("{", fn_start)
sig_end = push3.index("\n", brace_start) + 1

lines = push3[sig_end:].split("\n")
body_lines = []
depth = 1
for line in lines:
    depth += line.count("{") - line.count("}")
    if depth <= 0:
        break
    body_lines.append(line)
else:
    sys.exit("closing brace not found")

body = "\n".join(body_lines)

lib = f"""// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.19;

import {{OptimizerInput}} from "./IOptimizer.sol";

/**
 * @title OptimizerV3Push3Lib
 * @notice Shared library containing the canonical Push3 transpiler output for
 *         OptimizerV3 parameter calculation.  Used by both OptimizerV3Push3
 *         (standalone) and OptimizerV3 (UUPS-upgradeable Optimizer) so that
 *         future transpiler changes require only one edit.
 * @dev    Auto-regenerated by bootstrap-light.sh from CANDIDATE env var.
 */
library OptimizerV3Push3Lib {{
    function calculateParams(OptimizerInput[8] memory inputs)
        internal
        pure
        returns (uint256 ci, uint256 anchorShare, uint24 anchorWidth, uint256 discoveryDepth)
    {{
{body}
    }}
}}
"""
with open(sys.argv[2], "w") as f:
    f.write(lib)
PYEOF

  log "OptimizerV3Push3Lib.sol regenerated from candidate"
fi

# 4. Deploy contracts — capture output for addresses
log "Deploying contracts..."
cd "$ONCHAIN_DIR"
# Fix ownership of forge artifacts (docker creates root-owned files)
sudo chown -R "$(id -u):$(id -g)" cache out broadcast 2>/dev/null || true
rm -f deployments-local.json  # force fresh
DEPLOY_OUT=$($FORGE script script/DeployLocal.sol --rpc-url "$RPC_URL" --broadcast 2>&1)
echo "$DEPLOY_OUT" | grep -E "^\[|deployed|complete|Summary" || true

# 5. Extract addresses from output and write deployments-local.json
KRK=$(echo "$DEPLOY_OUT" | grep -oP 'Kraiken deployed: \K0x[a-fA-F0-9]+')
[[ -n "$KRK" ]] || die "Could not extract Kraiken address from deploy output"
STAKE=$(echo "$DEPLOY_OUT" | grep -oP 'Stake deployed: \K0x[a-fA-F0-9]+')
[[ -n "$STAKE" ]] || die "Could not extract Stake address from deploy output"
OPT=$(echo "$DEPLOY_OUT" | grep -oP 'Optimizer deployed: \K0x[a-fA-F0-9]+')
[[ -n "$OPT" ]] || die "Could not extract Optimizer address from deploy output"
LM=$(echo "$DEPLOY_OUT" | grep -oP 'LiquidityManager deployed: \K0x[a-fA-F0-9]+')

[[ -n "$LM" ]] || die "Could not extract LiquidityManager address from deploy output"

POOL=$(echo "$DEPLOY_OUT" | grep -oP 'Pool: \K0x[a-fA-F0-9]+' | head -1)
[[ -n "$POOL" ]] || die "Could not extract Pool address from deploy output"

# Base Sepolia Uniswap V3 Factory — must match v3Factory constant in DeployLocal.sol
V3_FACTORY="0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24"

WETH=0x4200000000000000000000000000000000000006

cat > "$ONCHAIN_DIR/deployments-local.json" << EOF
{
  "contracts": {
    "Kraiken": "$KRK",
    "Stake": "$STAKE",
    "LiquidityManager": "$LM",
    "OptimizerProxy": "$OPT",
    "Pool": "$POOL",
    "V3Factory": "$V3_FACTORY"
  },
  "infrastructure": {
    "weth": "$WETH"
  }
}
EOF

# 6. Upgrade Optimizer proxy to OptimizerV3 (candidate injection)
#    DeployLocal deploys Optimizer (v1) behind a UUPS proxy.  When a Push3
#    candidate was transpiled in step 3, we deploy a fresh OptimizerV3
#    implementation (which delegates to the regenerated OptimizerV3Push3Lib)
#    and upgrade the proxy so the candidate logic is live on-chain.
if [[ -n "$CANDIDATE" ]]; then
  log "Upgrading Optimizer proxy to OptimizerV3 (candidate: $(basename "$CANDIDATE" .push3))..."
  # Deployer PK — Anvil account 0 (same key DeployLocal.sol uses via .secret.local)
  DEPLOYER_PK=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

  # Deploy OptimizerV3 implementation
  V3_DEPLOY_OUT=$($FORGE create --rpc-url "$RPC_URL" --private-key "$DEPLOYER_PK" \
    src/OptimizerV3.sol:OptimizerV3 2>&1) \
    || die "OptimizerV3 deployment failed: $V3_DEPLOY_OUT"
  V3_IMPL=$(echo "$V3_DEPLOY_OUT" | grep -oP 'Deployed to: \K0x[a-fA-F0-9]+')
  [[ -n "$V3_IMPL" ]] || die "Could not extract OptimizerV3 address from forge create output"
  log "OptimizerV3 implementation: $V3_IMPL"

  # Upgrade the UUPS proxy
  $CAST send --rpc-url "$RPC_URL" --private-key "$DEPLOYER_PK" \
    "$OPT" "upgradeTo(address)" "$V3_IMPL" >/dev/null 2>&1 \
    || die "upgradeTo failed"
  log "Proxy upgraded to OptimizerV3"

  # Verify the upgrade by calling getLiquidityParams through the proxy
  VERIFY_OUT=$($CAST call --rpc-url "$RPC_URL" "$OPT" \
    "getLiquidityParams()(uint256,uint256,uint24,uint256)" 2>/dev/null) || true
  log "Post-upgrade getLiquidityParams: $VERIFY_OUT"
fi

# 7. Verify
VWAP=$($CAST call --rpc-url "$RPC_URL" "$LM" "cumulativeVolume()(uint256)" 2>/dev/null || echo "0")
log "LiquidityManager: $LM"
log "cumulativeVolume: $VWAP"
[[ "$VWAP" != "0" ]] && log "✅ Bootstrap complete — VWAP active" || log "⚠️ VWAP not bootstrapped"
