#!/bin/sh
set -eu
set -f

newline='
'
default_ifs=$IFS
fail=0

staged=$(git diff --cached --name-only --diff-filter=ACMR)
if [ -z "$staged" ]; then
  exit 0
fi

blocked=""
IFS=$newline
for file in $staged; do
  base=${file##*/}
  case "$base" in
    .env.example | .env.sample | .env.template) ;;
    .env | .env.* | *.env | *.pem | *.key | *.p12 | *.pfx | *.jks | *.keystore | id_rsa | id_dsa | id_ecdsa | id_ed25519)
      blocked="$blocked  $file$newline"
      ;;
  esac
done
IFS=$default_ifs

if [ -n "$blocked" ]; then
  printf 'pre-commit: these files look like secrets or private keys and were not committed:\n%s' "$blocked" >&2
  printf 'Unstage them with: git restore --staged <file>\n' >&2
  fail=1
fi

if git diff --cached --diff-filter=ACMR -U0 --no-color | grep -Eq '^\+.*-----BEGIN ([A-Z0-9]+ )*PRIVATE KEY( BLOCK)?-----'; then
  printf 'pre-commit: the staged changes contain a private key block.\n' >&2
  fail=1
fi

run_check() {
  label=$1
  files=$2
  shift 2
  if [ -z "$files" ]; then
    return 0
  fi
  IFS=$newline
  set -- "$@" $files
  IFS=$default_ifs
  if ! "$@"; then
    printf 'pre-commit: %s failed.\n' "$label" >&2
    fail=1
  fi
}

format_files=$(printf '%s\n' "$staged" | grep -E '\.(js|jsx|mjs|cjs|ts|tsx|mts|cts|json|css|scss|html|md|yml|yaml|vue|svelte)$' || true)
lint_files=$(printf '%s\n' "$staged" | grep -E '\.(js|jsx|mjs|cjs|ts|tsx|mts|cts)$' || true)
python_files=$(printf '%s\n' "$staged" | grep -E '\.py$' || true)

if [ -x node_modules/.bin/prettier ]; then
  run_check "Prettier format check" "$format_files" node_modules/.bin/prettier --check --ignore-unknown
fi

if [ -x node_modules/.bin/eslint ]; then
  run_check "ESLint" "$lint_files" node_modules/.bin/eslint --max-warnings=0 --no-warn-ignored
fi

if command -v ruff >/dev/null 2>&1; then
  run_check "Ruff format check" "$python_files" ruff format --check
  run_check "Ruff lint" "$python_files" ruff check
fi

if [ "$fail" -ne 0 ]; then
  printf 'pre-commit: commit blocked. Fix the problems above and commit again.\n' >&2
  exit 1
fi

exit 0
