#!/usr/bin/env bash
# S4 — 순서오류 탐지·교정(기능성 축): 저널(rtgs.journal)에 전역순번을 역전시켜 주입해도
# 원장엔진(Hermes)이 gap을 버퍼링→순서대로 재정렬 적용하는지 검증.
# 복원력방안 부록A S4 재현. 실행: bash sim/s4_order.sh
# ⚠ 순번기(Sequencer)를 잠시 멈추고 저널에 직접 주입한다(2-1 순번 영속화 덕에 재기동 시 안전 복원).
#   수동 기능테스트와 겹치지 않을 때 실행 권장.
cd "$(dirname "$0")"; source ./lib.sh
export KAFKA_HEAP_OPTS="-Xmx256M -Xms256M"   # kafka .bat의 wmic 분기 회피(포터블)
FAILED=0

hr; echo "S4 순서오류 탐지·교정 검증 — 저널에 seq 역전 주입"; hr

# 0) 드레인(잔여 없게) + 순번기 정지(경쟁 발번 차단)
wait_drain 30 >/dev/null
SP=$(pid_of sequencer)
echo "  Sequencer(PID $SP) 정지 — 주입 동안 경쟁 발번 차단"
[ -n "$SP" ] && taskkill //F //PID "$SP" //T >/dev/null 2>&1
sleep 3

TOTAL_BEFORE=$(q "SELECT sum(balance) FROM account")
M=$(q "SELECT COALESCE(MAX(global_seq),0) FROM journal_log")
echo "  현재 최대 순번 M=$M → 주입 순번 $((M+1)),$((M+2)),$((M+3)) (전달 순서는 역전)"

TS="$(date +%s)000"
B1="20260710S4$(printf '%010d' $((M+1)))"   # seq M+1  1002->1003
B2="20260710S4$(printf '%010d' $((M+2)))"   # seq M+2  1004->1005
B3="20260710S4$(printf '%010d' $((M+3)))"   # seq M+3  1006->1007
entry() { # seq bmi from to amt
  echo "{\"globalSeq\":$1,\"seqEpochMillis\":$TS,\"originCenter\":\"DC1\",\"core\":{\"bmi\":\"$2\",\"msgType\":\"pacs.008.001.08\",\"senderCode\":\"$3\",\"receiverCode\":\"$4\",\"debtorAcct\":\"ACC-$3\",\"creditorAcct\":\"ACC-$4\",\"amount\":$5,\"currency\":\"KRW\",\"origHash\":\"simS4\"}}"
}
# 전달 순서: M+2, M+3, M+1  (역전/gap 주입)
{
  entry $((M+2)) "$B2" 1004 1005 22
  entry $((M+3)) "$B3" 1006 1007 33
  entry $((M+1)) "$B1" 1002 1003 11
} > /tmp/s4_inject.txt
echo "  주입 순서: seq $((M+2)) → $((M+3)) → $((M+1))"
"$KAFKA_PROD" --topic rtgs.journal --bootstrap-server localhost:9092 < /tmp/s4_inject.txt 2>/dev/null

echo "  Hermes 재정렬·적용 대기..."
wait_drain 40 >/dev/null; sleep 2

s1=$(q "SELECT status FROM transfer WHERE bmi='$B1'")
s2=$(q "SELECT status FROM transfer WHERE bmi='$B2'")
s3=$(q "SELECT status FROM transfer WHERE bmi='$B3'")
# journal_log에 순번이 순서대로 기록되었는지
ORDER=$(q "SELECT string_agg(global_seq::text, ',' ORDER BY global_seq) FROM journal_log WHERE global_seq IN ($((M+1)),$((M+2)),$((M+3)))")
TOTAL_AFTER=$(q "SELECT sum(balance) FROM account")

hr; echo "결과"; hr
[ "$s1" = "ACCC" ] && [ "$s2" = "ACCC" ] && [ "$s3" = "ACCC" ] \
  && pass "역전 주입 3건 전건 정상 완결(ACCC) — 재정렬 성공" \
  || fail "완결 실패: seq$((M+1))=$s1 seq$((M+2))=$s2 seq$((M+3))=$s3"
[ "$ORDER" = "$((M+1)),$((M+2)),$((M+3))" ] \
  && pass "저널 순번 순서대로 기록: $ORDER" || fail "순번 기록 이상: $ORDER"
[ "$TOTAL_AFTER" = "$TOTAL_BEFORE" ] && pass "총액 보존: $TOTAL_AFTER" || fail "총액 불일치: $TOTAL_BEFORE -> $TOTAL_AFTER"

# 순번기 재기동(2-1 영속화: MAX(global_seq) 복원해 안전하게 이어서 발번)
echo "  Sequencer 재기동(순번 $((M+3)) 이후부터 복원 발번)"
start_svc "RTGS Sequencer :8090 (S4 복귀)" sequencer
hr
[ "$FAILED" = "0" ] && echo "S4 PASS ✅ (gap 버퍼링→순서 재정렬)" || echo "S4 FAIL ❌"
exit $FAILED
