#!/bin/sh

# Smart pre-commit hook: only runs checks relevant to staged files
# Use CLAUDELINT_PRECOMMIT_ALL=1 to force all checks

STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR 2>/dev/null)

if [ -z "$STAGED_FILES" ]; then
  echo "No staged files found, skipping pre-commit checks."
  exit 0
fi

# Detect file categories in staged files
HAS_TS=$(echo "$STAGED_FILES" | grep -c '\.ts$' || true)
HAS_MD=$(echo "$STAGED_FILES" | grep -c '\.md$' || true)
HAS_RULES=$(echo "$STAGED_FILES" | grep -c '^src/rules/' || true)
HAS_RULE_TESTS=$(echo "$STAGED_FILES" | grep -c '^tests/rules/' || true)
HAS_CLI=$(echo "$STAGED_FILES" | grep -c '^src/cli/' || true)
HAS_SCRIPTS=$(echo "$STAGED_FILES" | grep -c '^scripts/' || true)
HAS_JS=$(echo "$STAGED_FILES" | grep -c '\.js$' || true)
HAS_CI=$(echo "$STAGED_FILES" | grep -c '^\.github/' || true)
HAS_SCHEMAS=$(echo "$STAGED_FILES" | grep -c -E '(^schemas/|^src/schemas/)' || true)
HAS_VALIDATORS=$(echo "$STAGED_FILES" | grep -c -E '(^src/validators/|^tests/validators/)' || true)
HAS_RULE_DOCS=$(echo "$STAGED_FILES" | grep -c -E '(^website/rules/|^src/rules/)' || true)
HAS_SCHEMA_DOCS=$(echo "$STAGED_FILES" | grep -c '^website/api/schemas/' || true)
FORCE_ALL="${CLAUDELINT_PRECOMMIT_ALL:-0}"

# Track which checks to run
RUN_LINT_STAGED=1       # Always
RUN_EMOJIS=0
RUN_LOGGER_SPACING=0
RUN_LOGGER_USAGE=0
RUN_RULE_IMPLS=0
RUN_RULE_COVERAGE=0
RUN_SCHEMA_SYNC=0
RUN_MILESTONE_REFS=0
RUN_BUILD=1             # Always
RUN_VALIDATOR_TESTS=0
RUN_MARKDOWNLINT=0
RUN_HARDCODED_COUNTS=0
RUN_MSG_LENGTH=0
RUN_MSG_CONTENT=0
RUN_ORPHANED_DOCS=0
RUN_SCHEMA_DOCS=0

if [ "$FORCE_ALL" = "1" ]; then
  RUN_EMOJIS=1
  RUN_LOGGER_SPACING=1
  RUN_LOGGER_USAGE=1
  RUN_RULE_IMPLS=1
  RUN_RULE_COVERAGE=1
  RUN_MILESTONE_REFS=1
  RUN_SCHEMA_SYNC=1
  RUN_VALIDATOR_TESTS=1
  RUN_MARKDOWNLINT=1
  RUN_HARDCODED_COUNTS=1
  RUN_MSG_LENGTH=1
  RUN_MSG_CONTENT=1
  RUN_ORPHANED_DOCS=1
  RUN_SCHEMA_DOCS=1
else
  [ "$HAS_TS" -gt 0 ] || [ "$HAS_MD" -gt 0 ] && RUN_EMOJIS=1
  [ "$HAS_CLI" -gt 0 ] && RUN_LOGGER_SPACING=1
  [ "$HAS_SCRIPTS" -gt 0 ] && RUN_LOGGER_USAGE=1
  [ "$HAS_RULES" -gt 0 ] && RUN_RULE_IMPLS=1
  [ "$HAS_RULES" -gt 0 ] || [ "$HAS_RULE_TESTS" -gt 0 ] && RUN_RULE_COVERAGE=1
  [ "$HAS_TS" -gt 0 ] || [ "$HAS_JS" -gt 0 ] || [ "$HAS_CI" -gt 0 ] && RUN_MILESTONE_REFS=1
  [ "$HAS_SCHEMAS" -gt 0 ] && RUN_SCHEMA_SYNC=1
  [ "$HAS_VALIDATORS" -gt 0 ] && RUN_VALIDATOR_TESTS=1
  [ "$HAS_MD" -gt 0 ] && RUN_MARKDOWNLINT=1
  [ "$HAS_MD" -gt 0 ] && RUN_HARDCODED_COUNTS=1
  [ "$HAS_RULES" -gt 0 ] && RUN_MSG_LENGTH=1
  [ "$HAS_RULES" -gt 0 ] && RUN_MSG_CONTENT=1
  [ "$HAS_RULE_DOCS" -gt 0 ] && RUN_ORPHANED_DOCS=1
  [ "$HAS_SCHEMA_DOCS" -gt 0 ] && RUN_SCHEMA_DOCS=1
fi

# Count enabled checks for progress display
TOTAL=0
[ "$RUN_LINT_STAGED" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_EMOJIS" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_LOGGER_SPACING" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_LOGGER_USAGE" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_RULE_IMPLS" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_RULE_COVERAGE" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_MILESTONE_REFS" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_SCHEMA_SYNC" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_BUILD" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_BUILD" = "1" ] && TOTAL=$((TOTAL + 1))  # dogfood step
[ "$RUN_VALIDATOR_TESTS" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_MARKDOWNLINT" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_HARDCODED_COUNTS" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_MSG_LENGTH" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_MSG_CONTENT" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_ORPHANED_DOCS" = "1" ] && TOTAL=$((TOTAL + 1))
[ "$RUN_SCHEMA_DOCS" = "1" ] && TOTAL=$((TOTAL + 1))

STEP=0
echo "Running pre-commit checks ($TOTAL of 17 enabled)..."
if [ "$FORCE_ALL" = "1" ]; then
  echo "(CLAUDELINT_PRECOMMIT_ALL=1: running all checks)"
fi
echo ""

run_check() {
  STEP=$((STEP + 1))
  echo "$STEP/$TOTAL $1..."
}

fail_check() {
  echo "$1"
  exit 1
}

# 1. Lint-staged (always runs - already scoped to staged files)
if [ "$RUN_LINT_STAGED" = "1" ]; then
  run_check "Running lint-staged"
  npx lint-staged || fail_check "Lint-staged failed. Please fix the errors and try again."
  echo ""
fi

# 2. Emoji check
if [ "$RUN_EMOJIS" = "1" ]; then
  run_check "Checking for emojis"
  npm run check:emojis || fail_check "Emojis found in code. Please remove them before committing."
  echo ""
fi

# 3. Logger spacing
if [ "$RUN_LOGGER_SPACING" = "1" ]; then
  run_check "Checking logger spacing"
  npm run check:logger-spacing || fail_check "Logger spacing violations found. Please fix them."
  echo ""
fi

# 4. Logger usage
if [ "$RUN_LOGGER_USAGE" = "1" ]; then
  run_check "Checking logger usage in scripts"
  npm run check:logger-usage || fail_check "Logger usage violations found. Please fix them."
  echo ""
fi

# 5. Rule implementations
if [ "$RUN_RULE_IMPLS" = "1" ]; then
  run_check "Verifying rule implementations"
  npm run check:rule-implementations || fail_check "Rule implementation check failed."
  echo ""
fi

# 6. Message length
if [ "$RUN_MSG_LENGTH" = "1" ]; then
  run_check "Checking message lengths"
  npm run check:message-length || fail_check "Message length violations found. Shorten messages and move details to fix/docs fields."
  echo ""
fi

# 7. Message content
if [ "$RUN_MSG_CONTENT" = "1" ]; then
  run_check "Checking message content"
  npm run check:message-content || fail_check "Message content anti-patterns found. Move fix instructions to fix field."
  echo ""
fi

# 8. Rule coverage
if [ "$RUN_RULE_COVERAGE" = "1" ]; then
  run_check "Checking rule coverage"
  npm run check:rule-coverage || fail_check "Rule coverage check failed."
  echo ""
fi

# 9. Milestone references
if [ "$RUN_MILESTONE_REFS" = "1" ]; then
  run_check "Checking for stale milestone references"
  npm run check:milestone-refs || fail_check "Stale milestone references found. Use descriptive labels instead."
  echo ""
fi

# 10. Schema sync
if [ "$RUN_SCHEMA_SYNC" = "1" ]; then
  run_check "Checking schema sync"
  npm run check:schema-sync || fail_check "Schema sync check failed."
  echo ""
fi

# 11. Build (always runs - TypeScript must compile)
if [ "$RUN_BUILD" = "1" ]; then
  run_check "Building project"
  npm run build || fail_check "Build failed. Please fix TypeScript errors before committing."
  # Auto-stage rule files if they were regenerated during build
  git add src/rules/index.ts src/rules/rule-ids.ts website/data/rule-stats.json 2>/dev/null || true
  echo ""
fi

# 11b. Dogfood claudelint on itself (fast mode, changed files only)
if [ "$RUN_BUILD" = "1" ]; then
  run_check "Running claudelint on itself (dogfooding)"
  node bin/claudelint check-all --fast --changed --quiet || fail_check "claudelint dogfooding failed. Please fix validation errors."
  echo ""
fi

# 12. Validator tests
if [ "$RUN_VALIDATOR_TESTS" = "1" ]; then
  run_check "Running validator tests"
  npx jest tests/validators --passWithNoTests || fail_check "Validator tests failed."
  echo ""
fi

# 13. Markdownlint
if [ "$RUN_MARKDOWNLINT" = "1" ]; then
  run_check "Linting markdown files"
  npm run lint:md || fail_check "Markdownlint failed. Run 'npm run lint:md:fix' to auto-fix."
  echo ""
fi

# 14. Hardcoded rule counts
if [ "$RUN_HARDCODED_COUNTS" = "1" ]; then
  run_check "Checking for hardcoded rule counts"
  npm run check:hardcoded-counts || fail_check "Hardcoded rule counts found. Use <RuleCount> in website/ or generic language in docs/."
  echo ""
fi

# 15. Orphaned rule docs
if [ "$RUN_ORPHANED_DOCS" = "1" ]; then
  run_check "Checking for orphaned rule docs"
  npm run check:orphaned-rule-docs || fail_check "Orphaned rule docs found. Delete stale files or regenerate with: npm run docs:generate"
  echo ""
fi

# 16. Schema documentation consistency
if [ "$RUN_SCHEMA_DOCS" = "1" ]; then
  run_check "Checking schema documentation consistency"
  npm run check:schema-docs || fail_check "Schema docs violate standard template. Run 'npm run check:schema-docs' for details."
  echo ""
fi

echo "All pre-commit checks passed!"
exit 0
