#!/usr/bin/env bash
# run-protocol.sh — On-chain protocol health snapshot.
#
# Collects TVL, accumulated fees, position count, and rebalance frequency
# from the deployed LiquidityManager.  Writes evidence/protocol/YYYY-MM-DD.json.
#
# Exit codes:
#   0  snapshot written successfully
#   2  infrastructure error (RPC unreachable, missing deployments, forge unavailable)
#
# Environment:
#   RPC_URL              Base network RPC endpoint (required)
#   DEPLOYMENTS_FILE     path to deployments JSON (default: onchain/deployments-local.json)
#   LOOKBACK_BLOCKS      blocks to scan for Recentered events (default: 7200, ~24 h on Base)

set -euo pipefail

CAST="${CAST:-/home/debian/.foundry/bin/cast}"
FORGE="${FORGE:-/home/debian/.foundry/bin/forge}"
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
DATE="$(date -u +%Y-%m-%d)"
OUT_DIR="$REPO_ROOT/evidence/protocol"
OUT_FILE="$OUT_DIR/$DATE.json"

RPC_URL="${RPC_URL:?RPC_URL is required}"
DEPLOYMENTS_FILE="${DEPLOYMENTS_FILE:-onchain/deployments-local.json}"
LOOKBACK_BLOCKS="${LOOKBACK_BLOCKS:-7200}"

# Resolve relative deployments path against repo root
if [[ "$DEPLOYMENTS_FILE" != /* ]]; then
    DEPLOYMENTS_FILE="$REPO_ROOT/$DEPLOYMENTS_FILE"
fi

die() { echo "ERROR: $*" >&2; exit 2; }

mkdir -p "$OUT_DIR"

# ── read-addresses ────────────────────────────────────────────────────────────

[[ -f "$DEPLOYMENTS_FILE" ]] || die "Deployments file not found: $DEPLOYMENTS_FILE"

LM=$(jq -r '.contracts.LiquidityManager' "$DEPLOYMENTS_FILE")
POOL=$(jq -r '.contracts.Pool'            "$DEPLOYMENTS_FILE")
WETH=0x4200000000000000000000000000000000000006

[[ -n "$LM" && "$LM" != "null" ]]   || die "LiquidityManager address missing from $DEPLOYMENTS_FILE"
[[ -n "$POOL" && "$POOL" != "null" ]] || die "Pool address missing from $DEPLOYMENTS_FILE"

# ── collect block number ──────────────────────────────────────────────────────

block_number=$("$CAST" block-number --rpc-url "$RPC_URL" 2>/dev/null) \
    || die "RPC unreachable at $RPC_URL"

# ── collect-tvl ───────────────────────────────────────────────────────────────

tvl_eth="0"
tvl_eth_formatted="0.00"

if tvl_output=$(cd "$REPO_ROOT" && LM="$LM" WETH="$WETH" POOL="$POOL" \
    "$FORGE" script onchain/script/LmTotalEth.s.sol \
    --rpc-url "$RPC_URL" --silent 2>/dev/null); then
    # forge script outputs the number via console2.log — extract last number
    tvl_eth=$(echo "$tvl_output" | grep -oE '[0-9]+' | tail -1)
    tvl_eth="${tvl_eth:-0}"
    tvl_eth_formatted=$(awk "BEGIN {printf \"%.2f\", $tvl_eth / 1e18}")
else
    echo "WARN: LmTotalEth forge script failed, TVL will be 0" >&2
fi

# ── collect-fees ──────────────────────────────────────────────────────────────
# accumulatedFees() may not exist on older deployments — graceful fallback to 0.

accumulated_fees_eth="0"
accumulated_fees_eth_formatted="0.000"

if fees_output=$("$CAST" call "$LM" "accumulatedFees()(uint256)" --rpc-url "$RPC_URL" 2>/dev/null); then
    accumulated_fees_eth=$(echo "$fees_output" | grep -oE '[0-9]+' | head -1)
    accumulated_fees_eth="${accumulated_fees_eth:-0}"
    accumulated_fees_eth_formatted=$(awk "BEGIN {printf \"%.3f\", $accumulated_fees_eth / 1e18}")
fi

# ── collect-positions ─────────────────────────────────────────────────────────
# LiquidityManager.positions(uint8 stage) → (uint128 liquidity, int24 tickLower, int24 tickUpper)
# Stage: 0=FLOOR, 1=ANCHOR, 2=DISCOVERY

position_count=0
positions_json="["
stage_names=("floor" "anchor" "discovery")

for stage in 0 1 2; do
    name="${stage_names[$stage]}"

    if pos_output=$("$CAST" call "$LM" "positions(uint8)(uint128,int24,int24)" "$stage" --rpc-url "$RPC_URL" 2>/dev/null); then
        # cast returns one value per line
        liquidity=$(echo "$pos_output" | sed -n '1p' | tr -d '[:space:]')
        tick_lower=$(echo "$pos_output" | sed -n '2p' | tr -d '[:space:]')
        tick_upper=$(echo "$pos_output" | sed -n '3p' | tr -d '[:space:]')

        liquidity="${liquidity:-0}"
        tick_lower="${tick_lower:-0}"
        tick_upper="${tick_upper:-0}"

        if [[ "$liquidity" != "0" ]]; then
            position_count=$((position_count + 1))
        fi

        [[ "$stage" -gt 0 ]] && positions_json+=","
        positions_json+="
    {
      \"name\": \"$name\",
      \"tick_lower\": $tick_lower,
      \"tick_upper\": $tick_upper,
      \"liquidity\": \"$liquidity\"
    }"
    else
        echo "WARN: Failed to read positions($stage) from LiquidityManager" >&2
        [[ "$stage" -gt 0 ]] && positions_json+=","
        positions_json+="
    {
      \"name\": \"$name\",
      \"tick_lower\": 0,
      \"tick_upper\": 0,
      \"liquidity\": \"0\"
    }"
    fi
done

positions_json+="
  ]"

# ── collect-rebalances ────────────────────────────────────────────────────────
# Event: Recentered(int24 indexed currentTick, bool indexed isUp)

rebalance_count_24h=0
last_rebalance_block=0

from_block=$((block_number - LOOKBACK_BLOCKS))
[[ "$from_block" -lt 0 ]] && from_block=0

# Recentered(int24,bool) topic0
event_topic=$("$CAST" keccak "Recentered(int24,bool)" 2>/dev/null) || event_topic=""

if [[ -n "$event_topic" ]]; then
    if logs=$("$CAST" logs --from-block "$from_block" --to-block "$block_number" \
            --address "$LM" "$event_topic" --rpc-url "$RPC_URL" 2>/dev/null); then
        rebalance_count_24h=$(echo "$logs" | grep -c "blockNumber" 2>/dev/null || echo "0")

        last_block_hex=$(echo "$logs" | grep "blockNumber" | tail -1 | grep -oE '0x[0-9a-fA-F]+' | head -1)
        if [[ -n "$last_block_hex" ]]; then
            last_rebalance_block=$(printf '%d' "$last_block_hex" 2>/dev/null || echo "0")
        fi
    else
        echo "WARN: Failed to fetch Recentered event logs" >&2
    fi
fi

# ── verdict ───────────────────────────────────────────────────────────────────

verdict="healthy"

if [[ "$tvl_eth" == "0" ]]; then
    verdict="offline"
elif [[ "$position_count" -lt 3 ]] || [[ "$rebalance_count_24h" -eq 0 ]]; then
    verdict="degraded"
fi

# ── write JSON ────────────────────────────────────────────────────────────────

cat > "$OUT_FILE" <<ENDJSON
{
  "date": "$DATE",
  "block_number": $block_number,
  "tvl_eth": "$tvl_eth",
  "tvl_eth_formatted": "$tvl_eth_formatted",
  "accumulated_fees_eth": "$accumulated_fees_eth",
  "accumulated_fees_eth_formatted": "$accumulated_fees_eth_formatted",
  "position_count": $position_count,
  "positions": $positions_json,
  "rebalance_count_24h": $rebalance_count_24h,
  "last_rebalance_block": $last_rebalance_block,
  "staleness_threshold_days": 1,
  "verdict": "$verdict"
}
ENDJSON

echo "evidence/protocol/$DATE.json written — verdict: $verdict"
