#!/bin/zsh
set -euo pipefail

REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$REPO_ROOT"

export UFORIA_DATA_ROOT="${UFORIA_DATA_ROOT:-$REPO_ROOT/data}"
export UFORIA_DB_ENABLED="${UFORIA_DB_ENABLED:-true}"
export UFORIA_DB_DSN="${UFORIA_DB_DSN:-postgresql:///uforia?user=$USER}"
export UFORIA_DB_READ_MODE="${UFORIA_DB_READ_MODE:-db}"
export UFORIA_DB_WRITE_MODE="${UFORIA_DB_WRITE_MODE:-db}"
VENV_BIN="$REPO_ROOT/.venv/bin"
export PATH="$VENV_BIN:$PATH:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
UFORIA_BIN="${UFORIA_BIN:-$VENV_BIN/uforia-admin}"
REFRESH_SCOPE="${UFORIA_REFRESH_SCOPE:-all}"
LOCK_WRAPPER="$REPO_ROOT/ops/with_db_advisory_lock.py"
PYTHON_BIN="${UFORIA_PYTHON_BIN:-$REPO_ROOT/.venv/bin/python3}"
if [[ ! -x "$PYTHON_BIN" ]]; then
  PYTHON_BIN="$(command -v python3)"
fi

if ! command -v "$UFORIA_BIN" >/dev/null 2>&1; then
  echo "Refresh hot requires '$UFORIA_BIN' on PATH." >&2
  exit 1
fi

if ! "$UFORIA_BIN" build --help >/dev/null 2>&1; then
  echo "Refresh hot requires an admin CLI with 'build' commands. Current binary: $UFORIA_BIN" >&2
  exit 1
fi

case "$REFRESH_SCOPE" in
  all|options|derived) ;;
  *)
    echo "Invalid UFORIA_REFRESH_SCOPE: $REFRESH_SCOPE (expected all, options, or derived)" >&2
    exit 1
    ;;
esac

if [[ "${UFORIA_REFRESH_LOCK_HELD:-0}" != "1" ]]; then
  case "$REFRESH_SCOPE" in
    options) LOCK_KEY=72001 ;;
    derived) LOCK_KEY=72002 ;;
    all) LOCK_KEY=72003 ;;
    *) LOCK_KEY=72000 ;;
  esac
  exec "$PYTHON_BIN" "$LOCK_WRAPPER" \
    --dsn "$UFORIA_DB_DSN" \
    --key "$LOCK_KEY" \
    --label "refresh-hot/$REFRESH_SCOPE" \
    -- /bin/zsh "$0" "$@"
fi

RUNTIME_DIR="$REPO_ROOT/.runtime"
LOCK_DIR="$RUNTIME_DIR/refresh-hot.lock"
mkdir -p "$RUNTIME_DIR"

if mkdir "$LOCK_DIR" 2>/dev/null; then
  echo "$$" > "$LOCK_DIR/pid"
else
  existing_pid="$(cat "$LOCK_DIR/pid" 2>/dev/null || true)"
  if [[ -z "$existing_pid" ]] || kill -0 "$existing_pid" 2>/dev/null; then
    echo "Hot refresh already running." >&2
    exit 0
  fi
  rm -rf "$LOCK_DIR"
  mkdir "$LOCK_DIR" 2>/dev/null || exit 0
  echo "$$" > "$LOCK_DIR/pid"
fi

cleanup() {
  if [[ -f "$LOCK_DIR/pid" ]] && [[ "$(cat "$LOCK_DIR/pid" 2>/dev/null || true)" = "$$" ]]; then
    rm -rf "$LOCK_DIR"
  fi
}

trap cleanup EXIT INT TERM

timestamp() {
  date -u +"%Y-%m-%dT%H:%M:%SZ"
}

run_step() {
  local label="$1"
  shift
  local started=$SECONDS
  echo "[$(timestamp)] start ${label}"
  "$@"
  echo "[$(timestamp)] done ${label} ($((SECONDS - started))s)"
}

run_best_effort_step() {
  local label="$1"
  shift
  if ! run_step "$label" "$@"; then
    echo "[$(timestamp)] warn ${label} failed"
  fi
}

HOT_LOOKBACK_HOURS="${UFORIA_REFRESH_HOT_LOOKBACK_HOURS:-24}"
HOT_TS=$("$PYTHON_BIN" - <<PY
from datetime import datetime, timezone
ts = datetime.now(timezone.utc).replace(second=0, microsecond=0)
print(ts.strftime("%Y-%m-%dT%H:%M:00Z"))
PY
)
HOT_HOURLY_TS=$("$PYTHON_BIN" - <<PY
from datetime import datetime, timezone
ts = datetime.now(timezone.utc).replace(minute=0, second=0, microsecond=0)
print(ts.strftime("%Y-%m-%dT%H:00:00Z"))
PY
)
HOT_START=$("$PYTHON_BIN" - <<PY
from datetime import datetime, timedelta, timezone
end = datetime.now(timezone.utc).replace(second=0, microsecond=0)
start = end - timedelta(hours=int("${HOT_LOOKBACK_HOURS}"))
print(start.strftime("%Y-%m-%dT%H:%M:00Z"))
PY
)
PERPS_HOT_LOOKBACK_HOURS="${UFORIA_REFRESH_HOT_PERPS_LOOKBACK_HOURS:-6}"
PERPS_HOT_START=$("$PYTHON_BIN" - <<PY
from datetime import datetime, timedelta, timezone
end = datetime.now(timezone.utc).replace(second=0, microsecond=0)
start = end - timedelta(hours=int("${PERPS_HOT_LOOKBACK_HOURS}"))
print(start.strftime("%Y-%m-%dT%H:%M:00Z"))
PY
)

run_options_for_underlying() {
  local underlying="$1"
  "$UFORIA_BIN" ingest deribit-dvol --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" ingest deribit-funding --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build vol-index --underlying "$underlying" --source dvol --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build rvvix --underlying "$underlying" --source dvol --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build qvvix --underlying "$underlying" --source dvol --ts "$HOT_HOURLY_TS" || true
  "$UFORIA_BIN" build razor --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build surface-features --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build options-surface --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build options-carry --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build options-skew --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build options-dislocations --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build options-positioning --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build vol-cone --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build term-structure-momentum --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build gamma-exposure --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build funding-context --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build straddle-breakeven --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build surface-factor-rv --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build ml-carry-toxicity --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build expiry-flow-map --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build adaptive-hedging --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build sessionality-clocks --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build funding-basis-skew --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build options-signals --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build vol-regime-transitions --underlying "$underlying" --start "$HOT_START" --end "$HOT_TS" || true
}

run_derived_for_underlying() {
  local underlying="$1"
  run_best_effort_step "perps-signals ${underlying}" \
    "$UFORIA_BIN" build perps-signals --asset "$underlying" --start "$PERPS_HOT_START" --end "$HOT_TS"
  run_best_effort_step "perps-composites ${underlying}" \
    "$UFORIA_BIN" build perps-composites --asset "$underlying" --start "$PERPS_HOT_START" --end "$HOT_TS"
  run_best_effort_step "perps-transitions ${underlying}" \
    "$UFORIA_BIN" build perps-transitions --asset "$underlying" --start "$PERPS_HOT_START" --end "$HOT_TS"
  run_best_effort_step "composite ${underlying}" \
    "$UFORIA_BIN" build composite --asset "$underlying" --start "$HOT_START" --end "$HOT_TS" --skip-market
  run_best_effort_step "composite-components ${underlying}" \
    "$UFORIA_BIN" build composite-components --asset "$underlying" --start "$HOT_START" --end "$HOT_TS" --skip-market
  run_best_effort_step "composite-transitions ${underlying}" \
    "$UFORIA_BIN" build composite-transitions --asset "$underlying" --start "$HOT_START" --end "$HOT_TS" --skip-market
}

run_derived_market() {
  run_best_effort_step "composite-market" \
    "$UFORIA_BIN" build composite-market --start "$HOT_START" --end "$HOT_TS"
  run_best_effort_step "composite-market-components" \
    "$UFORIA_BIN" build composite-market-components --start "$HOT_START" --end "$HOT_TS"
  run_best_effort_step "composite-market-transitions" \
    "$UFORIA_BIN" build composite-market-transitions --start "$HOT_START" --end "$HOT_TS"
}

for UNDERLYING in BTC ETH; do
  if [[ "$REFRESH_SCOPE" == "all" || "$REFRESH_SCOPE" == "options" ]]; then
    run_options_for_underlying "$UNDERLYING"
  fi
  if [[ "$REFRESH_SCOPE" == "all" || "$REFRESH_SCOPE" == "derived" ]]; then
    run_derived_for_underlying "$UNDERLYING"
  fi
done

if [[ "$REFRESH_SCOPE" == "all" || "$REFRESH_SCOPE" == "options" ]]; then
  "$UFORIA_BIN" build options-rv --start "$HOT_START" --end "$HOT_TS" || true
  "$UFORIA_BIN" build btc-eth-dispersion --start "$HOT_START" --end "$HOT_TS" || true
fi

if [[ "$REFRESH_SCOPE" == "all" || "$REFRESH_SCOPE" == "derived" ]]; then
  run_derived_market
fi
