#!/bin/zsh
# One command for the whole recording: Notion, Lyonesse, then Control (a quiet Mac, no meeting app).
#   ./run.sh                 all three, in order
#   ./run.sh notion          just one (control | notion | lyonesse)
#
# It logs every process's network bytes,
# plays the clip itself, writes every timestamp itself, and notices Wi-Fi going off and on by
# itself. You only click Record / Stop in the app, toggle Wi-Fi, and press Enter when asked.
# Needs no sudo. Changes nothing on the Mac. Reads Wi-Fi state, never sets it.
cd "${0:A:h}"
CLIP=clip-10min.wav
BOLD=$'\e[1m'; DIM=$'\e[2m'; GRN=$'\e[32m'; YLW=$'\e[33m'; OFF=$'\e[0m'

say_do() { print "\n${BOLD}${YLW}>> $1${OFF}"; }
info()   { print "${DIM}$1${OFF}"; }
enter()  { print -n "${BOLD}   press Enter when done${OFF} "; read -r _; }
mark()   { echo "$(date +%s),$1" >> "$DIR/marks.csv"; info "   marked: $1 at $(date +%T)"; }
wifi()   { networksetup -getairportpower en0 2>/dev/null | awk '{print tolower($NF)}'; }

countdown() { # seconds, label
  local s=$1
  while (( s > 0 )); do printf "\r   ${DIM}%s: %d:%02d left ${OFF}" "$2" $((s/60)) $((s%60)); sleep 1; ((s--)); done
  printf "\r   %s: done              \n" "$2"
}

wait_wifi() { # off|on
  local want=$1
  if [[ $want == off ]]; then say_do "Turn Wi-Fi OFF (menu bar). I'll notice."; else say_do "Turn Wi-Fi back ON. I'll notice."; fi
  until [[ "$(wifi)" == "$want" ]]; do sleep 1; done
  mark "wifi $want"
  [[ $want == on ]] && { info "   waiting for the network to come back..."; until ping -c1 -t2 1.1.1.1 >/dev/null 2>&1; do sleep 1; done; }
}

start_log() { # label, version, plan
  DIR="runs/$1-$(date +%Y%m%d-%H%M%S)"; mkdir -p "$DIR"
  { echo "label: $1"; echo "started: $(date -u +%FT%TZ)"; sw_vers | tr '\n' ' '; echo
    echo "wifi: $(wifi)"; echo "app version: $2"; echo "plan: $3"; } > "$DIR/meta.txt"
  echo "epoch,mark" > "$DIR/marks.csv"
  ( while true; do echo "#t=$(date +%s)"; nettop -L 1 -x -n -J bytes_in,bytes_out 2>/dev/null; done ) >> "$DIR/net.log" &
  LOGGER=$!
  info "   logging to $DIR"
}

stop_log() {
  kill $LOGGER 2>/dev/null; wait $LOGGER 2>/dev/null
  echo "ended: $(date -u +%FT%TZ)" >> "$DIR/meta.txt"
  print "${GRN}   saved $DIR${OFF}"
  node summarize.mjs "$DIR" "$1" 2>/dev/null | head -12
}
trap 'kill $LOGGER 2>/dev/null' EXIT INT

preflight() {
  [[ -f $CLIP ]] || { print "missing $CLIP"; exit 1; }
  local busy=()
  for a in Slack "Google Chrome" Firefox Spotify Docker Tailscale Proxyman Mail Dropbox Safari; do
    pgrep -x "$a" >/dev/null && busy+=("$a")
  done
  if (( ${#busy} )); then
    say_do "Quit these first (Cmd-Q): ${(j:, :)busy}"; enter
  fi
  [[ "$(wifi)" == on ]] || { say_do "Wi-Fi is off. Turn it on."; until [[ "$(wifi)" == on ]]; do sleep 1; done; }
  info "Volume: set it to about 60% and leave it there for every run."
}

version_of() { defaults read "/Applications/$1.app/Contents/Info" CFBundleShortVersionString 2>/dev/null || echo "?"; }

run_control() {
  print "\n${BOLD}=== Run 0: Control (no meeting app, ~13 min, no clicks except Wi-Fi) ===${OFF}"
  start_log control none none
  mark "app open"
  countdown 600 "quiet Mac"
  mark "audio end"
  wait_wifi off; countdown 60 "offline"; mark "offline done"
  wait_wifi on; countdown 120 "after reconnect"
  stop_log
}

run_app() { # label, App name, record hint
  local label=$1 app=$2 hint=$3
  [[ -d "/Applications/$app.app" ]] || { print "${YLW}$app isn't in /Applications. Install it, then run ./run.sh $label${OFF}"; return 1; }
  print "\n${BOLD}=== $app (~20 min) ===${OFF}"
  local plan; print -n "   Plan in $app (free/paid) [free]: "; read -r plan; plan=${plan:-free}
  start_log "$label" "$(version_of "$app")" "$plan"

  open -a "$app"; mark "app open"
  say_do "In $app: $hint. Get it to the point where ONE click starts recording."; enter

  say_do "Click RECORD in $app now."; enter
  mark "rec start"
  info "   playing the 10-min clip through the speakers..."
  afplay "$CLIP"
  mark "audio end"
  say_do "Click STOP in $app."; enter
  mark "rec stopped"

  say_do "Wait until the transcript AND summary are both showing in $app."; enter
  mark "summary ready"
  countdown 180 "watching for late uploads"

  wait_wifi off
  say_do "Start a NEW recording in $app (the clip will play 60 s)."; enter
  mark "offline rec start"
  afplay -t 60 "$CLIP"
  say_do "Click STOP. Note what $app did (refused / recorded only / transcribed)."; enter
  mark "offline rec stopped"
  mkdir -p runs/screenshots
  say_do "Screenshot: click the $app window when the camera icon appears."
  screencapture -iWo "runs/screenshots/$label-offline.png" && info "   saved runs/screenshots/$label-offline.png"
  local what; print -n "   In a few words, what did it do offline? "; read -r what
  echo "offline: $what" >> "$DIR/meta.txt"
  mark "offline done"

  wait_wifi on
  countdown 180 "watching for catch-up uploads"
  mark "end"
  say_do "Quit $app fully: Cmd-Q, plus its menu-bar icon if it has one."
  until ! pgrep -x "$app" >/dev/null; do sleep 1; done
  info "   $app has quit."
  stop_log "$app"
}

preflight
case "${1:-all}" in
  control)  run_control ;;
  notion)   run_app notion Notion "open a page and get the AI Meeting Notes recorder ready" ;;
  lyonesse) run_app lyonesse Lyonesse "use plain Record (NOT Record a meeting, 2.0.4 has the Mac bug)" ;;
  all)
    run_app notion Notion "open a page and get the AI Meeting Notes recorder ready" || exit 1
    run_app lyonesse Lyonesse "use plain Record (NOT Record a meeting, 2.0.4 has the Mac bug)" || exit 1
    run_control
    print "\n${GRN}${BOLD}All three runs done. Results are in runs/, read them with analyze.mjs.${OFF}" ;;
  *) print "usage: ./run.sh [control|notion|lyonesse]"; exit 1 ;;
esac
