#!/usr/bin/env bash
# S2 — 무손실 승계(복원성 축): 부하 중 원장엔진(Hermes)을 강제 종료했다가 재기동해도
# 선저널(write-ahead)+Kafka 오프셋 재생으로 유실 0·전건 완결되는지 검증.
# 복원력방안 부록A S2 재현. 실행: bash sim/s2_failover.sh [건수]
# ⚠ Hermes를 죽였다 살리므로 수동 기능테스트와 겹치지 않을 때 실행 권장.
cd "$(dirname "$0")"; source ./lib.sh
N=${1:-40}
FAILED=0
BANKS=(1001 1002 1003 1004 1005 1006 1007 1010)
declare -a BMIS

hr; echo "S2 무손실 승계 검증 — 이체 ${N}건 투입 중 Hermes 강제 종료·재기동"; hr
TOTAL_BEFORE=$(q "SELECT sum(balance) FROM account")
echo "  이체 전 총액 = $TOTAL_BEFORE"

KILL_AT=$((N/3)); RESTARTED=0
for ((i=1;i<=N;i++)); do
  fi=${BANKS[$((RANDOM % ${#BANKS[@]}))]}
  ti=${BANKS[$((RANDOM % ${#BANKS[@]}))]}
  while [ "$ti" = "$fi" ]; do ti=${BANKS[$((RANDOM % ${#BANKS[@]}))]}; done
  bmi=$(mkbmi "$fi" "$i"); BMIS+=("$bmi")
  submit "$fi" "$ti" "$(( (RANDOM % 300) + 1 ))" "$bmi"

  if [ "$i" = "$KILL_AT" ] && [ "$RESTARTED" = "0" ]; then
    HP=$(pid_of hermes)
    echo "  >> $i건째: Hermes(PID $HP) 강제 종료"
    [ -n "$HP" ] && taskkill //F //PID "$HP" //T >/dev/null 2>&1
    sleep 3
    echo "  >> Hermes 재기동"
    start_svc "RTGS Hermes (S2 재기동)" hermes
    RESTARTED=1
  fi
  sleep 0.2
done

echo "  투입 완료. Hermes 복귀·정산 드레인 대기(최대 90s)..."
wait_drain 90 && echo "  드레인 완료" || echo "  (경고) 드레인 타임아웃 — 아래 잔류 확인"

# 투입한 BMI 전건이 종료상태(ACCC/RJCT)에 도달했는지 — 단일 쿼리(IN 리스트)로 확인
INLIST=$(printf "'%s'," "${BMIS[@]}"); INLIST=${INLIST%,}
TERM=$(q "SELECT count(*) FROM transfer WHERE bmi IN ($INLIST) AND status IN ('ACCC','RJCT')")
STUCK_LIST=$(PSQL -t -A -c "SELECT bmi||'('||status||')' FROM transfer WHERE bmi IN ($INLIST) AND status NOT IN ('ACCC','RJCT')" | tr '\n' ' ')
TOTAL_AFTER=$(q "SELECT sum(balance) FROM account")
NEG=$(q "SELECT count(*) FROM account WHERE balance < 0")

hr; echo "결과"; hr
[ "$TERM" = "$N" ] && pass "투입 $N건 전건 완결(ACCC/RJCT) — 유실 0" || fail "$((N-TERM))건 미완결:$STUCK_LIST"
[ "$TOTAL_AFTER" = "$TOTAL_BEFORE" ] && pass "총액 보존: $TOTAL_AFTER" || fail "총액 불일치: $TOTAL_BEFORE -> $TOTAL_AFTER"
[ "$NEG" = "0" ] && pass "잔액 음수 계좌 0" || fail "음수 계좌 $NEG 건"
hr
[ "$FAILED" = "0" ] && echo "S2 PASS ✅ (선저널+오프셋 재생으로 무손실 승계)" || echo "S2 FAIL ❌"
exit $FAILED
