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

PROJECT_ROOT="${PROJECT_ROOT:-$(pwd)}"
cd "$PROJECT_ROOT"

POOL="0x5a7b4970b2610aee4776a6944d9f2171ee6060b0"
POOL_NAME="base_CHECK_USDC_2PCT_fresh"

TIME_FROM="${TIME_FROM:-2026-05-01T00:00:00Z}"
TIME_TO="${TIME_TO:-$(date -u +%Y-%m-%dT%H:%M:%SZ)}"
WINDOW_HOURS="${WINDOW_HOURS:-6}"
MIN_SWAP_ROWS="${MIN_SWAP_ROWS:-${MIN_ROWS:-50}}"
MAX_LOOKBACK_HOURS="${MAX_LOOKBACK_HOURS:-168}"

if [[ "${TIME_FROM}" == "2026-05-01T00:00:00Z" ]]; then
  TIME_FROM="$(date -u -d "${WINDOW_HOURS} hours ago" +%Y-%m-%dT%H:%M:%SZ)"
fi

TS="$(date -u +%Y%m%dT%H%M%SZ)"
SAFE_FROM="$(echo "$TIME_FROM" | tr ':' '-' | tr -d 'Z')"
SAFE_TO="$(echo "$TIME_TO" | tr ':' '-' | tr -d 'Z')"

OUT_DIR="DEX_DATA/aerodrome_slipstream/${POOL_NAME}_${SAFE_FROM}_${SAFE_TO}"
TARGET_NPZ="DEX_DATA/fast_npz/base_CHECK_USDC_2PCT_fresh_fee_replay_v2.npz"
TMP_NPZ="DEX_DATA/fast_npz/_tmp/base_CHECK_USDC_2PCT_fresh_fee_replay_v2_${TS}.npz"
LOG_DIR="DEX_REPORTS/paper_live_check_static_85_0p5_336h_v1"
PYTHON_BIN="${PYTHON_BIN:-/var/www/vps2.happyuser.info/top/backtest_SK/.venv38/bin/python}"
EVENTS="${EVENTS:-Swap}"
CHUNK_SIZE="${CHUNK_SIZE:-10000}"
MIN_CHUNK_SIZE="${MIN_CHUNK_SIZE:-1000}"
SLEEP_S="${SLEEP_S:-0.05}"
ATTEMPTS="${ATTEMPTS:-8}"

if ! "${PYTHON_BIN}" - <<'PY' >/dev/null 2>&1
import importlib.util
raise SystemExit(0 if importlib.util.find_spec("web3") is not None else 1)
PY
then
  for candidate in \
    /var/www/vps2.happyuser.info/top/backtest_SK/.venv38/bin/python \
    /var/www/vps2.happyuser.info/top/backtest_SK/.venv38/bin/python3 \
    /home/simple_user/.local/share/virtualenvs/backtest_SK/bin/python3 \
    /usr/local/bin/python3 \
    python3
  do
    if [[ "${candidate}" == */* ]]; then
      [[ -x "${candidate}" ]] || continue
      candidate_bin="${candidate}"
    else
      candidate_bin="$(command -v "${candidate}" || true)"
      [[ -n "${candidate_bin}" ]] || continue
    fi
    if "${candidate_bin}" - <<'PY' >/dev/null 2>&1
import importlib.util
raise SystemExit(0 if importlib.util.find_spec("web3") is not None else 1)
PY
    then
      PYTHON_BIN="${candidate_bin}"
      break
    fi
  done
fi

mkdir -p "$OUT_DIR" "$(dirname "$TMP_NPZ")" "$LOG_DIR"

hours_ago() {
  "${PYTHON_BIN}" - "$1" "$2" <<'PY'
from datetime import datetime, timedelta, timezone
import sys
ts = datetime.strptime(sys.argv[1], "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=timezone.utc)
hours = int(sys.argv[2])
print((ts - timedelta(hours=hours)).strftime("%Y-%m-%dT%H:%M:%SZ"))
PY
}

csv_row_count() {
  local path="$1"
  if [[ ! -s "$path" ]]; then
    echo 0
    return 0
  fi
  tail -n +2 "$path" | wc -l | tr -d ' '
}

combine_events_csv() {
  "${PYTHON_BIN}" - "$COMBINED_EVENTS" "$@" <<'PY'
import csv
import sys
from pathlib import Path

out_path = Path(sys.argv[1])
in_paths = [Path(p) for p in sys.argv[2:]]

fieldnames = None
rows = []
for path in in_paths:
    if not path.exists() or path.stat().st_size == 0:
        continue
    with path.open(newline="") as fh:
        reader = csv.DictReader(fh)
        if reader.fieldnames is None:
            continue
        if fieldnames is None:
            fieldnames = list(reader.fieldnames)
        for row in reader:
            key = (
                int(row.get("blockNumber") or 0),
                int(row.get("transactionIndex") or 0),
                int(row.get("logIndex") or 0),
            )
            rows.append((key, row))

if fieldnames is None:
    raise SystemExit(0)

rows.sort(key=lambda item: item[0])
out_path.parent.mkdir(parents=True, exist_ok=True)
seen = set()
with out_path.open("w", newline="") as fh:
    writer = csv.DictWriter(fh, fieldnames=fieldnames, extrasaction="ignore")
    writer.writeheader()
    for key, row in rows:
        if key in seen:
            continue
        seen.add(key)
        writer.writerow(row)
PY
}

echo "[check_update] pool=${POOL}"
echo "[check_update] window=${TIME_FROM} -> ${TIME_TO}"
echo "[check_update] out_dir=${OUT_DIR}"
echo "[check_update] tmp_npz=${TMP_NPZ}"
echo "[check_update] target_npz=${TARGET_NPZ}"
echo "[check_update] python_bin=${PYTHON_BIN}"
echo "[check_update] events=${EVENTS} chunk_size=${CHUNK_SIZE} min_chunk_size=${MIN_CHUNK_SIZE} sleep_s=${SLEEP_S} attempts=${ATTEMPTS}"
echo "[check_update] min_swap_rows=${MIN_SWAP_ROWS} max_lookback_hours=${MAX_LOOKBACK_HOURS} window_hours=${WINDOW_HOURS}"

COMBINED_EVENTS="$OUT_DIR/events_all.csv"
rm -f "$COMBINED_EVENTS"

CURRENT_TO="$TIME_TO"
CURRENT_FROM="$TIME_FROM"
WINDOW_INDEX=0
MAX_WINDOWS=$(( (MAX_LOOKBACK_HOURS + WINDOW_HOURS - 1) / WINDOW_HOURS ))
TOTAL_ROWS=0
SLICE_EVENT_FILES=()

while (( WINDOW_INDEX < MAX_WINDOWS && TOTAL_ROWS < MIN_SWAP_ROWS )); do
  SLICED_FROM="$CURRENT_FROM"
  if [[ "$SLICED_FROM" == "$CURRENT_TO" ]]; then
    break
  fi

  SLICE_SAFE_FROM="$(echo "$SLICED_FROM" | tr ':' '-' | tr -d 'Z')"
  SLICE_SAFE_TO="$(echo "$CURRENT_TO" | tr ':' '-' | tr -d 'Z')"
  SLICE_OUT_DIR="$OUT_DIR/slices/${WINDOW_INDEX}_${SLICE_SAFE_FROM}_${SLICE_SAFE_TO}"
  mkdir -p "$SLICE_OUT_DIR"

  echo "[slice] idx=${WINDOW_INDEX} from=${SLICED_FROM} to=${CURRENT_TO} out_dir=${SLICE_OUT_DIR}"

  "${PYTHON_BIN}" dex_platform/data_collectors/fetch_aerodrome_slipstream_events_v2.py \
    --pool "$POOL" \
    --time-from "$SLICED_FROM" \
    --time-to "$CURRENT_TO" \
    --out-dir "$SLICE_OUT_DIR" \
    --rpc-url https://mainnet.base.org \
    --chunk-size "$CHUNK_SIZE" \
    --min-chunk-size "$MIN_CHUNK_SIZE" \
    --sleep-s "$SLEEP_S" \
    --attempts "$ATTEMPTS" \
    --events "$EVENTS" \
    --no-parquet

  SLICE_EVENTS="$SLICE_OUT_DIR/events_all.csv"
  if [[ ! -s "$SLICE_EVENTS" ]]; then
    echo "[warn] empty slice events: $SLICE_EVENTS"
  else
    SLICE_ROWS="$(csv_row_count "$SLICE_EVENTS")"
    echo "[slice_rows] idx=${WINDOW_INDEX} rows=${SLICE_ROWS}"
    SLICE_EVENT_FILES+=("$SLICE_EVENTS")
    combine_events_csv "${SLICE_EVENT_FILES[@]}"
    TOTAL_ROWS="$(csv_row_count "$COMBINED_EVENTS")"
    echo "[combined_rows] total=${TOTAL_ROWS}"
  fi

  if (( TOTAL_ROWS >= MIN_SWAP_ROWS )); then
    break
  fi

  CURRENT_TO="$SLICED_FROM"
  CURRENT_FROM="$(hours_ago "$CURRENT_TO" "$WINDOW_HOURS")"
  WINDOW_INDEX=$((WINDOW_INDEX + 1))
done

if (( TOTAL_ROWS < MIN_SWAP_ROWS )); then
  echo "[fatal] insufficient swap rows after adaptive refresh: total=${TOTAL_ROWS} min_required=${MIN_SWAP_ROWS} lookback_hours=${MAX_LOOKBACK_HOURS} window_hours=${WINDOW_HOURS}; target_npz_not_replaced=${TARGET_NPZ}"
  exit 4
fi

EVENTS="$COMBINED_EVENTS"

if [[ ! -s "$EVENTS" ]]; then
  echo "[fatal] events file missing/empty: $EVENTS"
  exit 2
fi

"${PYTHON_BIN}" dex_platform/data_collectors/build_cl_fee_replay_npz_v2.py \
  --events "$EVENTS" \
  --out-npz "$TMP_NPZ" \
  --pool-name base_CHECK_USDC_AERODROME_2PCT \
  --token0 USDC \
  --token1 CHECK \
  --dec0 6 \
  --dec1 18 \
  --quote-token token0 \
  --fee-rate 0.002515

if [[ ! -s "$TMP_NPZ" ]]; then
  echo "[fatal] tmp npz missing/empty: $TMP_NPZ"
  exit 3
fi

"${PYTHON_BIN}" scripts/check_check_npz_sanity_v1.py "$TMP_NPZ"

cp "$TARGET_NPZ" "${TARGET_NPZ}.bak_${TS}" 2>/dev/null || true
mv "$TMP_NPZ" "$TARGET_NPZ"

stat -c '[updated] %y %s %n' "$TARGET_NPZ"
