#!/usr/bin/env bash
# logs-read.sh — Shell counterpart to the logs-read MCP tool.
#
# Mirrors the MCP tool's exact behaviour so the dev agent can retrieve
# session logs from the Pi over SSH with one call instead of constructing
# ad-hoc grep pipelines.
#
# Usage:
#   logs-read.sh <sessionKey> [type]       Session-key mode (grep across log files)
#   logs-read.sh --tail [type] [lines]     Tail most recent file of specified type
#
# Types: system, session, error, heartbeat, public, server
#
# Exit codes:
#   0  Success (output produced)
#   1  No matches found (clean, not an error)
#   2  Usage error or missing directory
set -euo pipefail

# --- Resolve PLATFORM_ROOT from script location ---
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLATFORM_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"

# --- Resolve account logs directory ---
# Phase 0: single account, resolved by glob. Errors if missing.
# Accounts live at {installDir}/data/accounts/ — outside the platform/ wipe zone.
INSTALL_DIR="$(dirname "$PLATFORM_ROOT")"

# --- Resolve server log (platform-scoped, not account-scoped) ---
# Convention: configDir = ".${installDir}" (e.g. installDir "maxy" → configDir ".maxy")
INSTALL_DIR_NAME=$(basename "$INSTALL_DIR")
CONFIG_DIR="$HOME/.$INSTALL_DIR_NAME"
SERVER_LOG="$CONFIG_DIR/logs/server.log"
VNC_LOG="$CONFIG_DIR/logs/vnc-boot.log"
REVIEW_LOG="$CONFIG_DIR/logs/review.log"

ACCOUNTS_DIR="$INSTALL_DIR/data/accounts"
if [[ ! -d "$ACCOUNTS_DIR" ]]; then
  echo "Error: accounts directory does not exist: $ACCOUNTS_DIR" >&2
  exit 2
fi

# Glob for account dirs — Phase 0 expects exactly one
shopt -s nullglob
ACCOUNT_DIRS=("$ACCOUNTS_DIR"/*/)
shopt -u nullglob
if [[ ${#ACCOUNT_DIRS[@]} -eq 0 ]]; then
  echo "Error: no account directories found in $ACCOUNTS_DIR" >&2
  exit 2
fi

LOG_DIR="${ACCOUNT_DIRS[0]}logs"
if [[ ! -d "$LOG_DIR" ]]; then
  echo "Log directory does not exist: $LOG_DIR" >&2
  exit 2
fi

# --- Prefix map (mirrors MCP tool exactly) ---
# Function instead of associative array for bash 3.x compatibility (macOS testing).
prefix_for_type() {
  case "$1" in
    system)  echo "claude-agent-stream-" ;;
    error)   echo "claude-agent-stderr-" ;;
    session) echo "sse-events-" ;;
    public)  echo "public-agent-stream-" ;;
    mcp)     echo "mcp-" ;;
    *)       echo "" ;;
  esac
}

# All searchable types (excludes heartbeat — no session context in heartbeat logs)
SEARCH_TYPES="system error session public server mcp vnc review"
VALID_TYPES="system, session, error, heartbeat, public, server, mcp, vnc, review"

# --- Usage ---
usage() {
  cat >&2 <<EOF
Usage:
  logs-read.sh <sessionKey> [type]       Grep logs for session key
  logs-read.sh --tail [type] [lines]     Tail most recent log file

Types: $VALID_TYPES
Default type: system | Default lines: 50
EOF
  exit 2
}

# --- Validate type ---
validate_type() {
  local t="$1"
  case "$t" in
    system|session|error|heartbeat|public|server|mcp|vnc|review) return 0 ;;
    *) echo "Error: invalid type '$t'. Valid types: $VALID_TYPES" >&2; exit 2 ;;
  esac
}

# --- Session-key mode ---
session_key_mode() {
  local session_key="$1"
  local filter_type="${2:-}"

  # Guard against empty session key (grep -F "" matches everything)
  if [[ -z "$session_key" ]]; then
    echo "Error: session key cannot be empty" >&2
    exit 2
  fi

  if [[ -n "$filter_type" ]]; then
    validate_type "$filter_type"
  fi

  # Determine which types to search
  local types_to_search
  if [[ -n "$filter_type" && "$filter_type" != "heartbeat" ]]; then
    types_to_search="$filter_type"
  else
    types_to_search="$SEARCH_TYPES"
  fi

  local found=0

  for log_type in $types_to_search; do
    # server: single file in configDir (platform-scoped, not account-scoped)
    if [[ "$log_type" == "server" ]]; then
      if [[ -f "$SERVER_LOG" ]]; then
        local result
        if result=$(grep -F "$session_key" "$SERVER_LOG" 2>/dev/null); then
          if [[ -n "$result" ]]; then
            [[ $found -gt 0 ]] && echo ""
            echo "## server.log (server)"
            echo "$result"
            found=$((found + 1))
          fi
        fi
      fi
      continue
    fi

    # vnc: single platform-scoped file covering the VNC browser viewer
    # lifecycle (boot events from vnc.sh + runtime events from vnc-logger.ts)
    if [[ "$log_type" == "vnc" ]]; then
      if [[ -f "$VNC_LOG" ]]; then
        local result
        if result=$(grep -F "$session_key" "$VNC_LOG" 2>/dev/null); then
          if [[ -n "$result" ]]; then
            [[ $found -gt 0 ]] && echo ""
            echo "## vnc-boot.log (vnc)"
            echo "$result"
            found=$((found + 1))
          fi
        fi
      fi
      continue
    fi

    # review: single platform-scoped file containing every decision made
    # by the in-process review detector — scan cycles, matches, suppressions,
    # rate-limit decisions, rule mutations, and admin tool audit trail.
    # Task 385 — the one log that proves observability-plus-review is working.
    if [[ "$log_type" == "review" ]]; then
      if [[ -f "$REVIEW_LOG" ]]; then
        local result
        if result=$(grep -F "$session_key" "$REVIEW_LOG" 2>/dev/null); then
          if [[ -n "$result" ]]; then
            [[ $found -gt 0 ]] && echo ""
            echo "## review.log (review)"
            echo "$result"
            found=$((found + 1))
          fi
        fi
      fi
      continue
    fi

    local prefix
    prefix=$(prefix_for_type "$log_type")
    [[ -z "$prefix" ]] && continue

    # Find matching files, sorted chronologically by name (date suffix)
    shopt -s nullglob
    local files=("$LOG_DIR"/${prefix}*.log)
    shopt -u nullglob

    # Sort by filename (date suffix ensures chronological order)
    IFS=$'\n' files=($(printf '%s\n' "${files[@]}" | sort)); unset IFS

    for filepath in "${files[@]}"; do
      local file
      file=$(basename "$filepath")

      # grep -F: fixed string match. Exit 1 = no match (expected).
      local result
      if result=$(grep -F "$session_key" "$filepath" 2>/dev/null); then
        if [[ -n "$result" ]]; then
          [[ $found -gt 0 ]] && echo ""
          echo "## $file ($log_type)"
          echo "$result"
          found=$((found + 1))
        fi
      fi
    done
  done

  if [[ $found -eq 0 ]]; then
    echo "No log lines found for session key \"$session_key\"."
    exit 1
  fi

  exit 0
}

# --- Tail mode ---
tail_mode() {
  local log_type="${1:-system}"
  local lines="${2:-50}"

  validate_type "$log_type"

  # Validate lines is numeric
  if ! [[ "$lines" =~ ^[0-9]+$ ]]; then
    echo "Error: lines must be a number, got '$lines'" >&2
    exit 2
  fi

  # Heartbeat: single fixed file (account-scoped)
  if [[ "$log_type" == "heartbeat" ]]; then
    local hb_file="$LOG_DIR/check-due-events.log"
    if [[ ! -f "$hb_file" ]]; then
      echo "No heartbeat log found yet. The platform cron may not have run."
      exit 1
    fi
    echo "# check-due-events.log"
    echo ""
    tail -n "$lines" "$hb_file"
    exit 0
  fi

  # Server: single fixed file (platform-scoped, in configDir)
  if [[ "$log_type" == "server" ]]; then
    if [[ ! -f "$SERVER_LOG" ]]; then
      echo "No server log found at $SERVER_LOG"
      exit 1
    fi
    echo "# server.log"
    echo ""
    tail -n "$lines" "$SERVER_LOG"
    exit 0
  fi

  # VNC: single platform-scoped file covering the entire VNC browser
  # viewer lifecycle (Xtigervnc boot, websockify, Chromium CDP, HTTP
  # viewer fetches, WebSocket upgrades, proxy pipe events, MCP browser
  # tool calls, client disconnect reasons, ensureVnc/ensureCdp recovery).
  # Single retrieval must diagnose any browser-viewer failure mode.
  if [[ "$log_type" == "vnc" ]]; then
    if [[ ! -f "$VNC_LOG" ]]; then
      echo "No vnc-boot log found at $VNC_LOG"
      exit 1
    fi
    echo "# vnc-boot.log"
    echo ""
    tail -n "$lines" "$VNC_LOG"
    exit 0
  fi

  # Review: single platform-scoped file written by the review detector
  # (Task 385). Every scan cycle, rule match, suppression decision, rate
  # limit hold-back, and admin-tool rule mutation is logged here. This is
  # the canonical log to audit "did the detector see this?" questions.
  if [[ "$log_type" == "review" ]]; then
    if [[ ! -f "$REVIEW_LOG" ]]; then
      echo "No review log found at $REVIEW_LOG (detector may not have started yet)"
      exit 1
    fi
    echo "# review.log"
    echo ""
    tail -n "$lines" "$REVIEW_LOG"
    exit 0
  fi

  # Find most recent file by mtime
  local prefix
  prefix=$(prefix_for_type "$log_type")

  shopt -s nullglob
  local files=("$LOG_DIR"/${prefix}*.log)
  shopt -u nullglob

  if [[ ${#files[@]} -eq 0 ]]; then
    echo "No log file found for type '$log_type' in $LOG_DIR"
    exit 1
  fi

  # Sort by mtime descending — most recent first
  local match
  match=$(ls -t "${files[@]}" | head -1)
  match=$(basename "$match")

  echo "# $match"
  echo ""
  tail -n "$lines" "$LOG_DIR/$match"
  exit 0
}

# --- Main ---
if [[ $# -eq 0 ]]; then
  usage
fi

case "$1" in
  --tail)
    shift
    tail_mode "${1:-system}" "${2:-50}"
    ;;
  --help|-h)
    usage
    ;;
  -*)
    echo "Error: unknown option '$1'" >&2
    usage
    ;;
  *)
    session_key_mode "$1" "${2:-}"
    ;;
esac
