package com.zioinfo.kintex.publicsite.subscription;

import com.zioinfo.kintex.mail.MailProperties;
import com.zioinfo.kintex.mail.MailService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

/**
 * F-C1 티켓 오픈 감지 스케줄러 단위테스트 — dry-run 기본·화이트리스트·운영 발송·중복 발송 방지.
 */
class TicketOpenNotifierTest {

    private EventSubscriptionMapper mapper;
    private MailService mailService;
    private MailProperties props;
    private TicketOpenNotifier notifier;

    @BeforeEach
    void setUp() {
        mapper = mock(EventSubscriptionMapper.class);
        mailService = mock(MailService.class);
        props = new MailProperties();  // 실 객체(기본 edmTestMode=true)
        notifier = new TicketOpenNotifier(mapper, mailService, props);
        when(mapper.markNotified(anyString())).thenReturn(1);   // 선점 성공(기본)
    }

    private static Map<String, Object> sub(String id, String email) {
        return Map.of("id", id, "eventId", "e1", "email", email,
                "unsubToken", "tok-" + id, "eventName", "데모행사");
    }

    @Test
    void empty_noOp() {
        when(mapper.findPendingTicketOpen(anyInt())).thenReturn(List.of());
        assertEquals(0, notifier.runOnce());
        verifyNoInteractions(mailService);
    }

    @Test
    void testMode_dryRun_marksButDoesNotEmailSubscriber() {
        // 기본 테스트 모드 + 화이트리스트 비어 있음 → 실 구독자 미발송(dry-run), 처리 마킹은 수행.
        when(mapper.findPendingTicketOpen(anyInt())).thenReturn(List.of(sub("s1", "real@user.com")));
        int n = notifier.runOnce();
        assertEquals(1, n);
        verify(mapper).markNotified("s1");
        verifyNoInteractions(mailService);   // 실 구독자에게 발송 안 함
    }

    @Test
    void testMode_sendsOnlyToWhitelist() {
        props.setEdmTestRecipients(List.of("qa@kintex.test"));
        when(mapper.findPendingTicketOpen(anyInt())).thenReturn(List.of(sub("s1", "real@user.com")));
        notifier.runOnce();
        // 화이트리스트로만 발송, 실 구독자(real@user.com)로는 발송 안 함.
        verify(mailService).send(eq("TICKET_OPEN_TEST"), eq("s1"), eq("qa@kintex.test"),
                anyString(), anyString());
        verify(mailService, never()).send(anyString(), anyString(), eq("real@user.com"),
                anyString(), anyString());
    }

    @Test
    void liveMode_sendsToSubscriber() {
        props.setEdmTestMode(false);   // 운영 실발송(설정으로만 개방)
        when(mapper.findPendingTicketOpen(anyInt())).thenReturn(List.of(sub("s1", "real@user.com")));
        notifier.runOnce();
        verify(mailService).send(eq("TICKET_OPEN"), eq("s1"), eq("real@user.com"),
                anyString(), anyString());
    }

    @Test
    void skipsAlreadyClaimed() {
        when(mapper.findPendingTicketOpen(anyInt())).thenReturn(List.of(sub("s1", "real@user.com")));
        when(mapper.markNotified("s1")).thenReturn(0);   // 경쟁 — 이미 통지됨
        props.setEdmTestMode(false);
        assertEquals(0, notifier.runOnce());
        verifyNoInteractions(mailService);
    }
}
