#!/usr/bin/env bash
set -euo pipefail

VERSION="0.4.1"
FORMAT="markdown"
WITH_CODEX_VERSION=0
CHECK_LATEST_CODEX=0
WITH_CODEX_DOCTOR=0
COMPARE_FILE=""
COMPARE_REQUESTED=0
COMPARE_LOADED=0
COMPARE_NOTE="not requested; pass --compare <previous-report.json> to compare metadata deltas"
SESSIONS_TOTAL_ADVISORY_BYTES=""
SESSIONS_DAILY_GROWTH_ADVISORY_BYTES=""
SESSIONS_ADVISORY_REQUESTED=0
COMMAND="check"

usage() {
  cat <<'USAGE'
codex-healthkit - local metadata health checks for daily Codex operators

Usage:
  codex-healthkit check [--markdown|--json] [--compare <previous-report.json>] [--sessions-total-advisory-bytes <bytes>] [--sessions-daily-growth-advisory-bytes <bytes>] [--with-codex-version] [--check-latest-codex] [--with-codex-doctor]
  codex-healthkit --version
  codex-healthkit --help

Default behavior:
  Performs local file metadata checks only. It does not read auth files,
  SQLite contents, session transcript contents, token files, or cookies, and
  it does not execute the external codex command.

Optional:
  --compare <previous-report.json> compares current metadata with an explicit
     previous codex-healthkit JSON report. Requires jq. Does not store history.
  --sessions-total-advisory-bytes <bytes> flags large_total when the current
     active sessions directory meets the explicit byte threshold. Requires
     --compare. Does not change summary status or exit code.
  --sessions-daily-growth-advisory-bytes <bytes> flags rapid_growth when the
     daily-normalized active sessions increase meets the explicit byte
     threshold. Requires --compare. Does not change summary status or exit code.
  --with-codex-version runs `codex --version`.
  --check-latest-codex also checks the official npm stable dist-tag through an
     HTTPS metadata request. It implies --with-codex-version, never installs or
     updates Codex, and does not change summary status or exit code.
  --with-codex-doctor runs official `codex doctor --json` and extracts only
     redacted summary fields (status, ok/warn/fail counts, and a note). Raw
     doctor output is not included. Codex CLI may perform provider reachability
     checks through the existing Codex configuration when this option is enabled.
USAGE
}

die() {
  printf 'codex-healthkit: %s\n' "$*" >&2
  exit 2
}

safe_text() {
  LC_ALL=C tr '\001-\037\177' ' '
}

json_string() {
  local text
  text="$(printf '%s' "$1" | safe_text)"
  text="${text//\\/\\\\}"
  text="${text//\"/\\\"}"
  printf '"%s"' "$text"
}

markdown_inline() {
  local text
  text="$(printf '%s' "$1" | safe_text)"
  text="${text//\\/\\\\}"
  text="${text//|/\\|}"
  text="${text//\`/\\\`}"
  printf '%s' "$text"
}

bool_json() {
  if [ "$1" = "1" ]; then
    printf 'true'
  else
    printf 'false'
  fi
}

nullable_bool_json() {
  case "$1" in
    1) printf 'true' ;;
    0) printf 'false' ;;
    *) printf 'null' ;;
  esac
}

update_available_markdown() {
  case "$1" in
    1) printf 'yes' ;;
    0) printf 'no' ;;
    *) printf 'unavailable' ;;
  esac
}

nullable_json_string() {
  if [ -n "$1" ]; then
    json_string "$1"
  else
    printf 'null'
  fi
}

valid_semver() {
  printf '%s' "$1" | LC_ALL=C grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'
}

semver_is_newer() {
  local candidate="$1" current="$2"
  local candidate_base current_base candidate_suffix current_suffix
  local candidate_major candidate_minor candidate_patch
  local current_major current_minor current_patch

  candidate_base="${candidate%%-*}"
  current_base="${current%%-*}"
  candidate_suffix="${candidate#"$candidate_base"}"
  current_suffix="${current#"$current_base"}"

  IFS=. read -r candidate_major candidate_minor candidate_patch <<EOF
$candidate_base
EOF
  IFS=. read -r current_major current_minor current_patch <<EOF
$current_base
EOF

  if [ "$candidate_major" -ne "$current_major" ]; then
    [ "$candidate_major" -gt "$current_major" ]
    return
  fi
  if [ "$candidate_minor" -ne "$current_minor" ]; then
    [ "$candidate_minor" -gt "$current_minor" ]
    return
  fi
  if [ "$candidate_patch" -ne "$current_patch" ]; then
    [ "$candidate_patch" -gt "$current_patch" ]
    return
  fi

  [ -z "$candidate_suffix" ] && [ -n "$current_suffix" ]
}

codex_update_json_fragment() {
  if [ "$LATEST_CODEX_REQUESTED" -ne 1 ]; then
    return
  fi

  cat <<JSON
,
  "codex_update": {
    "requested": true,
    "checked": $(bool_json "$LATEST_CODEX_CHECKED"),
    "executable_path": $(nullable_json_string "$CODEX_EXECUTABLE"),
    "current_version": $(nullable_json_string "$CURRENT_CODEX_SEMVER"),
    "latest_version": $(nullable_json_string "$LATEST_CODEX_VERSION"),
    "update_available": $(nullable_bool_json "$CODEX_UPDATE_AVAILABLE"),
    "source": "npm:@openai/codex dist-tag latest",
    "checked_at": $(json_string "$GENERATED_AT"),
    "note": $(json_string "$LATEST_CODEX_NOTE")
  }
JSON
}

run_codex_update_check() {
  local response latest

  LATEST_CODEX_REQUESTED="$CHECK_LATEST_CODEX"
  LATEST_CODEX_CHECKED=0
  CURRENT_CODEX_SEMVER=""
  LATEST_CODEX_VERSION=""
  CODEX_UPDATE_AVAILABLE=""
  LATEST_CODEX_NOTE="not requested; pass --check-latest-codex for an opt-in stable version check"

  if [ "$CHECK_LATEST_CODEX" -ne 1 ]; then
    return
  fi

  if ! command -v curl >/dev/null 2>&1; then
    LATEST_CODEX_NOTE="curl is required for the opt-in stable version check"
    return
  fi
  if ! command -v jq >/dev/null 2>&1; then
    LATEST_CODEX_NOTE="jq is required to parse the opt-in stable version response"
    return
  fi

  response="$(curl -q --proto '=https' --tlsv1.2 --max-time 5 --retry 0 --silent --show-error --fail \
    --header 'Accept: application/json' \
    'https://registry.npmjs.org/@openai%2Fcodex/latest' 2>/dev/null)" || {
    LATEST_CODEX_NOTE="official npm stable version check failed; no update was performed"
    return
  }

  latest="$(printf '%s' "$response" | jq -er '.version | select(type == "string")' 2>/dev/null)" || {
    LATEST_CODEX_NOTE="official npm response did not contain a valid version; no update was performed"
    return
  }
  if ! valid_semver "$latest"; then
    LATEST_CODEX_NOTE="official npm response contained an invalid version; no update was performed"
    return
  fi

  LATEST_CODEX_CHECKED=1
  LATEST_CODEX_VERSION="$latest"
  case "$CODEX_VERSION" in
    'codex-cli '*) CURRENT_CODEX_SEMVER="${CODEX_VERSION#codex-cli }" ;;
  esac

  if ! valid_semver "$CURRENT_CODEX_SEMVER"; then
    CURRENT_CODEX_SEMVER=""
    LATEST_CODEX_NOTE="stable version checked, but the installed Codex version could not be compared"
    return
  fi

  if semver_is_newer "$LATEST_CODEX_VERSION" "$CURRENT_CODEX_SEMVER"; then
    CODEX_UPDATE_AVAILABLE=1
    LATEST_CODEX_NOTE="a newer stable Codex CLI version is available; no update was performed"
  else
    CODEX_UPDATE_AVAILABLE=0
    LATEST_CODEX_NOTE="installed Codex CLI is current relative to the stable npm dist-tag"
  fi
}

bytes_for() {
  local path="$1"
  if [ ! -e "$path" ] || [ -L "$path" ]; then
    printf '0'
    return
  fi

  if stat -f '%z' "$path" >/dev/null 2>&1; then
    stat -f '%z' "$path" 2>/dev/null || printf '0'
    return
  fi

  if stat -c '%s' "$path" >/dev/null 2>&1; then
    stat -c '%s' "$path" 2>/dev/null || printf '0'
    return
  fi

  printf '0'
}

tree_bytes_for() {
  local path="$1"
  if [ ! -e "$path" ] || [ -L "$path" ]; then
    printf '0'
    return
  fi

  if [ -d "$path" ]; then
    du -sk "$path" 2>/dev/null | awk '{printf "%d", $1 * 1024}' || printf '0'
    return
  fi

  bytes_for "$path"
}

human_size_for() {
  local path="$1"
  if [ ! -e "$path" ] || [ -L "$path" ]; then
    printf '0B'
    return
  fi

  du -sh "$path" 2>/dev/null | awk '{print $1}' || printf '0B'
}

count_jsonl_files() {
  local path="$1"
  if [ ! -d "$path" ] || [ -L "$path" ]; then
    printf '0'
    return
  fi

  { find "$path" -type f -name '*.jsonl' -print 2>/dev/null || true; } | wc -l | tr -d '[:space:]'
}

count_session_files() {
  local path="$1"
  if [ ! -d "$path" ] || [ -L "$path" ]; then
    printf '0'
    return
  fi

  { find "$path" -type f \( -name '*.jsonl' -o -name '*.jsonl.zst' \) -print 2>/dev/null || true; } | wc -l | tr -d '[:space:]'
}

path_exists_bool() {
  local path="$1"
  if [ -e "$path" ] && [ ! -L "$path" ]; then
    printf '1'
  else
    printf '0'
  fi
}

resolve_sqlite_home() {
  local raw="${CODEX_SQLITE_HOME:-${CODEX_HOME:-$HOME/.codex}}"
  case "$raw" in
    /*) printf '%s' "$raw" ;;
    *) printf '%s/%s' "$PWD" "$raw" ;;
  esac
}

health_note() {
  local db_bytes="$1"
  local wal_bytes="$2"
  local gib=$((1024 * 1024 * 1024))
  local mib=$((1024 * 1024))

  if [ "$db_bytes" -ge $((2 * gib)) ] || [ "$wal_bytes" -ge $((500 * mib)) ]; then
    printf 'watch: log DB or WAL is large; compare with a previous check.'
  elif [ "$wal_bytes" -ge $((100 * mib)) ]; then
    printf 'watch: WAL is above 100MB; check again after normal use.'
  else
    printf 'ok: no large WAL spike detected by size-only check.'
  fi
}

overall_status_for() {
  local db_bytes="$1"
  local wal_bytes="$2"
  local gib=$((1024 * 1024 * 1024))
  local mib=$((1024 * 1024))

  if [ "$db_bytes" -ge $((2 * gib)) ] || [ "$wal_bytes" -ge $((100 * mib)) ]; then
    printf 'watch'
  else
    printf 'ok'
  fi
}

human_bytes_value() {
  local bytes="$1"
  local abs="$bytes"

  if [ "$abs" -lt 0 ]; then
    abs=$((-abs))
  fi

  if [ "$abs" -ge 1073741824 ]; then
    awk -v bytes="$abs" 'BEGIN { printf "%.1fG", bytes / 1073741824 }'
  elif [ "$abs" -ge 1048576 ]; then
    awk -v bytes="$abs" 'BEGIN { printf "%.1fM", bytes / 1048576 }'
  elif [ "$abs" -ge 1024 ]; then
    awk -v bytes="$abs" 'BEGIN { printf "%.1fK", bytes / 1024 }'
  else
    printf '%dB' "$abs"
  fi
}

signed_human_delta_bytes() {
  local delta="$1"
  if [ "$delta" -gt 0 ]; then
    printf '+%s' "$(human_bytes_value "$delta")"
  elif [ "$delta" -lt 0 ]; then
    printf -- '-%s' "$(human_bytes_value "$delta")"
  else
    printf '0B'
  fi
}

signed_delta_count() {
  local delta="$1"
  if [ "$delta" -gt 0 ]; then
    printf '+%d' "$delta"
  else
    printf '%d' "$delta"
  fi
}

direction_for_delta() {
  local delta="$1"
  if [ "$delta" -gt 0 ]; then
    printf 'increased'
  elif [ "$delta" -lt 0 ]; then
    printf 'decreased'
  else
    printf 'unchanged'
  fi
}

positive_integer() {
  local prefix suffix

  case "$1" in
    ''|*[!0-9]*|0) return 1 ;;
  esac

  if [ "${#1}" -gt 19 ]; then
    return 1
  fi

  if [ "${#1}" -eq 19 ]; then
    prefix="${1%??????????}"
    suffix="${1#?????????}"
    if [ "$prefix" -gt 922337203 ] ||
      { [ "$prefix" -eq 922337203 ] && [ "$suffix" -gt 6854775807 ]; }; then
      return 1
    fi
  fi

  return 0
}

timestamp_epoch() {
  local value="$1" parsed

  case "$value" in
    ????-??-??T??:??:??Z) ;;
    *) return 1 ;;
  esac

  if parsed="$(LC_ALL=C date -j -u -f '%Y-%m-%dT%H:%M:%SZ' "$value" '+%s' 2>/dev/null)"; then
    printf '%s' "$parsed"
    return
  fi

  if parsed="$(LC_ALL=C date -u -d "$value" '+%s' 2>/dev/null)"; then
    printf '%s' "$parsed"
    return
  fi

  return 1
}

advisory_reasons_json() {
  local separator=""
  printf '['
  if [ "$ADVISORY_LARGE_TOTAL" -eq 1 ]; then
    printf '%s"large_total"' "$separator"
    separator=", "
  fi
  if [ "$ADVISORY_RAPID_GROWTH" -eq 1 ]; then
    printf '%s"rapid_growth"' "$separator"
  fi
  printf ']'
}

advisory_json_fragment() {
  if [ "$SESSIONS_ADVISORY_REQUESTED" -ne 1 ]; then
    return
  fi

  cat <<JSON
,
    "advisory": {
      "requested": true,
      "triggered": $(bool_json "$SESSIONS_ADVISORY_TRIGGERED"),
      "reasons": $(advisory_reasons_json),
      "thresholds": {
        "sessions_total_bytes": $(if [ -n "$SESSIONS_TOTAL_ADVISORY_BYTES" ]; then printf '%s' "$SESSIONS_TOTAL_ADVISORY_BYTES"; else printf 'null'; fi),
        "sessions_daily_growth_bytes": $(if [ -n "$SESSIONS_DAILY_GROWTH_ADVISORY_BYTES" ]; then printf '%s' "$SESSIONS_DAILY_GROWTH_ADVISORY_BYTES"; else printf 'null'; fi)
      },
      "note": $(json_string "$SESSIONS_ADVISORY_NOTE")
    }
JSON
}

previous_number() {
  local filter="$1"
  jq -er "$filter // 0 | if type == \"number\" then . else 0 end" "$COMPARE_FILE" 2>/dev/null || printf '0'
}

previous_string() {
  local filter="$1"
  jq -r "$filter // \"\"" "$COMPARE_FILE" 2>/dev/null || printf ''
}

comparison_json() {
  if [ "$COMPARE_REQUESTED" -ne 1 ]; then
    cat <<JSON
{
    "requested": false,
    "loaded": false,
    "note": $(json_string "$COMPARE_NOTE")
  }
JSON
    return
  fi

  cat <<JSON
{
    "requested": true,
    "loaded": $(bool_json "$COMPARE_LOADED"),
    "previous_generated_at": $(json_string "$PREVIOUS_GENERATED_AT"),
    "note": $(json_string "$COMPARE_NOTE"),
    "items": {
      "logs_2_sqlite_wal": {
        "previous_bytes": $PREV_LOG_WAL_BYTES,
        "current_bytes": $LOG_WAL_BYTES,
        "delta_bytes": $DELTA_LOG_WAL_BYTES,
        "direction": $(json_string "$(direction_for_delta "$DELTA_LOG_WAL_BYTES")")
      },
      "logs_2_sqlite": {
        "previous_bytes": $PREV_LOG_DB_BYTES,
        "current_bytes": $LOG_DB_BYTES,
        "delta_bytes": $DELTA_LOG_DB_BYTES,
        "direction": $(json_string "$(direction_for_delta "$DELTA_LOG_DB_BYTES")")
      },
      "sessions_bytes": {
        "previous_bytes": $PREV_SESSIONS_BYTES,
        "current_bytes": $SESSIONS_BYTES,
        "delta_bytes": $DELTA_SESSIONS_BYTES,
        "direction": $(json_string "$(direction_for_delta "$DELTA_SESSIONS_BYTES")")
      },
      "sessions_jsonl_count": {
        "previous_count": $PREV_SESSIONS_COUNT,
        "current_count": $SESSIONS_COUNT,
        "delta_count": $DELTA_SESSIONS_COUNT,
        "direction": $(json_string "$(direction_for_delta "$DELTA_SESSIONS_COUNT")")
      },
      "archived_sessions_bytes": {
        "previous_bytes": $PREV_ARCHIVED_BYTES,
        "current_bytes": $ARCHIVED_BYTES,
        "delta_bytes": $DELTA_ARCHIVED_BYTES,
        "direction": $(json_string "$(direction_for_delta "$DELTA_ARCHIVED_BYTES")")
      },
      "archived_sessions_jsonl_count": {
        "previous_count": $PREV_ARCHIVED_COUNT,
        "current_count": $ARCHIVED_COUNT,
        "delta_count": $DELTA_ARCHIVED_COUNT,
        "direction": $(json_string "$(direction_for_delta "$DELTA_ARCHIVED_COUNT")")
      },
      "quarantine_bytes": {
        "previous_bytes": $PREV_QUARANTINE_BYTES,
        "current_bytes": $QUARANTINE_BYTES,
        "delta_bytes": $DELTA_QUARANTINE_BYTES,
        "direction": $(json_string "$(direction_for_delta "$DELTA_QUARANTINE_BYTES")")
      }
    },
    "interval": {
      "valid": $(bool_json "$COMPARISON_INTERVAL_VALID"),
      "seconds": $(if [ "$COMPARISON_INTERVAL_VALID" -eq 1 ]; then printf '%s' "$COMPARISON_INTERVAL_SECONDS"; else printf 'null'; fi),
      "note": $(json_string "$COMPARISON_INTERVAL_NOTE")
    },
    "sessions_growth": {
      "delta_bytes": $DELTA_SESSIONS_BYTES,
      "bytes_per_day": $(if [ "$COMPARISON_INTERVAL_VALID" -eq 1 ]; then printf '%s' "$SESSIONS_GROWTH_BYTES_PER_DAY"; else printf 'null'; fi)
    }$(advisory_json_fragment)
  }
JSON
}

comparison_markdown() {
  if [ "$COMPARE_REQUESTED" -ne 1 ]; then
    return
  fi

  cat <<MARKDOWN

## Previous Report Comparison

- requested: \`yes\`
- previous_generated_at: \`$(markdown_inline "$PREVIOUS_GENERATED_AT")\`
- current_generated_at: \`$(markdown_inline "$GENERATED_AT")\`
- comparison_interval: \`$(if [ "$COMPARISON_INTERVAL_VALID" -eq 1 ]; then printf '%s seconds' "$COMPARISON_INTERVAL_SECONDS"; else printf 'unavailable'; fi)\`
- active_sessions_daily_growth: \`$(if [ "$COMPARISON_INTERVAL_VALID" -eq 1 ]; then signed_human_delta_bytes "$SESSIONS_GROWTH_BYTES_PER_DAY"; else printf 'unavailable'; fi) per day\`
- note: $(markdown_inline "$COMPARE_NOTE")

| item | previous | current | delta | note |
|---|---:|---:|---:|---|
| logs_2.sqlite-wal | $(human_bytes_value "$PREV_LOG_WAL_BYTES") | $(human_bytes_value "$LOG_WAL_BYTES") | $(signed_human_delta_bytes "$DELTA_LOG_WAL_BYTES") | size only; SQLite contents not read |
| logs_2.sqlite | $(human_bytes_value "$PREV_LOG_DB_BYTES") | $(human_bytes_value "$LOG_DB_BYTES") | $(signed_human_delta_bytes "$DELTA_LOG_DB_BYTES") | size only; SQLite contents not read |
| active sessions | $(human_bytes_value "$PREV_SESSIONS_BYTES") / $PREV_SESSIONS_COUNT | $(human_bytes_value "$SESSIONS_BYTES") / $SESSIONS_COUNT | $(signed_human_delta_bytes "$DELTA_SESSIONS_BYTES") / $(signed_delta_count "$DELTA_SESSIONS_COUNT") | file count only; transcript contents not read |
| archived sessions | $(human_bytes_value "$PREV_ARCHIVED_BYTES") / $PREV_ARCHIVED_COUNT | $(human_bytes_value "$ARCHIVED_BYTES") / $ARCHIVED_COUNT | $(signed_human_delta_bytes "$DELTA_ARCHIVED_BYTES") / $(signed_delta_count "$DELTA_ARCHIVED_COUNT") | normal growth can be expected; review before deleting |
| quarantine | $(human_bytes_value "$PREV_QUARANTINE_BYTES") | $(human_bytes_value "$QUARANTINE_BYTES") | $(signed_human_delta_bytes "$DELTA_QUARANTINE_BYTES") | metadata only |
MARKDOWN

  if [ "$SESSIONS_ADVISORY_REQUESTED" -eq 1 ]; then
    cat <<MARKDOWN

### Sessions Advisory

- triggered: \`$(if [ "$SESSIONS_ADVISORY_TRIGGERED" -eq 1 ]; then printf 'yes'; else printf 'no'; fi)\`
- reasons: \`$(if [ "$SESSIONS_ADVISORY_TRIGGERED" -eq 1 ]; then advisory_reasons_json; else printf '[]'; fi)\`
- total threshold: \`$(if [ -n "$SESSIONS_TOTAL_ADVISORY_BYTES" ]; then printf '%s bytes' "$SESSIONS_TOTAL_ADVISORY_BYTES"; else printf 'not set'; fi)\`
- daily growth threshold: \`$(if [ -n "$SESSIONS_DAILY_GROWTH_ADVISORY_BYTES" ]; then printf '%s bytes/day' "$SESSIONS_DAILY_GROWTH_ADVISORY_BYTES"; else printf 'not set'; fi)\`
- note: $(markdown_inline "$SESSIONS_ADVISORY_NOTE")
MARKDOWN
  fi
}

load_previous_report() {
  local previous_tool previous_epoch current_epoch

  if [ "$COMPARE_REQUESTED" -ne 1 ]; then
    return
  fi

  if [ ! -r "$COMPARE_FILE" ]; then
    die "--compare file is not readable"
  fi

  if ! command -v jq >/dev/null 2>&1; then
    die "--compare requires jq to read a previous codex-healthkit JSON report"
  fi

  previous_tool="$(jq -r '.tool // empty' "$COMPARE_FILE" 2>/dev/null)" ||
    die "--compare expects a valid codex-healthkit JSON report"

  if [ "$previous_tool" != "codex-healthkit" ]; then
    die "--compare expects output from codex-healthkit check --json"
  fi

  PREVIOUS_GENERATED_AT="$(previous_string '.generated_at')"
  if [ -z "$PREVIOUS_GENERATED_AT" ]; then
    PREVIOUS_GENERATED_AT="unknown"
  fi

  PREV_LOG_WAL_BYTES="$(previous_number '.state.logs_2_sqlite_wal.bytes')"
  PREV_LOG_DB_BYTES="$(previous_number '.state.logs_2_sqlite.bytes')"
  PREV_SESSIONS_BYTES="$(previous_number '.state.sessions.bytes')"
  PREV_SESSIONS_COUNT="$(previous_number '.state.sessions.jsonl_count')"
  PREV_ARCHIVED_BYTES="$(previous_number '.state.archived_sessions.bytes')"
  PREV_ARCHIVED_COUNT="$(previous_number '.state.archived_sessions.jsonl_count')"
  PREV_QUARANTINE_BYTES="$(previous_number '.state.quarantine.bytes')"

  DELTA_LOG_WAL_BYTES=$((LOG_WAL_BYTES - PREV_LOG_WAL_BYTES))
  DELTA_LOG_DB_BYTES=$((LOG_DB_BYTES - PREV_LOG_DB_BYTES))
  DELTA_SESSIONS_BYTES=$((SESSIONS_BYTES - PREV_SESSIONS_BYTES))
  DELTA_SESSIONS_COUNT=$((SESSIONS_COUNT - PREV_SESSIONS_COUNT))
  DELTA_ARCHIVED_BYTES=$((ARCHIVED_BYTES - PREV_ARCHIVED_BYTES))
  DELTA_ARCHIVED_COUNT=$((ARCHIVED_COUNT - PREV_ARCHIVED_COUNT))
  DELTA_QUARANTINE_BYTES=$((QUARANTINE_BYTES - PREV_QUARANTINE_BYTES))

  if previous_epoch="$(timestamp_epoch "$PREVIOUS_GENERATED_AT")" &&
    current_epoch="$(timestamp_epoch "$GENERATED_AT")" &&
    [ "$current_epoch" -gt "$previous_epoch" ]; then
    COMPARISON_INTERVAL_VALID=1
    COMPARISON_INTERVAL_SECONDS=$((current_epoch - previous_epoch))
    SESSIONS_GROWTH_BYTES_PER_DAY=$((DELTA_SESSIONS_BYTES * 86400 / COMPARISON_INTERVAL_SECONDS))
    COMPARISON_INTERVAL_NOTE="calculated from canonical UTC generated_at timestamps"
  else
    COMPARISON_INTERVAL_VALID=0
    COMPARISON_INTERVAL_SECONDS=0
    SESSIONS_GROWTH_BYTES_PER_DAY=0
    COMPARISON_INTERVAL_NOTE="unavailable because generated_at timestamps are invalid, equal, or not increasing"
  fi

  COMPARE_LOADED=1
  COMPARE_NOTE="explicit previous report loaded; comparison uses metadata already emitted by codex-healthkit and is informational"
}

evaluate_sessions_advisory() {
  if [ "$SESSIONS_ADVISORY_REQUESTED" -ne 1 ]; then
    return
  fi

  if [ -n "$SESSIONS_TOTAL_ADVISORY_BYTES" ] &&
    [ "$SESSIONS_BYTES" -ge "$SESSIONS_TOTAL_ADVISORY_BYTES" ]; then
    ADVISORY_LARGE_TOTAL=1
  fi

  if [ -n "$SESSIONS_DAILY_GROWTH_ADVISORY_BYTES" ] &&
    [ "$COMPARISON_INTERVAL_VALID" -eq 1 ] &&
    [ "$SESSIONS_GROWTH_BYTES_PER_DAY" -ge "$SESSIONS_DAILY_GROWTH_ADVISORY_BYTES" ]; then
    ADVISORY_RAPID_GROWTH=1
  fi

  if [ "$ADVISORY_LARGE_TOTAL" -eq 1 ] || [ "$ADVISORY_RAPID_GROWTH" -eq 1 ]; then
    SESSIONS_ADVISORY_TRIGGERED=1
    SESSIONS_ADVISORY_NOTE="one or more explicit metadata thresholds were met; review only, no cleanup performed"
  elif [ -n "$SESSIONS_DAILY_GROWTH_ADVISORY_BYTES" ] && [ "$COMPARISON_INTERVAL_VALID" -ne 1 ]; then
    SESSIONS_ADVISORY_NOTE="daily growth was not evaluated because the comparison interval is unavailable; no cleanup performed"
  else
    SESSIONS_ADVISORY_NOTE="explicit metadata thresholds were not met; no cleanup performed"
  fi
}

run_codex_doctor() {
  local doctor_json doctor_exit doctor_summary
  doctor_exit=0

  if [ "$WITH_CODEX_DOCTOR" -ne 1 ]; then
    DOCTOR_REQUESTED=0
    DOCTOR_RAN=0
    DOCTOR_STATUS="skipped"
    DOCTOR_NOTE="not requested; pass --with-codex-doctor to run official Codex doctor"
    DOCTOR_OK=0
    DOCTOR_WARN=0
    DOCTOR_FAIL=0
    return
  fi

  DOCTOR_REQUESTED=1

  if ! command -v codex >/dev/null 2>&1; then
    DOCTOR_RAN=0
    DOCTOR_STATUS="unavailable"
    DOCTOR_NOTE="codex command not found"
    DOCTOR_OK=0
    DOCTOR_WARN=0
    DOCTOR_FAIL=0
    return
  fi

  if ! command -v jq >/dev/null 2>&1; then
    DOCTOR_RAN=0
    DOCTOR_STATUS="skipped"
    DOCTOR_NOTE="jq is required to extract redacted codex doctor JSON safely"
    DOCTOR_OK=0
    DOCTOR_WARN=0
    DOCTOR_FAIL=0
    return
  fi

  doctor_json="$(codex doctor --json 2>/dev/null)" || doctor_exit=$?
  if [ "$doctor_exit" -ne 0 ] && [ -z "$doctor_json" ]; then
    DOCTOR_RAN=0
    DOCTOR_STATUS="error"
    DOCTOR_NOTE="codex doctor --json exited with code $doctor_exit"
    DOCTOR_OK=0
    DOCTOR_WARN=0
    DOCTOR_FAIL=0
    return
  fi

  doctor_summary="$(
    printf '%s' "$doctor_json" |
      jq -r '[
        (.overallStatus // "unknown"),
        ([.checks[]? | select(.status == "ok")] | length),
        ([.checks[]? | select(.status == "warn" or .status == "warning" or .status == "degraded")] | length),
        ([.checks[]? | select(.status == "fail" or .status == "error")] | length)
      ] | @tsv' 2>/dev/null
  )" || {
    DOCTOR_RAN=0
    DOCTOR_STATUS="error"
    DOCTOR_NOTE="codex doctor --json did not return parseable JSON"
    DOCTOR_OK=0
    DOCTOR_WARN=0
    DOCTOR_FAIL=0
    return
  }

  DOCTOR_RAN=1
  IFS="$(printf '\t')" read -r DOCTOR_STATUS DOCTOR_OK DOCTOR_WARN DOCTOR_FAIL <<EOF
$doctor_summary
EOF
  DOCTOR_NOTE="redacted official Codex doctor JSON summarized; raw output not included"
}

while [ "$#" -gt 0 ]; do
  case "$1" in
    check)
      COMMAND="check"
      ;;
    --markdown)
      FORMAT="markdown"
      ;;
    --json)
      FORMAT="json"
      ;;
    --with-codex-version)
      WITH_CODEX_VERSION=1
      ;;
    --check-latest-codex)
      CHECK_LATEST_CODEX=1
      WITH_CODEX_VERSION=1
      ;;
    --with-codex-doctor)
      WITH_CODEX_DOCTOR=1
      ;;
    --compare)
      shift
      [ "$#" -gt 0 ] || die "--compare requires a previous report path"
      COMPARE_FILE="$1"
      COMPARE_REQUESTED=1
      ;;
    --compare=*)
      COMPARE_FILE="${1#--compare=}"
      [ -n "$COMPARE_FILE" ] || die "--compare requires a previous report path"
      COMPARE_REQUESTED=1
      ;;
    --sessions-total-advisory-bytes)
      shift
      [ "$#" -gt 0 ] || die "--sessions-total-advisory-bytes requires a positive integer"
      positive_integer "$1" || die "--sessions-total-advisory-bytes requires a positive integer"
      SESSIONS_TOTAL_ADVISORY_BYTES="$1"
      SESSIONS_ADVISORY_REQUESTED=1
      ;;
    --sessions-total-advisory-bytes=*)
      SESSIONS_TOTAL_ADVISORY_BYTES="${1#--sessions-total-advisory-bytes=}"
      positive_integer "$SESSIONS_TOTAL_ADVISORY_BYTES" || die "--sessions-total-advisory-bytes requires a positive integer"
      SESSIONS_ADVISORY_REQUESTED=1
      ;;
    --sessions-daily-growth-advisory-bytes)
      shift
      [ "$#" -gt 0 ] || die "--sessions-daily-growth-advisory-bytes requires a positive integer"
      positive_integer "$1" || die "--sessions-daily-growth-advisory-bytes requires a positive integer"
      SESSIONS_DAILY_GROWTH_ADVISORY_BYTES="$1"
      SESSIONS_ADVISORY_REQUESTED=1
      ;;
    --sessions-daily-growth-advisory-bytes=*)
      SESSIONS_DAILY_GROWTH_ADVISORY_BYTES="${1#--sessions-daily-growth-advisory-bytes=}"
      positive_integer "$SESSIONS_DAILY_GROWTH_ADVISORY_BYTES" || die "--sessions-daily-growth-advisory-bytes requires a positive integer"
      SESSIONS_ADVISORY_REQUESTED=1
      ;;
    --version)
      printf 'codex-healthkit %s\n' "$VERSION"
      exit 0
      ;;
    --help|-h)
      usage
      exit 0
      ;;
    *)
      die "unknown argument: $1"
      ;;
  esac
  shift
done

[ "$COMMAND" = "check" ] || die "unsupported command: $COMMAND"
[ "$SESSIONS_ADVISORY_REQUESTED" -ne 1 ] || [ "$COMPARE_REQUESTED" -eq 1 ] ||
  die "sessions advisory thresholds require --compare"

GENERATED_AT="$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
CODEX_HOME_DIR="${CODEX_HOME:-$HOME/.codex}"
SQLITE_HOME_DIR="$(resolve_sqlite_home)"

SESSIONS_DIR="$CODEX_HOME_DIR/sessions"
ARCHIVED_DIR="$CODEX_HOME_DIR/archived_sessions"
QUARANTINE_DIR="$CODEX_HOME_DIR/quarantine"
LOG_DB="$SQLITE_HOME_DIR/logs_2.sqlite"
LOG_SHM="$SQLITE_HOME_DIR/logs_2.sqlite-shm"
LOG_WAL="$SQLITE_HOME_DIR/logs_2.sqlite-wal"

CODEX_FOUND=0
CODEX_VERSION="not requested"
CODEX_EXECUTABLE=""
if command -v codex >/dev/null 2>&1; then
  CODEX_FOUND=1
  CODEX_EXECUTABLE="$(command -v codex)"
  if [ "$WITH_CODEX_VERSION" -eq 1 ]; then
    CODEX_VERSION="$(codex --version 2>/dev/null || printf 'unknown')"
  fi
fi

LATEST_CODEX_REQUESTED=0
LATEST_CODEX_CHECKED=0
CURRENT_CODEX_SEMVER=""
LATEST_CODEX_VERSION=""
CODEX_UPDATE_AVAILABLE=""
LATEST_CODEX_NOTE=""
run_codex_update_check

SESSIONS_EXISTS="$(path_exists_bool "$SESSIONS_DIR")"
ARCHIVED_EXISTS="$(path_exists_bool "$ARCHIVED_DIR")"
QUARANTINE_EXISTS="$(path_exists_bool "$QUARANTINE_DIR")"
LOG_DB_EXISTS="$(path_exists_bool "$LOG_DB")"
LOG_SHM_EXISTS="$(path_exists_bool "$LOG_SHM")"
LOG_WAL_EXISTS="$(path_exists_bool "$LOG_WAL")"

SESSIONS_SIZE="$(human_size_for "$SESSIONS_DIR")"
ARCHIVED_SIZE="$(human_size_for "$ARCHIVED_DIR")"
QUARANTINE_SIZE="$(human_size_for "$QUARANTINE_DIR")"
LOG_DB_SIZE="$(human_size_for "$LOG_DB")"
LOG_SHM_SIZE="$(human_size_for "$LOG_SHM")"
LOG_WAL_SIZE="$(human_size_for "$LOG_WAL")"

SESSIONS_BYTES="$(tree_bytes_for "$SESSIONS_DIR")"
ARCHIVED_BYTES="$(tree_bytes_for "$ARCHIVED_DIR")"
QUARANTINE_BYTES="$(tree_bytes_for "$QUARANTINE_DIR")"
LOG_DB_BYTES="$(bytes_for "$LOG_DB")"
LOG_SHM_BYTES="$(bytes_for "$LOG_SHM")"
LOG_WAL_BYTES="$(bytes_for "$LOG_WAL")"

SESSIONS_COUNT="$(count_jsonl_files "$SESSIONS_DIR")"
ARCHIVED_COUNT="$(count_jsonl_files "$ARCHIVED_DIR")"
SESSIONS_FILE_COUNT="$(count_session_files "$SESSIONS_DIR")"
ARCHIVED_FILE_COUNT="$(count_session_files "$ARCHIVED_DIR")"

OVERALL_STATUS="$(overall_status_for "$LOG_DB_BYTES" "$LOG_WAL_BYTES")"
SQLITE_NOTE="$(health_note "$LOG_DB_BYTES" "$LOG_WAL_BYTES")"

DOCTOR_REQUESTED=0
DOCTOR_RAN=0
DOCTOR_STATUS="skipped"
DOCTOR_NOTE=""
DOCTOR_OK=0
DOCTOR_WARN=0
DOCTOR_FAIL=0
run_codex_doctor

if [ "$DOCTOR_RAN" = "1" ]; then
  if [ "$DOCTOR_FAIL" -gt 0 ]; then
    OVERALL_STATUS="fail"
  elif [ "$DOCTOR_WARN" -gt 0 ] && [ "$OVERALL_STATUS" = "ok" ]; then
    OVERALL_STATUS="watch"
  fi
fi

PREVIOUS_GENERATED_AT=""
PREV_LOG_WAL_BYTES=0
PREV_LOG_DB_BYTES=0
PREV_SESSIONS_BYTES=0
PREV_SESSIONS_COUNT=0
PREV_ARCHIVED_BYTES=0
PREV_ARCHIVED_COUNT=0
PREV_QUARANTINE_BYTES=0
DELTA_LOG_WAL_BYTES=0
DELTA_LOG_DB_BYTES=0
DELTA_SESSIONS_BYTES=0
DELTA_SESSIONS_COUNT=0
DELTA_ARCHIVED_BYTES=0
DELTA_ARCHIVED_COUNT=0
DELTA_QUARANTINE_BYTES=0
COMPARISON_INTERVAL_VALID=0
COMPARISON_INTERVAL_SECONDS=0
COMPARISON_INTERVAL_NOTE="not requested"
SESSIONS_GROWTH_BYTES_PER_DAY=0
ADVISORY_LARGE_TOTAL=0
ADVISORY_RAPID_GROWTH=0
SESSIONS_ADVISORY_TRIGGERED=0
SESSIONS_ADVISORY_NOTE="not requested"
load_previous_report
evaluate_sessions_advisory

if [ "$FORMAT" = "json" ]; then
  cat <<JSON
{
  "tool": "codex-healthkit",
  "version": $(json_string "$VERSION"),
  "generated_at": $(json_string "$GENERATED_AT"),
  "summary": {
    "status": $(json_string "$OVERALL_STATUS"),
    "sqlite_note": $(json_string "$SQLITE_NOTE")
  },
  "codex_cli": {
    "found": $(bool_json "$CODEX_FOUND"),
    "version": $(json_string "$CODEX_VERSION")
  }$(codex_update_json_fragment),
  "state": {
    "sessions": {
      "exists": $(bool_json "$SESSIONS_EXISTS"),
      "bytes": $SESSIONS_BYTES,
      "size": $(json_string "$SESSIONS_SIZE"),
      "jsonl_count": $SESSIONS_COUNT,
      "session_file_count": $SESSIONS_FILE_COUNT
    },
    "archived_sessions": {
      "exists": $(bool_json "$ARCHIVED_EXISTS"),
      "bytes": $ARCHIVED_BYTES,
      "size": $(json_string "$ARCHIVED_SIZE"),
      "jsonl_count": $ARCHIVED_COUNT,
      "session_file_count": $ARCHIVED_FILE_COUNT
    },
    "quarantine": {
      "exists": $(bool_json "$QUARANTINE_EXISTS"),
      "bytes": $QUARANTINE_BYTES,
      "size": $(json_string "$QUARANTINE_SIZE")
    },
    "logs_2_sqlite": {
      "exists": $(bool_json "$LOG_DB_EXISTS"),
      "bytes": $LOG_DB_BYTES,
      "size": $(json_string "$LOG_DB_SIZE")
    },
    "logs_2_sqlite_shm": {
      "exists": $(bool_json "$LOG_SHM_EXISTS"),
      "bytes": $LOG_SHM_BYTES,
      "size": $(json_string "$LOG_SHM_SIZE")
    },
    "logs_2_sqlite_wal": {
      "exists": $(bool_json "$LOG_WAL_EXISTS"),
      "bytes": $LOG_WAL_BYTES,
      "size": $(json_string "$LOG_WAL_SIZE")
    }
  },
  "comparison": $(comparison_json),
  "official_codex_doctor": {
    "requested": $(bool_json "$DOCTOR_REQUESTED"),
    "ran": $(bool_json "$DOCTOR_RAN"),
    "status": $(json_string "$DOCTOR_STATUS"),
    "ok": $DOCTOR_OK,
    "warn": $DOCTOR_WARN,
    "fail": $DOCTOR_FAIL,
    "note": $(json_string "$DOCTOR_NOTE")
  },
  "safety": {
    "auth_files_read": false,
    "token_files_read": false,
    "cookies_read": false,
    "sqlite_contents_read": false,
    "session_transcript_contents_read": false,
    "healthkit_network_telemetry": false
  }
}
JSON
  exit 0
fi

cat <<MARKDOWN
# codex-healthkit report

Generated: $GENERATED_AT

## Summary

- status: \`$OVERALL_STATUS\`
- sqlite_note: $SQLITE_NOTE
- default_mode: local file metadata only

## Codex CLI

- found: \`$(if [ "$CODEX_FOUND" = "1" ]; then printf 'yes'; else printf 'no'; fi)\`
- version: \`$(markdown_inline "$CODEX_VERSION")\`
- version_requested: \`$(if [ "$WITH_CODEX_VERSION" = "1" ]; then printf 'yes'; else printf 'no'; fi)\`
MARKDOWN

if [ "$LATEST_CODEX_REQUESTED" -eq 1 ]; then
  cat <<MARKDOWN

## Codex Stable Version Check

- requested: \`yes\`
- checked: \`$(if [ "$LATEST_CODEX_CHECKED" = "1" ]; then printf 'yes'; else printf 'no'; fi)\`
- executable_path: \`$(if [ -n "$CODEX_EXECUTABLE" ]; then markdown_inline "$CODEX_EXECUTABLE"; else printf 'unavailable'; fi)\`
- current_version: \`$(if [ -n "$CURRENT_CODEX_SEMVER" ]; then markdown_inline "$CURRENT_CODEX_SEMVER"; else printf 'unavailable'; fi)\`
- latest_version: \`$(if [ -n "$LATEST_CODEX_VERSION" ]; then markdown_inline "$LATEST_CODEX_VERSION"; else printf 'unavailable'; fi)\`
- update_available: \`$(update_available_markdown "$CODEX_UPDATE_AVAILABLE")\`
- source: \`npm:@openai/codex dist-tag latest\`
- note: $(markdown_inline "$LATEST_CODEX_NOTE")
MARKDOWN
fi

cat <<MARKDOWN

## Local State Metadata

| item | exists | bytes | size | count | note |
|---|---:|---:|---:|---:|---|
| active sessions | $(if [ "$SESSIONS_EXISTS" = "1" ]; then printf 'yes'; else printf 'no'; fi) | $SESSIONS_BYTES | $SESSIONS_SIZE | $SESSIONS_COUNT JSONL / $SESSIONS_FILE_COUNT session files | suffix count only; transcript contents not read |
| archived sessions | $(if [ "$ARCHIVED_EXISTS" = "1" ]; then printf 'yes'; else printf 'no'; fi) | $ARCHIVED_BYTES | $ARCHIVED_SIZE | $ARCHIVED_COUNT JSONL / $ARCHIVED_FILE_COUNT session files | includes recognized compressed session files; review before deleting |
| quarantine | $(if [ "$QUARANTINE_EXISTS" = "1" ]; then printf 'yes'; else printf 'no'; fi) | $QUARANTINE_BYTES | $QUARANTINE_SIZE | - | metadata only |
| logs_2.sqlite | $(if [ "$LOG_DB_EXISTS" = "1" ]; then printf 'yes'; else printf 'no'; fi) | $LOG_DB_BYTES | $LOG_DB_SIZE | - | size only; SQLite contents not read |
| logs_2.sqlite-shm | $(if [ "$LOG_SHM_EXISTS" = "1" ]; then printf 'yes'; else printf 'no'; fi) | $LOG_SHM_BYTES | $LOG_SHM_SIZE | - | size only |
| logs_2.sqlite-wal | $(if [ "$LOG_WAL_EXISTS" = "1" ]; then printf 'yes'; else printf 'no'; fi) | $LOG_WAL_BYTES | $LOG_WAL_SIZE | - | size only |
MARKDOWN

comparison_markdown

cat <<MARKDOWN

## Official Codex Doctor

- requested: \`$(if [ "$DOCTOR_REQUESTED" = "1" ]; then printf 'yes'; else printf 'no'; fi)\`
- ran: \`$(if [ "$DOCTOR_RAN" = "1" ]; then printf 'yes'; else printf 'no'; fi)\`
- status: \`$DOCTOR_STATUS\`
- checks: \`ok=$DOCTOR_OK warn=$DOCTOR_WARN fail=$DOCTOR_FAIL\`
- note: $(markdown_inline "$DOCTOR_NOTE")

When \`--with-codex-doctor\` is enabled, Codex CLI may perform provider reachability checks using your existing Codex configuration.

## Safety

- auth files read: \`no\`
- token files read: \`no\`
- cookies read: \`no\`
- SQLite contents read: \`no\`
- session transcript contents read: \`no\`
- healthkit telemetry/upload: \`no\`

Not affiliated with OpenAI.
MARKDOWN
