#!/bin/bash
# Session Archive & Optimize
# Archives OpenClaw sessions older than 3 days
# Run daily at 4 AM PHT via cron

SESSIONS_DIR="$HOME/.openclaw/agents/main/sessions"
ARCHIVE_DIR="$SESSIONS_DIR/archive/$(date +%Y-%m)"
SESSIONS_JSON="$SESSIONS_DIR/sessions.json"
LOCK_FILE="$SESSIONS_JSON.lock"
MAIN_SESSION_ID=""

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"; }

# Validate environment
if [ ! -d "$SESSIONS_DIR" ]; then
  log "ERROR: Sessions directory not found: $SESSIONS_DIR"
  exit 1
fi

if [ ! -f "$SESSIONS_JSON" ]; then
  log "ERROR: sessions.json not found: $SESSIONS_JSON"
  exit 1
fi

log "=== Session Archive Starting ==="

# Wait for any existing lock (max 30 seconds)
WAIT_COUNT=0
while [ -f "$LOCK_FILE" ] && [ $WAIT_COUNT -lt 30 ]; do
  log "Waiting for lock..."
  sleep 1
  ((WAIT_COUNT++))
done

if [ -f "$LOCK_FILE" ]; then
  log "ERROR: Could not acquire lock after 30s. Aborting."
  exit 1
fi

# Create temp files
ARCHIVED_IDS_FILE=$(mktemp)
ARCHIVED_IDS_JSON=$(mktemp)

# Cleanup on exit (includes all temp and backup files)
cleanup() {
  rm -f "$LOCK_FILE" "$ARCHIVED_IDS_FILE" "$ARCHIVED_IDS_JSON"
  rm -f "$SESSIONS_JSON.bak" "$SESSIONS_JSON.tmp"
}
trap cleanup EXIT

# Create our lock
echo $$ > "$LOCK_FILE"

# Get main session ID (never archive this)
MAIN_SESSION_ID=$(jq -r '.["agent:main:main"].sessionId // empty' "$SESSIONS_JSON" 2>/dev/null)
if [ -n "$MAIN_SESSION_ID" ]; then
  log "Main session ID: $MAIN_SESSION_ID (protected)"
fi

# Create archive directory
mkdir -p "$ARCHIVE_DIR"

# Count before
BEFORE_COUNT=$(find "$SESSIONS_DIR" -maxdepth 1 -name "*.jsonl" -type f | wc -l)
BEFORE_SIZE=$(du -sh "$SESSIONS_DIR" 2>/dev/null | cut -f1)

log "Sessions before: $BEFORE_COUNT ($BEFORE_SIZE)"

# 1. Archive deleted sessions (*.deleted.*)
DELETED_COUNT=0
while IFS= read -r f; do
  [ -z "$f" ] && continue
  mv "$f" "$ARCHIVE_DIR/" && ((DELETED_COUNT++)) || true
done < <(find "$SESSIONS_DIR" -maxdepth 1 -name "*.deleted.*" -type f 2>/dev/null)

log "Archived $DELETED_COUNT deleted sessions"

# 2. Archive sessions older than 3 days (excluding main session)
OLD_COUNT=0
while IFS= read -r f; do
  [ -z "$f" ] && continue
  BASENAME=$(basename "$f")
  SESSION_ID="${BASENAME%.jsonl}"
  
  # Skip main session
  if [ "$SESSION_ID" = "$MAIN_SESSION_ID" ]; then
    log "Skipping main session: $SESSION_ID"
    continue
  fi
  
  # Only record ID if move succeeds
  if mv "$f" "$ARCHIVE_DIR/"; then
    echo "$SESSION_ID" >> "$ARCHIVED_IDS_FILE"
    ((OLD_COUNT++))
  else
    log "WARNING: Failed to archive $SESSION_ID"
  fi
done < <(find "$SESSIONS_DIR" -maxdepth 1 -name "*.jsonl" -mtime +3 -type f 2>/dev/null)

log "Archived $OLD_COUNT sessions older than 3 days"

# 3. Update sessions.json - remove archived entries
if [ -s "$ARCHIVED_IDS_FILE" ] && [ -f "$SESSIONS_JSON" ]; then
  log "=== Updating sessions.json ==="
  
  # Backup first
  cp "$SESSIONS_JSON" "$SESSIONS_JSON.bak"
  
  # Convert IDs to JSON array
  if ! jq -R -s 'split("\n") | map(select(length > 0))' "$ARCHIVED_IDS_FILE" > "$ARCHIVED_IDS_JSON"; then
    log "ERROR: Failed to create JSON array of archived IDs"
    mv "$SESSIONS_JSON.bak" "$SESSIONS_JSON"
  else
    # Filter out archived sessions
    if jq --slurpfile ids "$ARCHIVED_IDS_JSON" \
       'with_entries(select(.value.sessionId as $sid | ($ids[0] | index($sid)) == null))' \
       "$SESSIONS_JSON" > "$SESSIONS_JSON.tmp" 2>/dev/null; then
      mv "$SESSIONS_JSON.tmp" "$SESSIONS_JSON"
      REMOVED_COUNT=$(wc -l < "$ARCHIVED_IDS_FILE" | tr -d ' ')
      log "Removed $REMOVED_COUNT entries from sessions.json"
    else
      log "WARNING: jq filter failed, restoring backup"
      mv "$SESSIONS_JSON.bak" "$SESSIONS_JSON"
    fi
  fi
fi

# 4. Compact sessions.json
log "=== Compacting JSON ==="
if jq -c '.' "$SESSIONS_JSON" > "$SESSIONS_JSON.tmp" 2>/dev/null; then
  mv "$SESSIONS_JSON.tmp" "$SESSIONS_JSON"
  log "sessions.json compacted"
else
  log "WARNING: Could not compact sessions.json"
fi

# Count after
AFTER_COUNT=$(find "$SESSIONS_DIR" -maxdepth 1 -name "*.jsonl" -type f | wc -l)
AFTER_SIZE=$(du -sh "$SESSIONS_DIR" 2>/dev/null | cut -f1)

log "=== Archive Complete ==="
log "Sessions after: $AFTER_COUNT ($AFTER_SIZE)"
log "Total archived: $((DELETED_COUNT + OLD_COUNT))"
log "Archive location: $ARCHIVE_DIR"
log "Done."
