#!/usr/bin/env bash
# search-logs.sh  -  cross-project search across multi-agent agent-log.md files.
#
# Greps ~/.claude/logs/multi-agent/**/agent-log.md (or --root PATH) for a query,
# groups results by task, and ranks by (match_count × recency_weight).
#
# Prefers ripgrep (rg) for speed + sane defaults; falls back to GNU grep -rE.
#
# Usage:
#   search-logs.sh "query" [flags]
#
# Flags:
#   --root PATH           Override log root. Default: $HOME/.claude/logs/multi-agent
#   --project NAME        Filter to tasks under this project dir
#   --since SPEC          7d | 30d | 2026-04-01  -  drop tasks older than this
#   --phase N             Only match inside "## Phase N" sections
#   --semantic            v8.3+: query the per-repo triage corpus instead of
#                         agent-log.md grep. Returns past triage findings
#                         ranked by token overlap (token-based recall, no LLM).
#                         Honors --project as the repo-slug; --since/--phase ignored.
#   --json                JSON output (for automation)
#   --tsv                 Tab-separated output (for pipelines)
#   --limit N             Max tasks to return (default 20)
#   --help                Show this help
#
# Exit codes:
#   0   at least one match
#   1   no matches
#   64  bad arguments

set -uo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

ROOT="$HOME/.claude/logs/multi-agent"
PROJECT=""
SINCE=""
PHASE=""
JSON=0
TSV=0
LIMIT=20
QUERY=""
SEMANTIC=0

while [ $# -gt 0 ]; do
  case "$1" in
    --root)    ROOT="$2"; shift 2 ;;
    --project) PROJECT="$2"; shift 2 ;;
    --since)   SINCE="$2"; shift 2 ;;
    --phase)   PHASE="$2"; shift 2 ;;
    --json)    JSON=1; shift ;;
    --tsv)     TSV=1; shift ;;
    --semantic) SEMANTIC=1; shift ;;
    --limit)   LIMIT="$2"; shift 2 ;;
    --help|-h)
      awk 'NR==1{next} /^[^#]/{exit} {sub(/^# ?/,""); print}' "$0"
      exit 0
      ;;
    --*) echo "unknown flag: $1" >&2; exit 64 ;;
    *)
      if [ -z "$QUERY" ]; then
        QUERY="$1"
      else
        QUERY="$QUERY $1"
      fi
      shift
      ;;
  esac
done

if [ -z "$QUERY" ]; then
  echo "usage: search-logs.sh \"query\" [flags]" >&2
  exit 64
fi

# v8.3+  -  semantic mode: dispatch to triage-memory.mjs corpus query and exit.
# Honors --project as the repo-slug, --json (default off → human table),
# --limit (passed as --top N). --since/--phase have no meaning here.
if [ "$SEMANTIC" -eq 1 ]; then
  TM_SCRIPT="$SCRIPT_DIR/triage-memory.mjs"
  if [ ! -x "$TM_SCRIPT" ] && ! command -v node >/dev/null 2>&1; then
    echo "search-logs: --semantic requires node + triage-memory.mjs" >&2
    exit 1
  fi
  TM_ARGS=(query --issue "$QUERY" --top "$LIMIT")
  if [ -n "$PROJECT" ]; then TM_ARGS+=(--repo-slug "$PROJECT"); fi
  RESPONSE=$(node "$TM_SCRIPT" "${TM_ARGS[@]}" 2>/dev/null)
  RC=$?
  if [ "$JSON" -eq 1 ]; then
    printf '%s\n' "$RESPONSE"
    exit "$RC"
  fi
  # Human render
  hits=$(echo "$RESPONSE" | jq -r '.hits | length' 2>/dev/null || echo 0)
  if [ "$hits" = "0" ] || [ "$hits" = "" ]; then
    echo "no semantic hits"
    exit 1
  fi
  printf '%-12s %-10s %-10s %-40s %-6s\n' "TASK" "VERDICT" "SEV" "FILE" "SCORE"
  printf '%-12s %-10s %-10s %-40s %-6s\n' "----" "-------" "---" "----" "-----"
  echo "$RESPONSE" | jq -r '.hits[] | [.taskId, .classification, .severity, .file, .score] | @tsv' | \
    awk -F'\t' '{ printf "%-12s %-10s %-10s %-40s %-6s\n", $1, $2, $3, substr($4,1,40), $5 }'
  exit 0
fi

if [ ! -d "$ROOT" ]; then
  if [ "$JSON" -eq 1 ]; then
    printf '{ "query": "%s", "root": "%s", "matches": 0, "tasks": [] }\n' "$QUERY" "$ROOT"
    exit 1
  fi
  echo "search-logs: log root not found: $ROOT" >&2
  exit 1
fi

# --- Time filter resolution ----------------------------------------------

since_epoch=0
if [ -n "$SINCE" ]; then
  case "$SINCE" in
    *d)
      days="${SINCE%d}"
      since_epoch=$(date -v-"${days}"d +%s 2>/dev/null || date -d "-${days} days" +%s 2>/dev/null || echo 0)
      ;;
    *-*-*)
      since_epoch=$(date -j -f "%Y-%m-%d" "$SINCE" +%s 2>/dev/null || date -d "$SINCE" +%s 2>/dev/null || echo 0)
      ;;
    *)
      echo "search-logs: --since accepts '7d', '30d', or 'YYYY-MM-DD'" >&2
      exit 64
      ;;
  esac
fi

# --- Candidate file discovery --------------------------------------------

CANDIDATES=$(mktemp)
trap 'rm -f "$CANDIDATES" "$FILTERED" "$RESULTS"' EXIT

find "$ROOT" -type f -name "agent-log.md" 2>/dev/null > "$CANDIDATES"

FILTERED=$(mktemp)
while IFS= read -r f; do
  [ -z "$f" ] && continue
  # Project filter: path must contain /$PROJECT/
  if [ -n "$PROJECT" ] && ! echo "$f" | grep -qF "/$PROJECT/"; then
    continue
  fi
  # Since filter: drop files with mtime older than since_epoch
  if [ "$since_epoch" -gt 0 ]; then
    m=$(stat -c %Y "$f" 2>/dev/null || stat -f %m "$f" 2>/dev/null || echo 0)
    [ "$m" -lt "$since_epoch" ] && continue
  fi
  echo "$f" >> "$FILTERED"
done < "$CANDIDATES"

# --- Search executor -----------------------------------------------------

has_rg=0
command -v rg >/dev/null 2>&1 && has_rg=1

RESULTS=$(mktemp)
NOW=$(date +%s)

while IFS= read -r f; do
  [ -z "$f" ] && continue

  # If --phase N is set, extract only the "## Phase N" section and grep inside
  if [ -n "$PHASE" ]; then
    section=$(awk -v n="$PHASE" '
      BEGIN { inside = 0 }
      /^##[[:space:]]+Phase[[:space:]]+/ {
        if ($0 ~ "Phase[[:space:]]+" n "[^0-9]") { inside = 1 } else { inside = 0 }
      }
      inside { print }
    ' "$f")
    if [ -z "$section" ]; then continue; fi
    count=$(printf '%s\n' "$section" | grep -ciE "$QUERY" 2>/dev/null)
    first_match=$(printf '%s\n' "$section" | grep -iE "$QUERY" 2>/dev/null | head -1)
  else
    if [ "$has_rg" -eq 1 ]; then
      count=$(rg -c -i "$QUERY" "$f" 2>/dev/null)
      first_match=$(rg -i -m1 "$QUERY" "$f" 2>/dev/null | head -1)
    else
      count=$(grep -ciE "$QUERY" "$f" 2>/dev/null)
      first_match=$(grep -iE "$QUERY" "$f" 2>/dev/null | head -1)
    fi
  fi

  # Normalise count: empty (rg no-match) or non-numeric → 0
  [ -z "$count" ] && count=0
  case "$count" in
    ''|*[!0-9]*) count=0 ;;
  esac

  [ "$count" -eq 0 ] && continue

  # Task metadata
  task_id=$(basename "$(dirname "$f")")
  project=$(basename "$(dirname "$(dirname "$f")")")
  title=$(head -1 "$f" | sed 's/^# *//' | cut -c1-80)
  branch=$(grep -m1 -iE '^\*\*Branch\*\*' "$f" 2>/dev/null | sed -E 's/.*Branch\*\*: *([^ |]+).*/\1/' | head -c60)
  [ -z "$branch" ] && branch="(unknown)"
  mtime=$(stat -c %Y "$f" 2>/dev/null || stat -f %m "$f" 2>/dev/null || echo "$NOW")

  # Recency weight: 1.0 for last 7d, 0.5 for 7-30d, 0.2 older
  age_days=$(( (NOW - mtime) / 86400 ))
  if [ "$age_days" -le 7 ]; then
    weight=100
  elif [ "$age_days" -le 30 ]; then
    weight=50
  else
    weight=20
  fi
  score=$(( count * weight ))

  # Pack into single tab-delimited line: score task_id project branch mtime count title snippet
  printf '%d\t%s\t%s\t%s\t%d\t%d\t%s\t%s\n' \
    "$score" "$task_id" "$project" "$branch" "$mtime" "$count" "$title" "$first_match" >> "$RESULTS"

done < "$FILTERED"

# Sort by score desc, limit
sort -t$'\t' -k1,1nr "$RESULTS" | head -n "$LIMIT" > "${RESULTS}.sorted"
mv "${RESULTS}.sorted" "$RESULTS"

TOTAL_TASKS=$(wc -l < "$RESULTS" | tr -d ' ')

# --- Report ---------------------------------------------------------------

if [ "$JSON" -eq 1 ]; then
  printf '{\n  "query": %s,\n' "$(printf '%s' "$QUERY" | sed 's/\\/\\\\/g; s/"/\\"/g; s/.*/"&"/')"
  printf '  "root": "%s",\n' "$ROOT"
  [ -n "$PROJECT" ] && printf '  "project": "%s",\n' "$PROJECT"
  [ -n "$SINCE" ] && printf '  "since": "%s",\n' "$SINCE"
  [ -n "$PHASE" ] && printf '  "phase": "%s",\n' "$PHASE"
  printf '  "ripgrep": %s,\n' "$( [ "$has_rg" -eq 1 ] && echo true || echo false )"
  printf '  "matched_tasks": %d,\n' "$TOTAL_TASKS"
  printf '  "tasks": [\n'
  i=0
  while IFS=$'\t' read -r score task_id project branch mtime count title snippet; do
    i=$((i+1))
    jt=$(printf '%s' "$title" | sed 's/\\/\\\\/g; s/"/\\"/g')
    js=$(printf '%s' "$snippet" | sed 's/\\/\\\\/g; s/"/\\"/g')
    date=$(date -r "$mtime" "+%Y-%m-%d" 2>/dev/null || date -d "@$mtime" "+%Y-%m-%d" 2>/dev/null || echo "")
    printf '    { "task_id": "%s", "project": "%s", "branch": "%s", "date": "%s", "matches": %d, "score": %d, "title": "%s", "snippet": "%s" }' \
      "$task_id" "$project" "$branch" "$date" "$count" "$score" "$jt" "$js"
    [ "$i" -lt "$TOTAL_TASKS" ] && printf ','
    printf '\n'
  done < "$RESULTS"
  printf '  ]\n}\n'
elif [ "$TSV" -eq 1 ]; then
  printf 'score\ttask_id\tproject\tbranch\tdate\tmatches\ttitle\tsnippet\n'
  while IFS=$'\t' read -r score task_id project branch mtime count title snippet; do
    date=$(date -r "$mtime" "+%Y-%m-%d" 2>/dev/null || date -d "@$mtime" "+%Y-%m-%d" 2>/dev/null || echo "")
    printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' "$score" "$task_id" "$project" "$branch" "$date" "$count" "$title" "$snippet"
  done < "$RESULTS"
else
  # Colored text report
  if [ -t 1 ] && command -v tput >/dev/null 2>&1; then
    C_BLD=$(tput bold); C_DIM=$(tput dim); C_CYN=$(tput setaf 6); C_YEL=$(tput setaf 3); C_GRN=$(tput setaf 2); C_RST=$(tput sgr0)
  else
    C_BLD=""; C_DIM=""; C_CYN=""; C_YEL=""; C_GRN=""; C_RST=""
  fi

  if [ "$TOTAL_TASKS" -eq 0 ]; then
    printf '%ssearch-logs%s · query=%s\n' "$C_BLD" "$C_RST" "$QUERY"
    [ -n "$PROJECT" ] && printf '  project=%s' "$PROJECT"
    [ -n "$SINCE" ]   && printf '  since=%s'   "$SINCE"
    [ -n "$PHASE" ]   && printf '  phase=%s'   "$PHASE"
    printf '\n  ⓘ no matches\n'
    exit 1
  fi

  printf '%ssearch-logs%s · %d task%s · query=%s%s%s\n' \
    "$C_BLD" "$C_RST" "$TOTAL_TASKS" "$([ "$TOTAL_TASKS" -eq 1 ] || echo s)" "$C_CYN" "$QUERY" "$C_RST"
  [ -n "$PROJECT" ] && printf '  %sproject=%s%s\n' "$C_DIM" "$PROJECT" "$C_RST"
  [ -n "$SINCE" ]   && printf '  %ssince=%s%s\n'   "$C_DIM" "$SINCE" "$C_RST"
  [ -n "$PHASE" ]   && printf '  %sphase=%s%s\n'   "$C_DIM" "$PHASE" "$C_RST"
  [ "$has_rg" -eq 0 ] && printf '  %s(ripgrep not found, using grep)%s\n' "$C_DIM" "$C_RST"
  printf '\n'

  while IFS=$'\t' read -r score task_id project branch mtime count title snippet; do
    date=$(date -r "$mtime" "+%Y-%m-%d" 2>/dev/null || date -d "@$mtime" "+%Y-%m-%d" 2>/dev/null || echo "")
    printf '%s%s%s · %s%s%s · %s%s%s · %s%d match%s%s\n' \
      "$C_YEL" "$task_id" "$C_RST" "$C_DIM" "$project" "$C_RST" "$C_DIM" "$branch" "$C_RST" "$C_GRN" "$count" "$([ "$count" -eq 1 ] || echo es)" "$C_RST"
    [ -n "$title" ] && printf '  %s%s%s\n' "$C_BLD" "$title" "$C_RST"
    printf '  %s%s  ·  %s%s\n\n' "$C_DIM" "$date" "$(echo "$snippet" | head -c 140)" "$C_RST"
  done < "$RESULTS"
fi

[ "$TOTAL_TASKS" -gt 0 ] && exit 0 || exit 1
