package com.zioinfo.kintex.security;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

/**
 * OTP 챌린지 재시도 시맨틱 회귀 테스트(2026-07-12 라이브 장애).
 * 오입력 1회가 챌린지를 태우면 "코드 틀림 → 세션 만료" 루프에 갇힌다 —
 * 실패 시 챌린지는 유지(5회 한도), 소비는 검증 성공 시에만.
 */
class OtpChallengeStoreTest {

    @Test
    void failureKeepsChallengeAliveUntilLimit() {
        OtpChallengeStore store = new OtpChallengeStore();
        String token = store.issue("usr-1");

        // 실패 4회까지는 챌린지 유지(재시도 가능)
        for (int i = 1; i <= 4; i++) {
            assertTrue(store.recordFailure(token), "실패 " + i + "회차엔 챌린지가 살아 있어야 한다");
            assertEquals("usr-1", store.peek(token));
        }
        // 5회째 실패 → 무효화
        assertFalse(store.recordFailure(token));
        assertNull(store.peek(token));
        assertNull(store.consume(token));
    }

    @Test
    void consumeIsOneShot() {
        OtpChallengeStore store = new OtpChallengeStore();
        String token = store.issue("usr-2");
        assertEquals("usr-2", store.peek(token));
        assertEquals("usr-2", store.consume(token));
        assertNull(store.consume(token));
    }

    @Test
    void unknownTokenIsRejected() {
        OtpChallengeStore store = new OtpChallengeStore();
        assertFalse(store.recordFailure("no-such-token"));
        assertNull(store.peek(null));
        assertNull(store.consume(null));
    }
}
