#!/usr/bin/env bash
# Fixture /dev ONLY — inotify watcher for rotated capture offload.
#
# Watches ~/EtherGold/dev/{data,logs}. On rotated sibling create/move/close,
# debounces then runs offload_fixture_dev_rotated.sh.
# Requires inotifywait (inotify-tools). No poll-as-primary path.
#
#   bash watch_fixture_dev_rotated.sh
# Install: bash install_fixture_dev_rotated_offload.sh

if grep -q $'\r' "${BASH_SOURCE[0]}" 2>/dev/null; then
  sed -i 's/\r$//' "${BASH_SOURCE[0]}"
  exec bash "${BASH_SOURCE[0]}" "$@"
fi

set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WORKER="${ROOT}/offload_fixture_dev_rotated.sh"
DEBOUNCE_SEC="${FIXTURE_DEV_OFFLOAD_DEBOUNCE_SEC:-2}"

if [[ -f "${ROOT}/ethergold_paths.sh" ]]; then
  # shellcheck source=ethergold_paths.sh
  source "${ROOT}/ethergold_paths.sh"
fi
ETHERGOLD_ROOT="${ETHERGOLD_ROOT:-/home/topbox/EtherGold}"
ETHERGOLD_LOGS="${ETHERGOLD_LOGS:-${ETHERGOLD_ROOT}/logs}"
DEV_ROOT="${ETHERGOLD_ROOT}/dev"
TRANSCRIPT="${ETHERGOLD_LOGS}/.fixture_dev_offload_last.log"
LOCK_DIR="${ETHERGOLD_LOGS}/.fixture_dev_offload.lock.d"

mkdir -p "${ETHERGOLD_LOGS}" "${DEV_ROOT}/data" "${DEV_ROOT}/logs"

log() {
  printf '%s %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$*" | tee -a "${TRANSCRIPT}"
}

if [[ ! -f "${WORKER}" ]]; then
  log "FATAL: missing worker ${WORKER}"
  exit 1
fi

if ! command -v inotifywait >/dev/null 2>&1; then
  log "FATAL: inotifywait not found — install inotify-tools (fixture-dev watcher requires it)"
  exit 1
fi

abs_path() {
  local p="${1}"
  if command -v realpath >/dev/null 2>&1; then
    realpath -m "${p}"
  else
    printf '%s\n' "${p}"
  fi
}

DEV_ABS="$(abs_path "${DEV_ROOT}")"
case "${DEV_ABS}" in
  */EtherGold/dev|*/EtherGold/dev/) ;;
  *)
    log "FATAL: refuse watch root '${DEV_ABS}' (must be …/EtherGold/dev)"
    exit 1
    ;;
esac

DATA_DIR="${DEV_ABS}/data"
LOGS_DIR="${DEV_ABS}/logs"
mkdir -p "${DATA_DIR}" "${LOGS_DIR}"

is_interesting() {
  local f="${1}"
  case "${f}" in
    events.jsonl.*|packets.raw.*|inject_echo.jsonl.*|hw_debug.jsonl.*|wide_rx.bin.*)
      return 0
      ;;
    fixture_bridge.log.*|orchestrator-bridge.log.*|pogcc-com.log.*)
      return 0
      ;;
    uartd.log.*|uartd_*.log.*)
      return 0
      ;;
    *) return 1 ;;
  esac
}

run_worker() {
  # Serialize overlapping debounce completions.
  if mkdir "${LOCK_DIR}" 2>/dev/null; then
    trap 'rmdir "${LOCK_DIR}" 2>/dev/null || true' RETURN
    log "watcher: running offload_fixture_dev_rotated.sh"
    FIXTURE_DEV_OFFLOAD_TRUNCATE=0 bash "${WORKER}" || log "WARN: offload exit=$?"
  else
    log "watcher: offload already running — skip overlapping pass"
  fi
}

log "=== watch_fixture_dev_rotated (inotify) ==="
log "watching: ${DATA_DIR} ${LOGS_DIR}"
log "debounce_sec=${DEBOUNCE_SEC}"

# Catch stamps left while watcher was down.
run_worker

while true; do
  inotifywait -m -e create,moved_to,close_write \
    --format '%w|%e|%f' \
    "${DATA_DIR}" "${LOGS_DIR}" 2>>"${TRANSCRIPT}" \
  | while IFS='|' read -r _dir events file; do
      [[ -n "${file}" ]] || continue
      is_interesting "${file}" || continue
      log "inotify: ${events} ${file}"
      # Debounce: keep draining until quiet for DEBOUNCE_SEC.
      while IFS='|' read -r -t "${DEBOUNCE_SEC}" _dir2 events2 file2; do
        [[ -n "${file2}" ]] || continue
        if is_interesting "${file2}"; then
          log "inotify: ${events2} ${file2}"
        fi
      done || true
      run_worker
    done
  log "WARN: inotifywait exited — restarting in 2s"
  sleep 2
done
