#!/usr/bin/env bash
# contract-check.sh — S2-Ff: 라이브 엔드포인트 ↔ 동결 fixture *모양* 드리프트 감지 (비차단 runbook).
#
#   라이브 재호출 → 키/타입 diff(LLM 값은 무시) → 드리프트면 비0 exit + fixture-update 안내.
#   PR 게이트 아님 — 수동/Tailscale-CI 트리거([[feedback_pr_gate_vs_runbook_separation]]).
#   fixture 는 동결·불변이며, 이 도구가 감지한 드리프트가 **재캡처 PR 의 유일 합법 트리거**(S2-0d).
#
#   exit: 0 = 드리프트 없음(체크된 것 중) · 1 = breaking 드리프트 · 2 = 아무것도 체크 못함(전부 도달불가)
#   env override: AIFABRIC_LOCALMLX_URL, AIFABRIC_DS_URL
#
# 스킵은 항상 *가시적*으로 출력(silent green 금지, [[feedback_silent_skip_accumulation]]).
set -uo pipefail   # NOT -e: 개별 체크 실패를 모아 보고

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
FIX="$SCRIPT_DIR/fixtures"
PY="$(command -v python3 || echo /usr/bin/python3)"
LLM_URL="${AIFABRIC_LOCALMLX_URL:-http://100.76.254.116:8890}"
DS_URL="${AIFABRIC_DS_URL:-https://document.hyungi.net/api}"
TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT

breaking=0
checked=0

echo "== S2-Ff contract drift check =="
echo "   llm-router: $LLM_URL"
echo "   DS:         $DS_URL"

# --- 1) llm-router /v1/chat/completions  (S2 fixture) ---
echo
echo "[1] llm-router /v1/chat/completions  ↔  llm-router-chat.response.json"
# 동결 request fixture 에서 _meta 떼고 그대로 wire body 로 POST(call-shape 도 함께 검증).
"$PY" -c 'import json,sys; o=json.load(open(sys.argv[1],encoding="utf-8")); o.pop("_meta",None); json.dump(o,open(sys.argv[2],"w"))' \
    "$FIX/llm-router-chat.request.json" "$TMP/req.json" 2>"$TMP/strip_err" || { echo "  SKIP — request fixture 처리 실패: $(head -c160 "$TMP/strip_err")"; }
if [ -s "$TMP/req.json" ]; then
    code="$(curl -sS -m 60 -o "$TMP/llm_live.json" -w '%{http_code}' \
        -H 'Content-Type: application/json' --data @"$TMP/req.json" \
        "$LLM_URL/v1/chat/completions" 2>"$TMP/llm_err" || true)"
    if [ "$code" = "200" ]; then
        checked=$((checked + 1))
        if "$PY" "$SCRIPT_DIR/shape_diff.py" "$FIX/llm-router-chat.response.json" "$TMP/llm_live.json"; then
            echo "  PASS — shape 일치"
        else
            echo "  >> 드리프트: llm-router-chat.{request,response}.json 재캡처 PR 필요"
            breaking=1
        fi
    else
        echo "  SKIP — 도달 불가/비200 (http=${code:-curlfail}; 맥미니 offline?) $(head -c120 "$TMP/llm_err" 2>/dev/null)"
    fi
fi

# --- 2) DS /search/ask  (S1 fixture, best-effort: 인증 필요할 수 있음) ---
echo
echo "[2] DS /search/ask  ↔  ask.json   (best-effort)"
code="$(curl -sS -m 30 -G -o "$TMP/ds_live.json" -w '%{http_code}' \
    --data-urlencode 'q=충격시험은 언제 면제되나' --data-urlencode 'backend=mac-mini-default' \
    "$DS_URL/search/ask" 2>"$TMP/ds_err" || true)"
case "$code" in
    200)
        checked=$((checked + 1))
        if "$PY" "$SCRIPT_DIR/shape_diff.py" "$FIX/ask.json" "$TMP/ds_live.json"; then
            echo "  PASS — shape 일치"
        else
            echo "  >> 드리프트: ask.json(S1) 재캡처 검토"
            breaking=1
        fi ;;
    401|403) echo "  SKIP — 인증 필요(JWT). DS ask 체크는 토큰 주입 시에만(S1 도메인)." ;;
    *)       echo "  SKIP — 도달 불가/비200 (http=${code:-curlfail})." ;;
esac

echo
if [ "$breaking" -ne 0 ]; then
    echo "RESULT: DRIFT 발견 — 위 fixture 재캡처 PR 필요(S2-0d 의 유일 합법 fixture 변경 경로)."
    exit 1
elif [ "$checked" -eq 0 ]; then
    echo "RESULT: 체크한 엔드포인트 0건(전부 도달 불가) — 드리프트 판정 불가. (green 아님 → exit 2)"
    exit 2
else
    echo "RESULT: OK — 체크 ${checked}건 모두 shape 일치, 드리프트 없음."
    exit 0
fi
