#!/usr/bin/env bash
# aTool - hooks/git/pre-commit
# Self-contained git pre-commit quality gate for IDE-agnostic enforcement
# (GitHub Copilot and any other environment without lifecycle hooks).
# No jq / no aTool lib dependencies — safe to commit and share with the team.
#
# Checks (staged files only):
#   1. Sensitive files (.env, credentials, keys)  -> BLOCK (exit 1)
#   2. TODO/FIXME/HACK/XXX leftovers              -> warn
#   3. Files larger than 1MB                      -> warn
#   4. Source staged without any .md update       -> warn (doc-sync gate)
#   5. 10+ staged files                           -> warn (suggest splitting)
#
# Escape hatch: ATOOL_SKIP_GITHOOKS=1 git commit ...   (or git commit --no-verify)
set -euo pipefail

if [[ "${ATOOL_SKIP_GITHOOKS:-0}" == "1" ]]; then
    exit 0
fi

STAGED=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null || true)
if [[ -z "$STAGED" ]]; then
    exit 0
fi

REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)

WARNINGS=""
BLOCKED_FILES=""

SENSITIVE_PATTERNS='(\.env$|\.env\.|credentials|\.pem$|\.key$|secret|\.p12$|\.pfx$|id_rsa|id_ed25519|\.npmrc$|\.pypirc$)'
SOURCE_PATTERN='\.(ts|tsx|js|jsx|vue|svelte|html|rs|py|go|java|kt|kts|swift|dart|ets|sh|bash)$'

TODO_COUNT=0
LARGE_FILES=""
HAS_SOURCE=false
HAS_DOC=false
FILE_COUNT=0

while IFS= read -r file; do
    [[ -z "$file" ]] && continue
    FILE_COUNT=$((FILE_COUNT + 1))

    # 1. Sensitive files
    if printf '%s' "$file" | grep -qE "$SENSITIVE_PATTERNS" 2>/dev/null; then
        if [[ -z "$BLOCKED_FILES" ]]; then
            BLOCKED_FILES="$file"
        else
            BLOCKED_FILES="$BLOCKED_FILES, $file"
        fi
    fi

    # Classify for doc-sync gate
    if printf '%s' "$file" | grep -qE "$SOURCE_PATTERN" 2>/dev/null; then
        HAS_SOURCE=true
    fi
    case "$file" in
        *.md|*.markdown) HAS_DOC=true ;;
    esac

    abs_path="$REPO_ROOT/$file"
    if [[ -f "$abs_path" ]]; then
        # 2. TODO/FIXME leftovers
        file_todos=$(grep -cE '(TODO|FIXME|HACK|XXX)' "$abs_path" 2>/dev/null || true)
        file_todos="${file_todos:-0}"
        if [[ "$file_todos" -gt 0 ]]; then
            TODO_COUNT=$((TODO_COUNT + file_todos))
        fi

        # 3. Large files (> 1MB)
        file_size=$(wc -c < "$abs_path" 2>/dev/null || echo "0")
        if [[ "$file_size" -gt 1048576 ]]; then
            size_mb=$((file_size / 1048576))
            if [[ -z "$LARGE_FILES" ]]; then
                LARGE_FILES="$file (${size_mb}MB)"
            else
                LARGE_FILES="$LARGE_FILES, $file (${size_mb}MB)"
            fi
        fi
    fi
done <<< "$STAGED"

if [[ "$TODO_COUNT" -gt 0 ]]; then
    WARNINGS+="  - ${TODO_COUNT} TODO/FIXME/HACK/XXX marker(s) in staged files. Resolve or track them before commit.\n"
fi

if [[ -n "$LARGE_FILES" ]]; then
    WARNINGS+="  - Large file(s) staged: ${LARGE_FILES}. Consider .gitattributes or Git LFS.\n"
fi

if $HAS_SOURCE && ! $HAS_DOC; then
    WARNINGS+="  - Source files staged without any documentation update. If behavior/structure changed, update README.md / COMPONENT.md / docs/ (aTool Doc Sync Gate: stale docs = task NOT done).\n"
fi

if [[ "$FILE_COUNT" -ge 10 ]]; then
    WARNINGS+="  - ${FILE_COUNT} files in one commit. Consider splitting into smaller, reviewable commits.\n"
fi

if [[ -n "$WARNINGS" ]]; then
    {
        echo "[aTool pre-commit] Quality check warnings:"
        printf '%b' "$WARNINGS"
    } >&2
fi

if [[ -n "$BLOCKED_FILES" ]]; then
    {
        echo "[aTool pre-commit] BLOCKED: sensitive file(s) staged: ${BLOCKED_FILES}"
        echo "  Never commit secrets. Unstage them (git reset <file>) and add to .gitignore."
        echo "  Intentional? Bypass once with: ATOOL_SKIP_GITHOOKS=1 git commit ..."
    } >&2
    exit 1
fi

exit 0
