#!/usr/bin/env bash
# vibecrafted-husky-template :: pre-commit
#
# Stage-scoped pre-commit gate. Each step is opt-in via .husky/config.env.
# Failures on feature branches are demoted to warnings (WARN mode); the
# log is archived under .husky/warns/ and a signature trailer is appended
# to the commit message by prepare-commit-msg.
#
# Vibecrafted with AI Agents by Vetcoders (c)2024-2026 LibraxisAI

set -euo pipefail
HUSKY_HOOK_NAME="pre-commit"

HUSKY_LIB="${BASH_SOURCE[0]%/*}/lib"
# shellcheck disable=SC1090,SC1091
. "$HUSKY_LIB/core.sh"
# shellcheck disable=SC1090,SC1091
. "$HUSKY_LIB/secrets.sh"
# shellcheck disable=SC1090,SC1091
. "$HUSKY_LIB/env-files.sh"
# shellcheck disable=SC1090,SC1091
. "$HUSKY_LIB/lint-routing.sh"

husky_init
husky_warns_print_backlog "$HUSKY_HOOK_NAME"

LOG_FILE="$(mktemp -t "husky-${HUSKY_HOOK_NAME}.XXXX.log")"
# Strict steps write "1" here when they fail. Used by the tail logic to
# refuse WARN-mode override — see lib/core.sh::husky_run_strict_step.
HUSKY_STRICT_FAILED_FILE="$(mktemp -t "husky-${HUSKY_HOOK_NAME}-strict.XXXX")"
export HUSKY_STRICT_FAILED_FILE
trap 'rm -f "$LOG_FILE" "$HUSKY_STRICT_FAILED_FILE"' EXIT

set +e
(
  set -euo pipefail
  # NOTE: deliberately do not tighten IFS globally — Semgrep flags global
  # IFS mutation as ifs-tampering. Functions that need controlled splitting
  # set IFS locally on the read/loop boundary.

  husky_log "──────────────────────────────────────────────"
  husky_log "  Vibecrafted Husky :: pre-commit"
  husky_log "  branch: $(husky_current_branch)"
  if husky_warn_mode_active; then
    husky_log "  mode  : WARN  (failures → warns archive)"
  else
    husky_log "  mode  : STRICT"
  fi
  husky_log "──────────────────────────────────────────────"

  # SECURITY: secret and env-file guards run as STRICT — never demoted to
  # warning even on feature branches. A leaked credential / staged .env in
  # the commit object cannot be retroactively scrubbed without history
  # rewriting, so the gate has to actually gate.
  [ "$HUSKY_PRECOMMIT_SECRETS" = "1" ]          && husky_run_strict_step "Secret leak guard" husky_secrets_scan_staged
  [ "$HUSKY_PRECOMMIT_ENV_FILES" = "1" ]        && husky_run_strict_step "Env-file guard"    husky_env_files_scan_staged

  [ "$HUSKY_PRECOMMIT_LINT_STAGED" = "1" ]      && husky_run_step "lint-staged"              husky_lint_lint_staged
  [ "$HUSKY_PRECOMMIT_PRETTIER_STAGED" = "1" ]  && husky_run_step "Prettier (staged)"        husky_lint_prettier_staged
  [ "$HUSKY_PRECOMMIT_ESLINT_STAGED" = "1" ]    && husky_run_step "ESLint (staged)"          husky_lint_eslint_staged
  [ "$HUSKY_PRECOMMIT_STYLELINT_STAGED" = "1" ] && husky_run_step "Stylelint (staged)"       husky_lint_stylelint_staged
  [ "$HUSKY_PRECOMMIT_TSC" = "1" ]              && husky_run_step "TypeScript --noEmit"     husky_lint_tsc_full
  [ "$HUSKY_PRECOMMIT_SEMGREP_STAGED" = "1" ]   && husky_run_step "Semgrep (staged)"         husky_lint_semgrep_staged
  [ "$HUSKY_PRECOMMIT_LOCT_HEALTH" = "1" ]      && husky_run_advisory "Loctree health"       husky_lint_loct_health
  [ "$HUSKY_PRECOMMIT_LOCT_SUPPRESSIONS" = "1" ] && husky_run_step "Loctree suppressions"    husky_lint_loct_suppressions
  [ "$HUSKY_PRECOMMIT_RUSTFMT_STAGED" = "1" ]   && husky_run_step "rustfmt (staged)"         husky_lint_rustfmt_staged
  [ "$HUSKY_PRECOMMIT_RUST_CARGO_CHECK" = "1" ] && husky_run_step "cargo check"              husky_lint_cargo_check
  [ "$HUSKY_PRECOMMIT_PY_RUFF" = "1" ]          && husky_run_step "ruff (staged)"            husky_lint_py_ruff_staged
  [ "$HUSKY_PRECOMMIT_SH_SHELLCHECK" = "1" ]    && husky_run_step "shellcheck (staged)"      husky_lint_sh_shellcheck_staged

  husky_run_local_extensions "$HUSKY_HOOK_NAME"

  if [ "$STEP_FAILURE_COUNT" -eq 0 ]; then
    husky_ok "pre-commit gate passed"
  else
    husky_warn "pre-commit completed with $STEP_FAILURE_COUNT warning(s) (WARN mode)"
  fi
) 2>&1 | husky_secrets_redact | tee "$LOG_FILE"
status=${PIPESTATUS[0]}
set -e

if [ "$status" -eq 0 ]; then
  husky_warns_clear_for_hook "$HUSKY_HOOK_NAME"
  exit 0
fi

# If any strict step (secret guard, env-file guard) failed, refuse to demote
# regardless of branch policy. WARN mode is for quality regressions, not for
# credentials landing in the commit object.
if husky_strict_failed; then
  husky_err "STRICT step failed — WARN-mode override DISABLED. Commit blocked."
  husky_warns_archive "$HUSKY_HOOK_NAME" "$LOG_FILE" >/dev/null
  exit "$status"
fi

signature="$(husky_warns_archive "$HUSKY_HOOK_NAME" "$LOG_FILE")"
# Escalate only when THIS signature appears in more than one archived log,
# i.e. the same failure has been seen before. The current failure was just
# archived (so it always contributes 1) — a count > 1 means a genuine repeat.
# Counting all *.log files instead would escalate on any unrelated warning.
if [ "$(grep -l "^signature=${signature}$" "$(husky_warns_dir)"/"${HUSKY_HOOK_NAME}"-*.log 2>/dev/null | wc -l | tr -d ' ')" -gt 1 ]; then
  husky_err "Same failure signature already seen — escalating back to strict."
  husky_err "Signature: $signature"
  husky_err "Inspect: ls -1t .husky/warns/${HUSKY_HOOK_NAME}-*.log | head -2"
  exit "$status"
fi

if husky_warn_mode_active; then
  # shellcheck disable=SC2012
  husky_warn "WARN mode: commit allowed, log archived as $(ls -1t "$(husky_warns_dir)"/"${HUSKY_HOOK_NAME}"-*.log | head -1)"
  exit 0
fi
exit "$status"
