#!/usr/bin/env bash
# PreToolUse(Write) — 새 화면의 첫 파일을 쓰기 전에 UX 계약이 정해졌는지 검사한다.
#
# 왜: 기존 UI 게이트(ui-quality·slop-check·ui-critic)는 전부 코드가 나온 뒤에 돈다.
# 그래서 "어떻게 생겼나"가 아니라 "어떻게 행동하나"의 결정(확인을 받나, 0건일 때
# 뭘 보여주나, 실패하면 어디로 가나)은 아무도 안 정한 채 화면마다 다르게 발명되고,
# 발산은 화면이 다 만들어진 뒤에야 드러난다 — 그때 고치면 구조를 다시 짠다.
# 실사용 관찰에서 서로 모르는 세 사람이 같은 뿌리를 지적했다: 확인 없이
# 즉시 전송되는 버튼, 화면마다 모양이 다른 확인 창, 제품과 결이 다른 톤.
# 그래서 검사 대상이 코드가 아니라 fe-design 문서다 — 코드보다 앞에 있는 유일한 산출물.
#
# 대상은 pages 슬라이스의 첫 화면 파일 하나뿐이다(후속 파일·수정은 통과). 실패 시
# 조용히 통과(fail-open) — 게이트가 죽어도 작업은 안 막는다.

set -u
input=$(cat 2>/dev/null || true)
fp=$(printf '%s' "$input" | node "$(dirname "$0")/read-json-field.mjs" tool_input.file_path 2>/dev/null || true)
[ -n "$fp" ] || exit 0

case "$fp" in
  */src/pages/*/ui/*.tsx) ;;
  *) exit 0 ;;
esac
case "$fp" in
  *.spec.*|*.test.*|*_gate-selftest*|*/pages/sample-table/*|*/pages/not-found/*) exit 0 ;;
esac
[ -e "$fp" ] && exit 0

slice=$(printf '%s' "$fp" | sed -E 's|.*/src/pages/([^/]+)/.*|\1|')
[ -n "$slice" ] || exit 0

# 슬라이스의 첫 화면 파일일 때만. 후속 파일마다 물으면 순수 마찰이 된다.
slice_dir=$(printf '%s' "$fp" | sed -E 's|(.*/src/pages/[^/]+)/.*|\1|')
if [ -d "$slice_dir" ] &&
   [ -n "$(find "$slice_dir" -name '*.tsx' ! -name '*.spec.tsx' -print -quit 2>/dev/null)" ]; then
  exit 0
fi

# 최장(%%)이 아니라 최단(%) — 조상 경로에 src가 있으면(~/src/myapp 같은 흔한 배치)
# %%가 거기서 잘라 루트를 조부모로 잡는다. 그러면 설계 문서를 제대로 써도 영영 통과하지
# 못하고 안내 문구가 엉뚱한 경로를 가리킨다(실측 확인).
root=${fp%/src/*}
docdir="$root/docs/features"

deny() {
  printf '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"%s"}}' "$1"
  exit 0
}

FORMAT='- **register**: product\n- **되돌릴 수 없는 동작**: (없으면 없음이라고 적기)\n- **빈 상태**: 0건일 때 문구 + 다음 행동\n- **로딩·실패**: 기다릴 때 / 실패했을 때\n- **최소 폭**: 1280 기준, 768까지'

if [ ! -d "$docdir" ]; then
  deny "이 화면의 설계 문서가 아직 없습니다. start-feature 스킬로 7-step을 먼저 진행해 docs/features/<slug>.md를 만드세요. 특히 Step 2.5 UX 계약 5줄이 채워져 있어야 이 파일을 쓸 수 있습니다.\n\n$FORMAT"
fi

# 이 슬라이스를 언급하는 설계 문서를 찾는다 (Step 3 컴포넌트 트리·Step 6 라우트에 자연히 나온다).
doc=''
for f in "$docdir"/*.md; do
  [ -f "$f" ] || continue
  if grep -qF "$slice" "$f" 2>/dev/null; then doc="$f"; break; fi
done

if [ -z "$doc" ]; then
  deny "docs/features/ 안에 '$slice' 화면을 다루는 설계 문서가 없습니다. start-feature로 이 화면의 7-step을 먼저 진행하세요 — Step 2.5 UX 계약까지 채워야 통과합니다.\n\n$FORMAT"
fi

missing=''
for key in 'register' '되돌릴 수 없는 동작' '빈 상태' '로딩·실패' '최소 폭'; do
  line=$(grep -E "^[[:space:]]*-[[:space:]]*\*\*${key}\*\*:" "$doc" 2>/dev/null | head -1)
  value=$(printf '%s' "$line" | sed -E "s|^[[:space:]]*-[[:space:]]*\*\*${key}\*\*:[[:space:]]*||")
  case "$value" in
    ''|'?'|'미정'|'TBD'|'-') missing="$missing $key" ;;
  esac
done

if [ -n "$missing" ]; then
  deny "설계 문서($(basename "$doc"))의 UX 계약이 비어 있습니다 — 안 채워진 항목:$missing\n\n화면이 어떻게 생겼는지가 아니라 어떻게 행동하는지를 코드 전에 정하는 자리입니다. 정할 근거가 없으면 기본값을 쓰되 미정으로 남기지 마세요 — 기본값도 결정입니다. start-feature Step 2.5 참고.\n\n$FORMAT\n\n확인 창은 새로 만들지 말고 shared/ui의 openConfirmDialog를 쓰세요."
fi

exit 0
