#!/usr/bin/env bash
# aTool - hooks/doc-sync-reminder
# PostToolUse hook: reminds AI to update docs after source file modifications
# Only triggers on Write|Edit of source files (not .md/.json/.css/.lock etc.)

set -euo pipefail

# Escape string for JSON embedding
escape_for_json() {
    local s="$1"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//$'\n'/\\n}"
    s="${s//$'\r'/\\r}"
    s="${s//$'\t'/\\t}"
    printf '%s' "$s"
}

main() {
    # Read tool input from stdin (Claude Code provides JSON on stdin for PostToolUse)
    local INPUT=""
    if [[ ! -t 0 ]]; then
        INPUT=$(cat)
    fi

    # ── Fast filter: extract file path from tool input (< 5ms) ───────────────

    local TOOL_NAME=""
    local FILE_PATH=""
    if command -v jq &>/dev/null && [[ -n "$INPUT" ]]; then
        TOOL_NAME=$(printf '%s' "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null || echo "")
        FILE_PATH=$(printf '%s' "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null || echo "")
    elif [[ -n "$INPUT" ]]; then
        # Fallback: extract tool_name and file_path using grep/sed (jq not available)
        TOOL_NAME=$(printf '%s' "$INPUT" | grep -oE '"tool_name"[[:space:]]*:[[:space:]]*"[^"]*"' 2>/dev/null | head -1 | sed 's/.*"tool_name"[[:space:]]*:[[:space:]]*"//;s/"$//' || echo "")
        FILE_PATH=$(printf '%s' "$INPUT" | grep -oE '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' 2>/dev/null | head -1 | sed 's/.*"file_path"[[:space:]]*:[[:space:]]*"//;s/"$//' || echo "")
    fi

    # Only respond to Write/Edit/MultiEdit
    if [[ "$TOOL_NAME" != "Write" && "$TOOL_NAME" != "Edit" && "$TOOL_NAME" != "MultiEdit" ]]; then
        exit 0
    fi

    # No file path extracted — exit silently
    if [[ -z "$FILE_PATH" ]]; then
        exit 0
    fi

    # ── Source file detection: only trigger on actual source code ─────────────

    local FILE_EXT="${FILE_PATH##*.}"
    local FILE_BASE
    FILE_BASE=$(basename "$FILE_PATH")

    # Skip non-source files
    case "$FILE_EXT" in
        md|markdown|txt|rst) exit 0 ;;
        json|yaml|yml|toml|xml) exit 0 ;;
        css|scss|less|sass|styl) exit 0 ;;
        lock|map|log) exit 0 ;;
        svg|png|jpg|jpeg|gif|ico|webp|ttf|woff|woff2|eot) exit 0 ;;
        gitignore|editorconfig|prettierrc|eslintrc) exit 0 ;;
    esac

    # Skip config files and dotfiles
    case "$FILE_BASE" in
        .*|*.config.*|tsconfig.*|jsconfig.*|vite.config.*|next.config.*|tailwind.config.*|postcss.config.*|webpack.config.*) exit 0 ;;
    esac

    # Only trigger on known source extensions
    case "$FILE_EXT" in
        ts|tsx|js|jsx|vue|svelte) ;;   # Web
        html) ;;                        # HTML templates
        rs) ;;                          # Rust
        py) ;;                          # Python
        go) ;;                          # Go
        java|kt|kts) ;;                 # Java/Kotlin
        swift) ;;                       # Swift
        dart) ;;                        # Dart
        ets) ;;                         # HarmonyOS ArkTS
        sh|bash) ;;                     # Shell
        *) exit 0 ;;                     # Unknown extension, skip
    esac

    # ── Stale doc check: remind if any docs are actually stale ────────────────

    local PROJECT_DIR="${PWD:-}"

    # Source common.sh for count_stale_docs
    local _LIB_FOUND=false
    for _lib_dir in "$HOME/.claude/lib" "$HOME/.cursor/lib" "${ATOOL_ROOT:-}/lib"; do
        if [[ -f "${_lib_dir}/common.sh" ]]; then
            # shellcheck source=/dev/null
            source "${_lib_dir}/common.sh"
            _LIB_FOUND=true
            break
        fi
    done

    local STALE=false
    if $_LIB_FOUND && declare -f count_stale_docs &>/dev/null; then
        # Check against all common documentation files — any stale doc triggers reminder
        local DOC_FILES=()
        for doc in "README.md" "COMPONENT.md" "UI_STYLE.md" "DESIGN.md" "ARCHITECTURE.md" "CODE_REVIEW.md"; do
            [[ -f "$PROJECT_DIR/$doc" ]] && DOC_FILES+=("$doc")
        done
        # Also check docs/ directory markdown files (up to 20)
        if [[ -d "$PROJECT_DIR/docs" ]]; then
            while IFS= read -r doc; do
                [[ -n "$doc" ]] && DOC_FILES+=("$doc")
            done < <(find "$PROJECT_DIR/docs" -maxdepth 1 -name '*.md' -type f 2>/dev/null | head -20 | sed "s|^$PROJECT_DIR/||")
        fi

        if [[ ${#DOC_FILES[@]} -gt 0 ]]; then
            local STALE_COUNT
            STALE_COUNT=$(count_stale_docs "$PROJECT_DIR" "${DOC_FILES[@]}")
            if [[ "$STALE_COUNT" -gt 0 ]]; then
                STALE=true
            fi
        fi
    fi

    # If no stale doc detection available, exit silently (consistent with task-state-tracker fallback)
    if ! $_LIB_FOUND; then
        exit 0
    fi

    if ! $STALE; then
        exit 0  # Docs are up to date, no reminder needed
    fi

    # ── Output reminder ──────────────────────────────────────────────────────

    local _REMINDER='<ATOOL-DOC-SYNC-REMINDER>
You just modified a source file. Documentation may now be stale.

IMMEDIATE actions required (do NOT defer):
1. Update affected docs: README.md (architecture/structure), COMPONENT.md (API/usage), UI_STYLE.md (styles), DESIGN.md (design system tokens), docs/ (knowledge base).
2. Before claiming this task done, invoke /verification-before-completion to verify doc freshness.
3. For substantial doc updates, invoke /doc-coauthoring. For doc format validation, invoke /doc-standards-enforcer.

Gate rule: if any doc is stale, the task is NOT done.
</ATOOL-DOC-SYNC-REMINDER>'

    # Use structured JSON output for Claude Code PostToolUse hooks
    # Plain text stdout is only visible in verbose mode, NOT injected into conversation.
    # The correct format is: {"hookSpecificOutput":{"hookEventName":"PostToolUse","additionalContext":"..."}}
    local _ESCAPED
    _ESCAPED=$(escape_for_json "$_REMINDER")
    printf '{"hookSpecificOutput":{"hookEventName":"PostToolUse","additionalContext":"%s"}}\n' "$_ESCAPED"

    exit 0
}

main "$@"
