#!/usr/bin/env bash
# auto-commit-guard.sh — Background daemon that auto-commits uncommitted work
#
# Usage: auto-commit-guard.sh [interval_seconds] [worktree_base]
#   auto-commit-guard.sh          # defaults: 120s, ~/worktrees
#   auto-commit-guard.sh 60       # check every 60s
#   auto-commit-guard.sh 180 ~/my-worktrees
#
# Scans all git repos under the worktree base for uncommitted changes.
# If dirty for >= 1 check cycle, auto-commits with a WIP message.
# Pushes unpushed commits so work is always recoverable from the remote.
#
# Also scans /tmp for orphaned agent workdirs on startup.

set -uo pipefail

INTERVAL="${1:-120}"
WORKTREE_BASE="${2:-$HOME/worktrees}"
LOG_DIR="$HOME/.hermes/logs"
LOG="$LOG_DIR/auto-commit-guard.log"
PIDFILE="$LOG_DIR/auto-commit-guard.pid"
ORPHAN_SCAN_DONE="$LOG_DIR/.orphan-scan-done"

mkdir -p "$LOG_DIR"

# Single instance guard
if [ -f "$PIDFILE" ]; then
  old_pid=$(cat "$PIDFILE")
  if kill -0 "$old_pid" 2>/dev/null; then
    echo "auto-commit-guard already running (PID $old_pid)" >&2
    exit 0
  fi
fi
echo $$ > "$PIDFILE"
trap 'rm -f "$PIDFILE"' EXIT

log() {
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] AUTO-COMMIT: $*" >> "$LOG"
}

# --- Orphaned workdir scan (runs once on startup) ---
scan_orphans() {
  if [ -f "$ORPHAN_SCAN_DONE" ]; then
    return 0
  fi
  log "Scanning /tmp for orphaned agent workdirs..."
  local found=0
  local rescued=0

  for dir in /tmp/*-work-* /tmp/timmy-burn-* /tmp/tc-burn; do
    [ -d "$dir" ] || continue
    [ -d "$dir/.git" ] || continue

    found=$((found + 1))
    cd "$dir" 2>/dev/null || continue

    local dirty
    dirty=$(git status --porcelain 2>/dev/null | wc -l | tr -d " ")
    if [ "${dirty:-0}" -gt 0 ]; then
      local branch
      branch=$(git branch --show-current 2>/dev/null || echo "orphan")
      git add -A 2>/dev/null
      if git commit -m "WIP: orphan rescue — $dirty file(s) auto-committed on $(date -u +%Y-%m-%dT%H:%M:%SZ)

Orphaned workdir detected at $dir.
Branch: $branch
Rescued by auto-commit-guard on startup." 2>/dev/null; then
        rescued=$((rescued + 1))
        log "RESCUED: $dir ($dirty files on branch $branch)"

        # Try to push if remote exists
        if git remote get-url origin >/dev/null 2>&1; then
          git push -u origin "$branch" 2>/dev/null &&             log "PUSHED orphan rescue: $dir → $branch" ||             log "PUSH FAILED orphan rescue: $dir (no remote access)"
        fi
      fi
    fi
  done

  log "Orphan scan complete: $found workdirs checked, $rescued rescued"
  touch "$ORPHAN_SCAN_DONE"
}

# --- Main guard loop ---
guard_cycle() {
  local committed=0
  local scanned=0

  # Scan worktree base
  if [ -d "$WORKTREE_BASE" ]; then
    for dir in "$WORKTREE_BASE"/*/; do
      [ -d "$dir" ] || continue
      [ -d "$dir/.git" ] || continue

      scanned=$((scanned + 1))
      cd "$dir" 2>/dev/null || continue

      local dirty
      dirty=$(git status --porcelain 2>/dev/null | wc -l | tr -d " ")
      [ "${dirty:-0}" -eq 0 ] && continue

      local branch
      branch=$(git branch --show-current 2>/dev/null || echo "detached")

      git add -A 2>/dev/null
      if git commit -m "WIP: auto-commit — $dirty file(s) on $branch

Automated commit by auto-commit-guard at $(date -u +%Y-%m-%dT%H:%M:%SZ).
Work preserved to prevent loss on crash." 2>/dev/null; then
        committed=$((committed + 1))
        log "COMMITTED: $dir ($dirty files, branch $branch)"

        # Push to preserve remotely
        if git remote get-url origin >/dev/null 2>&1; then
          git push -u origin "$branch" 2>/dev/null &&             log "PUSHED: $dir → $branch" ||             log "PUSH FAILED: $dir (will retry next cycle)"
        fi
      fi
    done
  fi

  # Also scan /tmp for agent workdirs
  for dir in /tmp/*-work-*; do
    [ -d "$dir" ] || continue
    [ -d "$dir/.git" ] || continue

    scanned=$((scanned + 1))
    cd "$dir" 2>/dev/null || continue

    local dirty
    dirty=$(git status --porcelain 2>/dev/null | wc -l | tr -d " ")
    [ "${dirty:-0}" -eq 0 ] && continue

    local branch
    branch=$(git branch --show-current 2>/dev/null || echo "detached")

    git add -A 2>/dev/null
    if git commit -m "WIP: auto-commit — $dirty file(s) on $branch

Automated commit by auto-commit-guard at $(date -u +%Y-%m-%dT%H:%M:%SZ).
Agent workdir preserved to prevent loss." 2>/dev/null; then
      committed=$((committed + 1))
      log "COMMITTED: $dir ($dirty files, branch $branch)"

      if git remote get-url origin >/dev/null 2>&1; then
        git push -u origin "$branch" 2>/dev/null &&           log "PUSHED: $dir → $branch" ||           log "PUSH FAILED: $dir (will retry next cycle)"
      fi
    fi
  done

  [ "$committed" -gt 0 ] && log "Cycle done: $scanned scanned, $committed committed"
}

# --- Entry point ---
log "Starting auto-commit-guard (interval=${INTERVAL}s, worktree=${WORKTREE_BASE})"
scan_orphans

while true; do
  guard_cycle
  sleep "$INTERVAL"
done
