#!/usr/bin/env bash
# mt-run — operator front-end for the acquisition pass units.
#
#   sudo mt-run daily        start a daily pass, stream its output live
#   sudo mt-run minute       start a minute pass, stream its output live
#   sudo mt-run kalshi       start a Kalshi collection pass, stream it live
#   mt-run status            state + last result + recent output of every pass
#   mt-run follow daily      attach to a running pass's live output
#                            (also: follow minute, follow kalshi)
#   mt-run <anything else>   run production's mt CLI, e.g. mt-run data caggs status
#
# Starting streams output exactly like the old manual invocation, with one
# improvement: Ctrl-C DETACHES your terminal and the pass keeps running
# (re-attach any time with `mt-run follow daily`). The command exits with
# the pass's real exit code when it completes.
#
# The timers run the same units automated; mt-run is for out-of-schedule
# runs and for checking on whatever is currently happening.
set -euo pipefail

usage() {
  sed -n '2,11p' "$0" | sed 's/^# \{0,3\}//'
  exit 2
}

# The pass kinds this wrapper drives. Adding a source means adding its kind
# here and nowhere else in this script (runbook 100, "Adding a source").
KINDS=(daily minute kalshi)

is_kind() {
  local candidate
  for candidate in "${KINDS[@]}"; do
    [[ "$1" == "${candidate}" ]] && return 0
  done
  return 1
}

unit_for() {
  is_kind "$1" || usage
  echo "mt-${1}-pass.service"
}

is_running() {
  local st
  st="$(systemctl is-active "$1" || true)"
  [[ "${st}" == "active" || "${st}" == "activating" ]]
}

show_status() {
  local unit kind st
  for kind in "${KINDS[@]}"; do
    unit="$(unit_for "${kind}")"
    st="$(systemctl is-active "${unit}" || true)"
    if is_running "${unit}"; then
      echo "== ${kind}: RUNNING (since $(systemctl show "${unit}" -p ExecMainStartTimestamp --value)) — latest output:"
      journalctl -u "${unit}" -n 5 --no-hostname --no-pager 2>/dev/null \
        || echo "   (journal not readable as this user — try sudo mt-run status)"
      echo "   attach live: mt-run follow ${kind}"
    else
      local ended
      ended="$(systemctl show "${unit}" -p ExecMainExitTimestamp --value)"
      if [[ -n "${ended}" ]]; then
        echo "== ${kind}: not running (state=${st}); last run: $(systemctl show "${unit}" -p Result --value), exit=$(systemctl show "${unit}" -p ExecMainStatus --value), ended ${ended}"
      else
        # systemd forgets a dead oneshot's ExecMain* after daemon-reload;
        # the journal still knows.
        local lastline
        lastline="$(journalctl -u "${unit}" -n 1 --no-pager --no-hostname -q 2>/dev/null || true)"
        if [[ -n "${lastline}" ]]; then
          echo "== ${kind}: not running (state=${st}); last journal activity:"
          echo "   ${lastline}"
        else
          echo "== ${kind}: not running (state=${st}); never run"
        fi
      fi
    fi
  done
  echo "== timers:"
  systemctl list-timers 'mt-*' --no-pager | sed 's/^/   /'
}

follow() {
  local unit
  unit="$(unit_for "$1")"
  is_running "${unit}" || echo "(no ${1} pass is currently running — showing/waiting on the journal anyway; Ctrl-C exits)"
  # Plain attach: Ctrl-C here only stops the viewer, never the pass.
  exec journalctl -u "${unit}" -f --no-hostname
}

start_and_stream() {
  local kind="$1" unit
  unit="$(unit_for "${kind}")"

  [[ "$(id -u)" -eq 0 ]] || { echo "ERROR: starting needs root: sudo mt-run ${kind}" >&2; exit 1; }

  if is_running "${unit}"; then
    echo "A ${kind} pass is already running — attaching to it instead." >&2
    exec journalctl -u "${unit}" -f --no-hostname
  fi

  # Begin the journal follow BEFORE starting the unit so no lines are missed.
  journalctl -u "${unit}" -f -n 0 --no-hostname &
  local jctl=$!

  # shellcheck disable=SC2329  # invoked indirectly via the INT trap below
  detach() {
    kill "${jctl}" 2>/dev/null || true
    echo
    echo "Detached — the pass is still running. Check on it with:"
    echo "  mt-run status        # or: mt-run follow ${kind}"
    exit 130
  }
  trap detach INT

  systemctl start --no-block "${unit}"

  while is_running "${unit}"; do sleep 2; done
  trap - INT
  kill "${jctl}" 2>/dev/null || true
  wait "${jctl}" 2>/dev/null || true

  local result code
  result="$(systemctl show "${unit}" -p Result --value)"
  code="$(systemctl show "${unit}" -p ExecMainStatus --value)"
  echo
  if [[ "${result}" == "success" ]]; then
    echo "Pass complete: ${unit} exited 0 (success)."
  else
    echo "Pass FAILED: ${unit} result=${result} exit=${code}. Full log: mt-run follow ${kind} (or journalctl -u ${unit} -e)" >&2
  fi
  exit "${code:-1}"
}

# NAME=VALUE for every MT_* variable named in the env file, taking each value
# from the already-sourced environment (indirect expansion) so quoting and
# interpolation in the file are honoured exactly once. Extracted so it can be
# exercised on its own: bash -c '. deploy/mt-run; mt_env_assignments FILE'.
mt_env_assignments() {
  local file="$1" name
  # Absolute tool paths: this runs after the env file has been sourced, and a
  # stray PATH= line in that file must not decide whether the wrapper works.
  while IFS= read -r name; do
    printf '%s=%s\n' "${name}" "${!name-}"
  done < <(/usr/bin/grep -oE '^[[:space:]]*(export[[:space:]]+)?MT_[A-Z0-9_]+=' "${file}" \
             | /usr/bin/grep -oE 'MT_[A-Z0-9_]+' | /usr/bin/sort -u)
}

# Anything that is not a wrapper verb passes through to production's own mt
# CLI: /opt binary + /etc/manta-trading.env credentials. One front door.
run_production_mt() {
  local mt_bin="/opt/manta-trading/.venv/bin/mt" env_file="/etc/manta-trading.env"
  [[ -x "${mt_bin}" ]] || { echo "ERROR: ${mt_bin} not found — is production installed?" >&2; exit 1; }
  if [[ -r "${env_file}" ]]; then
    set -a; # shellcheck disable=SC1090  # runtime env file, not a script dependency
    . "${env_file}"; set +a
    exec "${mt_bin}" "$@"
  elif [[ "$(id -u)" -eq 0 ]]; then
    set -a; # shellcheck disable=SC1090
    . "${env_file}"; set +a
    # Forward EVERY MT_* variable the env file defines, not a hard-coded pair:
    # the old two-name list silently dropped MT_KALSHI_*/MT_LOG_LEVEL on this
    # branch, so `sudo mt-run data kalshi status` ran without its credentials
    # (design 263, Decision 6).
    local -a env_args=()
    readarray -t env_args < <(mt_env_assignments "${env_file}")
    exec runuser -u manta-trading -- env HOME=/opt/manta-trading \
      "${env_args[@]}" "${mt_bin}" "$@"
  elif [[ -t 0 ]]; then
    # Credentials need elevation; just do it rather than making the human
    # retype the command. (Group membership from usermod applies at login —
    # after the next logout/login this branch stops being needed.)
    echo "(elevating via sudo — credentials are root-protected)" >&2
    exec sudo "$0" "$@"
  else
    echo "ERROR: ${env_file} not readable and no terminal for sudo. Run as root or add this user to the manta-trading group." >&2
    exit 1
  fi
}

[[ $# -ge 1 ]] || usage
case "$1" in
  status)        show_status ;;
  follow)        [[ $# -eq 2 ]] || usage; follow "$2" ;;
  -h|--help)     usage ;;
  *)             if is_kind "$1"; then start_and_stream "$1"; else run_production_mt "$@"; fi ;;
esac
