package com.zioinfo.kintex.mail;

import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.mail.javamail.JavaMailSender;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;

/**
 * MailService/MailBatch 단위 테스트 — ①비활성(MAIL_ENABLED=false) 스킵 ②수신자 마스킹 ③배치 분할.
 * SMTP 연동 없이 순수 로직만 검증한다.
 */
class MailServiceTest {

    @SuppressWarnings("unchecked")
    private ObjectProvider<JavaMailSender> providerOf(JavaMailSender sender) {
        ObjectProvider<JavaMailSender> p = mock(ObjectProvider.class);
        when(p.getIfAvailable()).thenReturn(sender);
        return p;
    }

    @Test
    void disabled_skips_actual_send_and_records_skipped() {
        MailProperties props = new MailProperties();
        props.setEnabled(false);                       // MAIL_ENABLED=false
        JavaMailSender sender = mock(JavaMailSender.class);
        MailLogMapper mapper = mock(MailLogMapper.class);

        MailService svc = new MailService(props, providerOf(sender), mapper);
        svc.send("AUCTION_OPEN", "AUC-1", "kimchulsu@domain.com", "제목", "<p>body</p>");

        // 실제 SMTP 전송은 발생하지 않는다.
        verify(sender, never()).send(any(jakarta.mail.internet.MimeMessage.class));
        // 이력은 skipped 상태 + 마스킹 수신자로 기록.
        ArgumentCaptor<String> statusCap = ArgumentCaptor.forClass(String.class);
        ArgumentCaptor<String> recipientCap = ArgumentCaptor.forClass(String.class);
        verify(mapper).insert(anyString(), eq("AUCTION_OPEN"), eq("AUC-1"), anyString(),
                recipientCap.capture(), statusCap.capture(), any());
        assertThat(statusCap.getValue()).isEqualTo("skipped");
        assertThat(recipientCap.getValue()).isEqualTo("kim***@domain.com");
    }

    @Test
    void sender_absent_also_skips() {
        MailProperties props = new MailProperties();
        props.setEnabled(true);                        // 켜져 있어도 sender 없으면 스킵
        MailLogMapper mapper = mock(MailLogMapper.class);

        MailService svc = new MailService(props, providerOf(null), mapper);
        svc.send("EDM", "cp-1", "a@b.com", "제목", "<p>body</p>");

        verify(mapper).insert(anyString(), eq("EDM"), eq("cp-1"), anyString(),
                anyString(), eq("skipped"), any());
    }

    @Test
    void maskEmail_masks_local_part() {
        assertThat(MailService.maskEmail("kimchulsu@domain.com")).isEqualTo("kim***@domain.com");
        assertThat(MailService.maskEmail("ab@x.com")).isEqualTo("a***@x.com");
        assertThat(MailService.maskEmail(null)).isEqualTo("***");
        assertThat(MailService.maskEmail("noatsign")).isEqualTo("***");
    }

    @Test
    void batch_partitions_by_size() {
        List<Integer> items = new java.util.ArrayList<>();
        for (int i = 0; i < 120; i++) {
            items.add(i);
        }
        List<List<Integer>> batches = MailBatch.partition(items, 50);
        assertThat(batches).hasSize(3);
        assertThat(batches.get(0)).hasSize(50);
        assertThat(batches.get(1)).hasSize(50);
        assertThat(batches.get(2)).hasSize(20);
    }

    @Test
    void batch_empty_and_nonpositive() {
        assertThat(MailBatch.partition(List.<Integer>of(), 50)).isEmpty();
        assertThat(MailBatch.partition(List.of(1, 2, 3), 0)).hasSize(1);
    }
}
