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

# nix fmtが実行可能なプロジェクトでのみフォーマットを実行します。

# 必要なコマンドが存在するか検証します。
# 基礎的なコマンドなので存在しないのは異常な環境です。
for cmd in nix git; do
  if ! command -v "$cmd" &>/dev/null; then
    echo "Error: required command $cmd is not found" >&2
    exit 1
  fi
done

# CLAUDE_PROJECT_DIRはClaude Codeのhookで必ず設定されるはずの変数です。
if [[ -z "${CLAUDE_PROJECT_DIR:-}" ]]; then
  echo "Error: CLAUDE_PROJECT_DIR is not set" >&2
  exit 1
fi

cd "$CLAUDE_PROJECT_DIR"

# Nixプロジェクトではなければフォーマットの対象外なので正常終了します。
if [[ ! -r "flake.nix" ]]; then
  exit 0
fi

# flakeはGitリポジトリでなければ動作しないので正常終了します。
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
  exit 0
fi

# nixはトラッキングしていないファイルを取り扱わないので、
# 未追跡ファイルの存在だけをGitに登録します。
# git add --allは削除もステージしてしまうため、未追跡ファイルのみを対象にします。
# 未追跡ファイルがなくても空入力で正常終了します。
# hintメッセージを環境変数で抑制して想定外のエラーは残します。
git ls-files --others --exclude-standard -z \
  | GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=advice.addEmptyPathspec GIT_CONFIG_VALUE_0=false \
    git add --intent-to-add --pathspec-from-file=- --pathspec-file-nul

# nix fmtを実行します。
# 既にチェック済みのファイルはキャッシュされてチェックされないので、
# 連続実行してもパフォーマンスは悪くありません。
# フォーマットは自動適用され、
# リンターのエラーがあればそのままClaude Codeに伝わります。
nix fmt
