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

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PYTHON_BIN="$ROOT_DIR/.venv/bin/python"

usage() {
  cat <<'USAGE'
Braiins Ratchet

Commands:
  next               Show exactly what to do next. Default command.
  setup              Create the local .venv and initialize the local database.
  once               Fetch one fresh sample, then print the cockpit.
  watch [hours]      Run repeated monitor cycles for N hours. Default: 6.
  supervise          Run the durable forever lifecycle supervisor.
  engine             Start/stop/status for the background monitor engine.
  app                Build and open the native macOS app.
  mirror             Print the app's latest self-written visual-state snapshot.
  position           Record/list/close manually executed Braiins exposure.
  report             Print the latest stored report without fetching new data.
  app-state          Print structured JSON for the native macOS app.
  experiments        Print the Karpathy-style experiment ledger.
  retro SINCE [UNTIL] Write a retroactive report from stored snapshots.
  raw-cycle          Run one full monitor cycle and print raw JSON.
  test               Run the network-free test suite.
  guide              Print the noob-friendly user guide.
  operator-guide     Print the installation, migration, and recovery guide.
  explain            Alias for guide.

Examples:
  ./scripts/ratchet
  ./scripts/ratchet next
  ./scripts/ratchet setup
  ./scripts/ratchet once
  ./scripts/ratchet watch 6
  ./scripts/ratchet supervise
  ./scripts/ratchet engine status
  ./scripts/ratchet app
  ./scripts/ratchet mirror
  ./scripts/ratchet position list
  ./scripts/ratchet report
  ./scripts/ratchet experiments
  ./scripts/ratchet guide
  ./scripts/ratchet operator-guide
  ./scripts/ratchet retro 2026-04-25T19:08:00+00:00 2026-04-25T21:05:00+00:00
USAGE
}

ensure_venv() {
  if [[ ! -x "$PYTHON_BIN" ]]; then
    echo "Creating local virtual environment at .venv ..." >&2
    python3 -m venv "$ROOT_DIR/.venv"
  fi
}

run_python() {
  ensure_venv
  PYTHONPATH="$ROOT_DIR/src" "$PYTHON_BIN" "$@"
}

cmd_setup() {
  ensure_venv
  run_python -m braiins_ratchet.cli init-db
  echo
  echo "Setup complete. Next: ./scripts/ratchet next"
}

cmd_next() {
  run_python -m braiins_ratchet.cli next
}

cmd_once() {
  run_python -m braiins_ratchet.cli cycle >/dev/null
  echo
  echo "Fresh sample collected. Reading the cockpit now."
  echo "Technical report is available with: ./scripts/ratchet report"
  echo
  run_python -m braiins_ratchet.cli next
}

cmd_raw_cycle() {
  run_python -m braiins_ratchet.cli cycle
}

cmd_watch() {
  local hours="${1:-6}"
  local interval_seconds=300
  local cycles

  if ! [[ "$hours" =~ ^[0-9]+$ ]] || [[ "$hours" -lt 1 ]]; then
    echo "watch expects whole hours, e.g. ./scripts/ratchet watch 6" >&2
    exit 2
  fi

  cycles=$((hours * 3600 / interval_seconds))
  echo "Watch started. This terminal is now controlled by Braiins Ratchet for about $hours hour(s)."
  echo "You do not need to babysit it. Leave this terminal open and come back later."
  echo "It will run $cycles cycles, one cycle every $interval_seconds seconds."
  echo "It only reads public/OCEAN data and writes local snapshots inside this repo."
  echo "At the end it writes reports/EXPERIMENT_LOG.md plus a run report, then prints DO THIS NOW."
  echo "Stop early only if you intentionally want a partial run: Ctrl-C."
  echo

  set +e
  run_python -m braiins_ratchet.cli watch --cycles "$cycles" --interval-seconds "$interval_seconds"
  local status=$?
  set -e
  if [[ "$status" -ne 0 && "$status" -ne 130 ]]; then
    exit "$status"
  fi
  echo
  echo "Watch finished. Reading the cockpit now."
  echo
  BRAIINS_RATCHET_IGNORE_PROCESS_WATCH=1 run_python -m braiins_ratchet.cli next
  return "$status"
}

cmd_report() {
  run_python -m braiins_ratchet.cli report
}

cmd_app_state() {
  run_python -m braiins_ratchet.cli app-state
}

cmd_pipeline() {
  run_python -m braiins_ratchet.cli pipeline "$@"
}

cmd_supervise() {
  run_python -m braiins_ratchet.cli supervise "$@"
}

cmd_engine() {
  run_python -m braiins_ratchet.cli engine "$@"
}

cmd_app() {
  local app_path
  app_path="$("$ROOT_DIR/scripts/build_mac_app" | tail -n 1)"
  echo "Opening $app_path"
  pkill -x BraiinsRatchetMac 2>/dev/null || true
  open "$app_path"
}

cmd_mirror() {
  local path="$ROOT_DIR/data/app_visual_state.md"
  if [[ ! -f "$path" ]]; then
    echo "No app visual-state snapshot exists yet."
    echo "Open the native app with: ./scripts/ratchet app"
    echo "Then refresh or open the Reality Mirror tab."
    return 0
  fi
  cat "$path"
}

cmd_position() {
  run_python -m braiins_ratchet.cli position "$@"
}

cmd_experiments() {
  run_python -m braiins_ratchet.cli experiments
}

cmd_retro() {
  local since="${1:-}"
  local until="${2:-}"
  local run_id

  if [[ -z "$since" ]]; then
    echo "retro expects an ISO timestamp, e.g. ./scripts/ratchet retro 2026-04-25T19:08:00+00:00" >&2
    exit 2
  fi

  run_id="retro-${since//[:+]/-}"
  if [[ -n "$until" ]]; then
    run_python -m braiins_ratchet.cli retro-report --since "$since" --until "$until" --run-id "$run_id" --write
  else
    run_python -m braiins_ratchet.cli retro-report --since "$since" --run-id "$run_id" --write
  fi
}

cmd_test() {
  run_python -m unittest discover -s "$ROOT_DIR/tests"
}

cmd_explain() {
  cat "$ROOT_DIR/docs/USER_GUIDE.md"
}

cmd_operator_guide() {
  cat "$ROOT_DIR/docs/OPERATOR_GUIDE.md"
}

main() {
  cd "$ROOT_DIR"
  local command="${1:-next}"
  shift || true

  case "$command" in
    next) cmd_next "$@" ;;
    setup) cmd_setup "$@" ;;
    once) cmd_once "$@" ;;
    watch) cmd_watch "$@" ;;
    pipeline|auto) cmd_pipeline "$@" ;;
    supervise|daemon) cmd_supervise "$@" ;;
    engine) cmd_engine "$@" ;;
    app|mac-app) cmd_app "$@" ;;
    mirror|reality) cmd_mirror "$@" ;;
    position|positions) cmd_position "$@" ;;
    report) cmd_report "$@" ;;
    app-state) cmd_app_state "$@" ;;
    experiments) cmd_experiments "$@" ;;
    retro) cmd_retro "$@" ;;
    raw-cycle) cmd_raw_cycle "$@" ;;
    test) cmd_test "$@" ;;
    guide|user-guide|explain) cmd_explain "$@" ;;
    operator-guide|operator) cmd_operator_guide "$@" ;;
    help|-h|--help) usage ;;
    *)
      echo "Unknown command: $command" >&2
      echo >&2
      usage >&2
      exit 2
      ;;
  esac
}

main "$@"
