#!/usr/bin/env bash
#
# Claude Code PreToolUse hook (Edit|Write matcher).
# Blocks edits to autogenerated files. Receives JSON on stdin with the
# tool invocation payload; inspects .tool_input.file_path.
#
# This script prevents accidental modification of autogenerated files
# in the build/package pipeline. Add file paths to the AUTOGENERATED_FILES
# array below to protect them from manual edits.
#

set -euo pipefail

# Autogenerated files that should not be manually edited.
#
# Each entry is either:
#   - A base name (no extension): matches any .cpp or .hpp file with that name
#     e.g. "UserPrefValues" blocks UserPrefValues.cpp and UserPrefValues.hpp
#   - A filename with extension: exact filename match (any directory)
#     e.g. "SessionUserPrefValues.R" blocks that specific file
#   - A regex pattern (contains [, |, or (): matched against the full path
#     e.g. "UserPrefsAccessor[^/]*\.(java|properties)" blocks all variants
AUTOGENERATED_FILES=(
  # Generated by scripts/generate-prefs.R
  "UserPrefValues"
  "UserStateValues"
  "UserPrefsAccessor[^/]*\.java"
  "UserStateAccessor[^/]*\.java"
  "UserPrefsAccessorConstants_en.properties"
  "UserStateAccessorConstants_en.properties"
  "SessionUserPrefValues.R"

  # Generated by scripts/generate-options.R
  "*.gen.*"

  # Generated during GWT build (ant draft)
  "CmdConstants[^/]*\.java"
  "MenuConstants[^/]*\.java"
  "CmdConstants_en.properties"
  "MenuConstants_en.properties"
  "Commands.cmd.xml.MD5"
)

# Read tool input JSON from stdin (passed by Claude Code PreToolUse hook)
input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty') || {
  echo "WARNING: Failed to parse hook input JSON. Blocking as a precaution." >&2
  exit 2
}

if [ -z "$file_path" ]; then
  exit 0
fi

# Returns a remediation message for the matched file.
remediation_message() {
  local path="$1"
  if echo "$path" | grep -qE '(UserPrefValues|UserStateValues|UserPrefsAccessor|UserStateAccessor|SessionUserPrefValues)\b'; then
    echo "Edit the schema in src/cpp/session/resources/schema/ instead, then run: Rscript scripts/generate-prefs.R"
  elif echo "$path" | grep -qE '\.gen\.'; then
    echo "Edit server-options.json or session-options.json instead, then run: Rscript scripts/generate-options.R"
  elif echo "$path" | grep -qE '(CmdConstants|MenuConstants|Commands\.cmd\.xml\.MD5)'; then
    echo "Edit Commands.cmd.xml instead, then build with: cd src/gwt && ant draft"
  else
    echo "This file is autogenerated and should not be manually edited."
  fi
}

# Check if the file being edited matches any autogenerated file pattern
for entry in "${AUTOGENERATED_FILES[@]}"; do
  if [[ "$entry" =~ [\[\|\(] ]]; then
    # Regex pattern: match against full path
    match=$(echo "$file_path" | grep -E "(^|/)${entry}$" || true)
  elif [[ "$entry" == *[\*\?.]* ]]; then
    # Glob-style pattern (contains *, ?, or .): convert to regex
    regex=$(echo "$entry" | sed 's/\./\\./g; s/\*/.*/g')
    match=$(echo "$file_path" | grep -E "(^|/)${regex}$" || true)
  else
    # Base name (no extension): match .cpp or .hpp
    match=""
    for ext in cpp hpp; do
      match=$(echo "$file_path" | grep -E "(^|/)${entry}\.${ext}$" || true)
      if [ -n "$match" ]; then break; fi
    done
  fi

  if [ -n "$match" ]; then
    advice=$(remediation_message "$file_path")
    echo "BLOCKED: '$file_path' is autogenerated. $advice" >&2
    exit 2
  fi
done
