package com.njcn.msgpush.module.push.service.retry;

import com.njcn.msgpush.module.push.dal.dataobject.message.MessageRecordDO;
import org.junit.jupiter.api.Test;

import java.time.Duration;
import java.time.LocalDateTime;

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

/**
 * 限流重试治本核心的纯决策逻辑单测（无 Spring / 无 DB / 无 Redis）。
 */
class RetryDecisionLogicTest {

    @Test
    void isRateLimit_trueOnlyForRateLimitErrorCode() {
        MessageRecordDO rateLimited = new MessageRecordDO();
        rateLimited.setErrorCode("RATE_LIMIT");
        assertTrue(MessageRetryQueueServiceImpl.isRateLimit(rateLimited));

        MessageRecordDO other = new MessageRecordDO();
        other.setErrorCode("SOMETHING_ELSE");
        assertFalse(MessageRetryQueueServiceImpl.isRateLimit(other));

        MessageRecordDO noCode = new MessageRecordDO();
        assertFalse(MessageRetryQueueServiceImpl.isRateLimit(noCode));

        assertFalse(MessageRetryQueueServiceImpl.isRateLimit(null));
    }

    @Test
    void isRateLimitExhausted_nullFirstFailTimeMeansNotExhausted() {
        assertFalse(MessageRetryQueueServiceImpl.isRateLimitExhausted(null, LocalDateTime.now()));
    }

    @Test
    void isRateLimitExhausted_falseBelow12h_trueAtOrAbove12h() {
        LocalDateTime now = LocalDateTime.now();
        // 43199s < 12h → 未满
        assertFalse(MessageRetryQueueServiceImpl.isRateLimitExhausted(now.minusSeconds(43199), now));
        // 43200s == 12h → 满（>=）
        assertTrue(MessageRetryQueueServiceImpl.isRateLimitExhausted(now.minusSeconds(43200), now));
        // 43201s > 12h → 满
        assertTrue(MessageRetryQueueServiceImpl.isRateLimitExhausted(now.minusSeconds(43201), now));
    }

    @Test
    void calculateNextRetryTime_rateLimitUsesFixed120s() {
        MessageRetryQueueServiceImpl service = new MessageRetryQueueServiceImpl();
        LocalDateTime before = LocalDateTime.now();
        LocalDateTime next = service.calculateNextRetryTime("SMS", 1, true);
        long seconds = Duration.between(before, next).getSeconds();
        // rate-limit 分支在使用任何字段前就 return，故 new 裸实例可调；允许执行抖动 ±2s
        assertTrue(seconds >= 118 && seconds <= 122, "expected ~120s, got " + seconds);
    }
}
