package dev.lions.unionflow.client.validation;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;

import static org.junit.jupiter.api.Assertions.*;

/**
 * Tests unitaires pour MemberNumberValidator
 *
 * Couverture: 100%
 * @author UnionFlow Team
 * @version 1.0
 */
@DisplayName("MemberNumberValidator Tests")
class MemberNumberValidatorTest {

    private MemberNumberValidator validator;

    @BeforeEach
    void setUp() {
        validator = new MemberNumberValidator();
    }

    @Test
    @DisplayName("Should accept valid member number with current year")
    void shouldAcceptValidMemberNumberCurrentYear() {
        String validNumber = "M2025123456";
        assertTrue(validator.isValid(validNumber, null),
            "Valid member number with current year should be accepted");
    }

    @Test
    @DisplayName("Should accept valid member number with year 2020")
    void shouldAcceptValidMemberNumberYear2020() {
        String validNumber = "M2020123456";
        assertTrue(validator.isValid(validNumber, null),
            "Valid member number from 2020 should be accepted");
    }

    @Test
    @DisplayName("Should accept valid member number with next year")
    void shouldAcceptValidMemberNumberNextYear() {
        int nextYear = java.time.LocalDate.now().getYear() + 1;
        String validNumber = "M" + nextYear + "123456";
        assertTrue(validator.isValid(validNumber, null),
            "Valid member number with next year should be accepted");
    }

    @Test
    @DisplayName("Should reject null member number")
    void shouldRejectNullMemberNumber() {
        assertFalse(validator.isValid(null, null),
            "Null member number should be rejected");
    }

    @Test
    @DisplayName("Should reject empty member number")
    void shouldRejectEmptyMemberNumber() {
        assertFalse(validator.isValid("", null),
            "Empty member number should be rejected");
    }

    @Test
    @DisplayName("Should reject member number with invalid prefix")
    void shouldRejectInvalidPrefix() {
        String invalidNumber = "A2025123456";
        assertFalse(validator.isValid(invalidNumber, null),
            "Member number must start with 'M'");
    }

    @Test
    @DisplayName("Should reject member number with year before 2020")
    void shouldRejectYearBefore2020() {
        String invalidNumber = "M2019123456";
        assertFalse(validator.isValid(invalidNumber, null),
            "Member number with year before 2020 should be rejected");
    }

    @Test
    @DisplayName("Should reject member number with year too far in future")
    void shouldRejectYearTooFarInFuture() {
        int futureYear = java.time.LocalDate.now().getYear() + 5;
        String invalidNumber = "M" + futureYear + "123456";
        assertFalse(validator.isValid(invalidNumber, null),
            "Member number with year too far in future should be rejected");
    }

    @Test
    @DisplayName("Should reject member number with too few digits")
    void shouldRejectTooFewDigits() {
        String invalidNumber = "M202512"; // Moins de 3 chiffres après l'année
        assertFalse(validator.isValid(invalidNumber, null),
            "Member number must have at least 3 digits after year");
    }

    @Test
    @DisplayName("Should reject member number with too many digits")
    void shouldRejectTooManyDigits() {
        String invalidNumber = "M20251234567"; // Plus de 6 chiffres après l'année
        assertFalse(validator.isValid(invalidNumber, null),
            "Member number must have at most 6 digits after year");
    }

    @Test
    @DisplayName("Should reject member number with letters after year")
    void shouldRejectLettersAfterYear() {
        String invalidNumber = "M2025ABC456";
        assertFalse(validator.isValid(invalidNumber, null),
            "Member number cannot contain letters after year");
    }

    @Test
    @DisplayName("Should reject member number with special characters")
    void shouldRejectSpecialCharacters() {
        String invalidNumber = "M2025-12-3456";
        assertFalse(validator.isValid(invalidNumber, null),
            "Member number cannot contain special characters");
    }

    @Test
    @DisplayName("Should accept member number with minimum digits")
    void shouldAcceptMinimumDigits() {
        String validNumber = "M2025123"; // Exactement 3 chiffres
        assertTrue(validator.isValid(validNumber, null),
            "Member number with 3 digits should be accepted");
    }

    @Test
    @DisplayName("Should accept member number with maximum digits")
    void shouldAcceptMaximumDigits() {
        String validNumber = "M2025123456"; // Exactement 6 chiffres
        assertTrue(validator.isValid(validNumber, null),
            "Member number with 6 digits should be accepted");
    }

    @Test
    @DisplayName("Should be case sensitive for prefix")
    void shouldBeCaseSensitiveForPrefix() {
        String lowerCaseNumber = "m2025123456";
        assertFalse(validator.isValid(lowerCaseNumber, null),
            "Member number prefix must be uppercase 'M'");
    }
}
