#!/usr/bin/env bash
# OgenticAI Software Factory — pre-commit hook
# Blocks commits that smell like secrets. Five minutes to install. Prevents disasters.
#
# Install: cp .claude/hooks/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit
# Or with husky: copy this content into .husky/pre-commit

set -euo pipefail

# Paths that LOOK like secrets but are canonical templates and must be allowed
# through. Checked BEFORE FORBIDDEN_PATHS so `.env.example` etc. aren't blocked
# by the broader `\.env\.` rule.
ALLOWED_PATHS=(
  '(^|/)\.env(\.[^/]+)*\.(example|sample|template)$'
)

# Files we never want committed, period.
FORBIDDEN_PATHS=(
  '\.env$'
  '\.env\.'
  '\.env_'
  '\.key$'
  '\.pem$'
  '\.p12$'
  '\.pfx$'
  '\.jks$'
  'secrets\.json$'
  'credentials\.json$'
  'service-account.*\.json$'
  'id_rsa$'
  'id_ed25519$'
)

# Strings that look like secrets even inside otherwise-fine files.
FORBIDDEN_CONTENT=(
  'AKIA[0-9A-Z]{16}'                         # AWS access key
  'aws_secret_access_key\s*=\s*["'\''][^"'\'' ]+["'\'' ]'
  'sk-[A-Za-z0-9]{20,}'                      # OpenAI-style
  'sk-ant-[A-Za-z0-9_-]{20,}'                # Anthropic
  'AIza[0-9A-Za-z_-]{35}'                    # Google API key
  'ghp_[A-Za-z0-9]{36}'                      # GitHub PAT classic
  'github_pat_[A-Za-z0-9_]{50,}'             # GitHub PAT fine-grained
  'xox[baprs]-[A-Za-z0-9-]{10,}'             # Slack token
  '-----BEGIN (RSA |EC |DSA |OPENSSH |PRIVATE) ?KEY-----'
)

errors=0

# 1) Check staged file paths
staged_paths="$(git diff --cached --name-only --diff-filter=ACM || true)"
if [[ -n "$staged_paths" ]]; then
  while IFS= read -r path; do
    # Allowlist: canonical templates (.env.example, .env.local.example, etc.)
    # short-circuit before forbidden-path checks. Use `--` so patterns that
    # start with a dash don't get parsed as flags by BSD grep on macOS.
    allowed=0
    for pat in "${ALLOWED_PATHS[@]}"; do
      if echo "$path" | grep -E -q -- "$pat"; then
        allowed=1
        break
      fi
    done
    [[ $allowed -eq 1 ]] && continue

    for pat in "${FORBIDDEN_PATHS[@]}"; do
      if echo "$path" | grep -E -q -- "$pat"; then
        echo "🚫 BLOCKED: $path matches forbidden path pattern /$pat/"
        errors=$((errors+1))
      fi
    done
  done <<< "$staged_paths"
fi

# 2) Check staged content for secret-shaped strings
if [[ -n "$staged_paths" ]]; then
  while IFS= read -r path; do
    [[ -f "$path" ]] || continue
    # Skip binaries
    if file --mime "$path" | grep -q 'charset=binary'; then
      continue
    fi
    for pat in "${FORBIDDEN_CONTENT[@]}"; do
      # `--` terminates option parsing so patterns that start with a dash
      # (e.g. the PEM `-----BEGIN ... KEY-----` regex) aren't mistaken for
      # flags by BSD grep on macOS.
      if git diff --cached "$path" | grep -E -q -- "$pat"; then
        echo "🚫 BLOCKED: $path contains content matching /$pat/"
        errors=$((errors+1))
      fi
    done
  done <<< "$staged_paths"
fi

if (( errors > 0 )); then
  echo ""
  echo "Pre-commit blocked your commit because it looks like it contains secrets."
  echo "If this is a false positive (e.g. a fixture or doc), either:"
  echo "  - move it to .gitleaks-allowlist and explain why in the PR description"
  echo "  - or override with: SKIP_SECRETS_CHECK=1 git commit ..."
  echo "    (you will own the consequences)"
  if [[ "${SKIP_SECRETS_CHECK:-0}" == "1" ]]; then
    echo "SKIP_SECRETS_CHECK=1 set — allowing commit despite findings."
    exit 0
  fi
  exit 1
fi

exit 0
