#!/bin/bash
# PostToolUse Hook: логирование действий + мониторинг контекста
# Объединённый скрипт — один процесс вместо двух на каждый tool call

INPUT=$(cat)
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

# ====== ACTION LOGGER ======
LOG_DIR="$HOME/.claude/logs"
LOG_FILE="$LOG_DIR/actions.log"
MAX_SIZE=5242880  # 5MB — ротация при превышении

mkdir -p "$LOG_DIR"

if [ -f "$LOG_FILE" ] && [ "$(stat -c%s "$LOG_FILE" 2>/dev/null || echo 0)" -gt "$MAX_SIZE" ] 2>/dev/null; then
    mv "$LOG_FILE" "$LOG_FILE.old"
fi

TOOL=$(echo "$INPUT" | jq -r '.tool_name // "unknown"')
SESSION=$(echo "$INPUT" | jq -r '.session_id // "unknown"' | head -c 8)

case "$TOOL" in
    Bash)
        DETAIL=$(echo "$INPUT" | jq -r '.tool_input.command // ""' | head -c 120)
        ;;
    Read|Write|Edit)
        DETAIL=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
        ;;
    Glob|Grep)
        DETAIL=$(echo "$INPUT" | jq -r '.tool_input.pattern // ""')
        ;;
    *)
        DETAIL=$(echo "$INPUT" | jq -r '.tool_input | keys[:2] | join(", ")' 2>/dev/null || echo "")
        ;;
esac

echo "[$TIMESTAMP] [$SESSION] $TOOL: $DETAIL" >> "$LOG_FILE"

# ====== CONTEXT MONITOR ======
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"' | head -c 16)
STATE_FILE="/tmp/claude-ctx-${SESSION_ID}.json"

TOOL_INPUT_SIZE=$(echo "$INPUT" | jq -r '.tool_input // {} | tostring' | wc -c)
TOOL_OUTPUT_SIZE=$(echo "$INPUT" | jq -r '.tool_output // "" | tostring' | wc -c)
CALL_SIZE=$((TOOL_INPUT_SIZE + TOOL_OUTPUT_SIZE))

if [ -f "$STATE_FILE" ]; then
    CUMULATIVE=$(jq -r '.cumulative_bytes // 0' "$STATE_FILE")
    TOOL_CALLS=$(jq -r '.tool_calls // 0' "$STATE_FILE")
    LAST_WARNING=$(jq -r '.last_warning // "none"' "$STATE_FILE")
    CALLS_SINCE_WARN=$(jq -r '.calls_since_warning // 0' "$STATE_FILE")
else
    CUMULATIVE=0
    TOOL_CALLS=0
    LAST_WARNING="none"
    CALLS_SINCE_WARN=0
fi

CUMULATIVE=$((CUMULATIVE + CALL_SIZE))
TOOL_CALLS=$((TOOL_CALLS + 1))
CALLS_SINCE_WARN=$((CALLS_SINCE_WARN + 1))

EST_TOKENS=$(( (CUMULATIVE * 18) / (4 * 10) ))
MAX_TOKENS=${CLAUDE_CONTEXT_TOKENS:-1000000}

if [ "$MAX_TOKENS" -gt 0 ]; then
    PERCENT=$(( (EST_TOKENS * 100) / MAX_TOKENS ))
else
    PERCENT=0
fi

CURRENT_LEVEL="ok"
if [ "$PERCENT" -ge 80 ]; then
    CURRENT_LEVEL="critical"
elif [ "$PERCENT" -ge 65 ]; then
    CURRENT_LEVEL="warning"
elif [ "$PERCENT" -ge 50 ]; then
    CURRENT_LEVEL="notice"
fi

SHOULD_WARN=false
if [ "$CURRENT_LEVEL" = "critical" ] && [ "$LAST_WARNING" != "critical" ]; then
    SHOULD_WARN=true
elif [ "$CURRENT_LEVEL" = "critical" ] && [ "$CALLS_SINCE_WARN" -ge 8 ]; then
    SHOULD_WARN=true
elif [ "$CURRENT_LEVEL" = "warning" ] && [[ "$LAST_WARNING" = "none" || "$LAST_WARNING" = "ok" || "$LAST_WARNING" = "notice" ]]; then
    SHOULD_WARN=true
elif [ "$CURRENT_LEVEL" = "warning" ] && [ "$CALLS_SINCE_WARN" -ge 8 ]; then
    SHOULD_WARN=true
elif [ "$CURRENT_LEVEL" = "notice" ] && [[ "$LAST_WARNING" = "none" || "$LAST_WARNING" = "ok" ]]; then
    SHOULD_WARN=true
fi

if [ "$SHOULD_WARN" = true ]; then
    SAVE_LAST="$CURRENT_LEVEL"
    SAVE_CALLS=0
else
    SAVE_LAST="$LAST_WARNING"
    SAVE_CALLS="$CALLS_SINCE_WARN"
fi

cat > "$STATE_FILE" << STATEJSON
{
  "cumulative_bytes": $CUMULATIVE,
  "tool_calls": $TOOL_CALLS,
  "estimated_tokens": $EST_TOKENS,
  "percent_used": $PERCENT,
  "max_tokens": $MAX_TOKENS,
  "last_warning": "$SAVE_LAST",
  "calls_since_warning": $SAVE_CALLS,
  "updated": "$(date -Iseconds)"
}
STATEJSON

if [ "$SHOULD_WARN" = true ]; then
    case "$CURRENT_LEVEL" in
        notice)
            echo "[context-monitor] Контекст ~${PERCENT}% заполнен (~${EST_TOKENS} токенов из ${MAX_TOKENS}). Пока всё нормально, но имей в виду."
            ;;
        warning)
            echo "[context-monitor] Контекст ~${PERCENT}% заполнен. Рекомендуется: делегировать тяжёлые задачи субагентам, избегать чтения больших файлов целиком, завершить текущую работу в ближайшее время."
            ;;
        critical)
            echo "[context-monitor] КРИТИЧНО: контекст ~${PERCENT}% заполнен! Завершай текущую задачу. Не начинай новых. При необходимости — предложи Дане сохранить сессию и начать новую."
            ;;
    esac
fi

exit 0
