#!/usr/bin/env bash
set -euo pipefail

if ! command -v git-format-staged >/dev/null 2>&1; then
  echo "error: git-format-staged is required for the pre-commit hook" >&2
  echo "install it or bypass with git commit --no-verify" >&2
  exit 1
fi

stash_created=0

install_commit_msg_hook() {
  local repo_root
  repo_root="$(git rev-parse --show-toplevel)"
  "$repo_root/scripts/install-git-hook-shims" commit-msg
}

staged_paths_are_docs_or_media_only() {
  local path
  local found=0

  while IFS= read -r path; do
    found=1
    case "${path,,}" in
      docs/*|*.md|*.markdown|*.avif|*.gif|*.jpeg|*.jpg|*.png|*.svg|*.webp) ;;
      *) return 1 ;;
    esac
  done < <(git diff --cached --name-only --diff-filter=ACMRD)

  [[ "$found" -eq 1 ]]
}

restore_unstaged() {
  local status=$?
  if [[ "$stash_created" -eq 1 ]]; then
    if ! git stash pop --quiet; then
      echo "error: failed to restore unstaged changes after pre-commit checks" >&2
      echo "resolve the stash conflict, then run git stash drop when finished" >&2
      status=1
    fi
  fi
  exit "$status"
}
trap restore_unstaged EXIT

hide_unstaged_changes() {
  if git diff --quiet --ignore-submodules -- && [[ -z "$(git ls-files --others --exclude-standard)" ]]; then
    return 0
  fi
  git stash push --quiet --keep-index --include-untracked -m "pre-commit unstaged changes"
  stash_created=1
}

install_commit_msg_hook
git-format-staged
hide_unstaged_changes

if staged_paths_are_docs_or_media_only; then
  echo "skip pre-commit checks: only documentation or media files staged"
  exit 0
fi

if ! just pre-commit; then
  echo "pre-commit checks failed" >&2
  echo "if clippy reported fixable lints, run: just clippy-fix" >&2
  echo "review and stage any fixes, then commit again" >&2
  exit 1
fi
