package kr.or.bok.rtgs.prada

import kr.or.bok.rtgs.common.QuorumContext
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test

/** B2 정족수 집계 규율 고정 테스트. */
class QuorumAggregatorTest {

    @Test
    fun `1센터는 자기 보고 1건으로 즉시 과반`() {
        val agg = QuorumAggregator(QuorumContext("DC1", 1)) // quorum=1
        assertTrue(agg.record("bmiA", "DC1"), "1센터: 첫 보고에 과반 도달")
        assertTrue(agg.isFinalized("bmiA"))
    }

    @Test
    fun `3센터는 2개 서로 다른 센터에서 과반 도달`() {
        val agg = QuorumAggregator(QuorumContext("DC1", 3)) // quorum=2
        assertFalse(agg.record("bmiA", "DC1"), "1개 센터: 아직 미달")
        assertEquals(1, agg.count("bmiA"))
        assertTrue(agg.record("bmiA", "DC2"), "2개 센터: 과반 최초 도달")
        assertTrue(agg.isFinalized("bmiA"))
    }

    @Test
    fun `같은 센터 중복 보고는 집계되지 않는다`() {
        val agg = QuorumAggregator(QuorumContext("DC1", 3)) // quorum=2
        assertFalse(agg.record("bmiA", "DC1"))
        assertFalse(agg.record("bmiA", "DC1"), "동일 센터 재보고: 중복 제거 → 여전히 미달")
        assertEquals(1, agg.count("bmiA"))
    }

    @Test
    fun `과반 최초 도달은 단 한 번만 true`() {
        val agg = QuorumAggregator(QuorumContext("DC1", 3)) // quorum=2
        agg.record("bmiA", "DC1")
        assertTrue(agg.record("bmiA", "DC2"), "최초 도달")
        assertFalse(agg.record("bmiA", "DC3"), "이미 완결: 세 번째 보고는 false(멱등)")
    }

    @Test
    fun `완결 후 늦은 ack는 상태를 되돌리지 않는다`() {
        val agg = QuorumAggregator(QuorumContext("DC1", 3))
        agg.record("bmiA", "DC1")
        agg.record("bmiA", "DC2") // 완결
        assertTrue(agg.isFinalized("bmiA"))
        assertFalse(agg.record("bmiA", "DC3"))
        assertTrue(agg.isFinalized("bmiA"), "여전히 완결 유지")
    }

    @Test
    fun `서로 다른 bmi는 독립 집계`() {
        val agg = QuorumAggregator(QuorumContext("DC1", 3))
        assertFalse(agg.record("bmiA", "DC1"))
        assertFalse(agg.record("bmiB", "DC2"))
        assertFalse(agg.isFinalized("bmiA"))
        assertFalse(agg.isFinalized("bmiB"))
    }
}
