package de.gecheckt.pdf.umbenenner.domain.model;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

/**
 * Tests for {@link PreCheckFailureReason}.
 * <p>
 * These tests ensure complete coverage of all enum values and their properties,
 * including descriptions and distinguishing characteristics.
 */
class PreCheckFailureReasonTest {

    @Test
    void testEnumValuesExist() {
        // Verify all expected enum values exist
        assertNotNull(PreCheckFailureReason.NO_USABLE_TEXT);
        assertNotNull(PreCheckFailureReason.PAGE_LIMIT_EXCEEDED);
        assertNotNull(PreCheckFailureReason.CONTENT_NOT_EXTRACTABLE);
        
        // Verify total count to detect unexpected additions
        assertEquals(3, PreCheckFailureReason.values().length);
    }

    @Test
    void testNoUsableTextProperties() {
        PreCheckFailureReason reason = PreCheckFailureReason.NO_USABLE_TEXT;
        
        assertEquals("No usable text in extracted PDF content", reason.getDescription());
        assertEquals("NO_USABLE_TEXT", reason.name());
        assertEquals(0, reason.ordinal());
    }

    @Test
    void testPageLimitExceededProperties() {
        PreCheckFailureReason reason = PreCheckFailureReason.PAGE_LIMIT_EXCEEDED;
        
        assertEquals("Document page count exceeds configured limit", reason.getDescription());
        assertEquals("PAGE_LIMIT_EXCEEDED", reason.name());
        assertEquals(1, reason.ordinal());
    }

    @Test
    void testContentNotExtractableProperties() {
        PreCheckFailureReason reason = PreCheckFailureReason.CONTENT_NOT_EXTRACTABLE;
        
        assertEquals("PDF content not extractable", reason.getDescription());
        assertEquals("CONTENT_NOT_EXTRACTABLE", reason.name());
        assertEquals(2, reason.ordinal());
    }

    @Test
    void testValueOfMethod() {
        // Test that all enum values can be retrieved via valueOf
        assertEquals(PreCheckFailureReason.NO_USABLE_TEXT, 
                PreCheckFailureReason.valueOf("NO_USABLE_TEXT"));
        assertEquals(PreCheckFailureReason.PAGE_LIMIT_EXCEEDED, 
                PreCheckFailureReason.valueOf("PAGE_LIMIT_EXCEEDED"));
        assertEquals(PreCheckFailureReason.CONTENT_NOT_EXTRACTABLE, 
                PreCheckFailureReason.valueOf("CONTENT_NOT_EXTRACTABLE"));
    }

    @Test
    void testToStringMethod() {
        // Test that toString returns the name (default behavior)
        assertEquals("NO_USABLE_TEXT", PreCheckFailureReason.NO_USABLE_TEXT.toString());
        assertEquals("PAGE_LIMIT_EXCEEDED", PreCheckFailureReason.PAGE_LIMIT_EXCEEDED.toString());
        assertEquals("CONTENT_NOT_EXTRACTABLE", PreCheckFailureReason.CONTENT_NOT_EXTRACTABLE.toString());
    }

    @Test
    void testDescriptionsAreDistinct() {
        // Ensure all descriptions are unique and meaningful
        String noUsableTextDesc = PreCheckFailureReason.NO_USABLE_TEXT.getDescription();
        String pageLimitExceededDesc = PreCheckFailureReason.PAGE_LIMIT_EXCEEDED.getDescription();
        String contentNotExtractableDesc = PreCheckFailureReason.CONTENT_NOT_EXTRACTABLE.getDescription();
        
        assertNotEquals(noUsableTextDesc, pageLimitExceededDesc);
        assertNotEquals(noUsableTextDesc, contentNotExtractableDesc);
        assertNotEquals(pageLimitExceededDesc, contentNotExtractableDesc);
        
        // Verify descriptions contain meaningful content
        assertTrue(noUsableTextDesc.contains("usable") && noUsableTextDesc.contains("text"));
        assertTrue(pageLimitExceededDesc.contains("page") && pageLimitExceededDesc.contains("limit"));
        assertTrue(contentNotExtractableDesc.contains("PDF") && contentNotExtractableDesc.contains("extractable"));
    }

    @Test
    void testEnumConstantOrderIsStable() {
        // Verify the order of enum constants is as expected
        PreCheckFailureReason[] values = PreCheckFailureReason.values();
        assertEquals(PreCheckFailureReason.NO_USABLE_TEXT, values[0]);
        assertEquals(PreCheckFailureReason.PAGE_LIMIT_EXCEEDED, values[1]);
        assertEquals(PreCheckFailureReason.CONTENT_NOT_EXTRACTABLE, values[2]);
    }

    @Test
    void testDescriptionsAreNotNullAndNotEmpty() {
        // Verify all descriptions are not null or empty
        for (PreCheckFailureReason reason : PreCheckFailureReason.values()) {
            String description = reason.getDescription();
            assertNotNull(description, "Description should not be null for " + reason.name());
            assertFalse(description.isEmpty(), "Description should not be empty for " + reason.name());
            assertTrue(description.length() > 10, "Description should be meaningful for " + reason.name());
        }
    }

    @Test
    void testEachEnumValueHasUniqueDescription() {
        // Verify each enum value has a unique description
        PreCheckFailureReason[] values = PreCheckFailureReason.values();
        for (int i = 0; i < values.length; i++) {
            for (int j = i + 1; j < values.length; j++) {
                assertNotEquals(values[i].getDescription(), values[j].getDescription(),
                        "Descriptions should be unique for " + values[i].name() + " and " + values[j].name());
            }
        }
    }

    @Test
    void testEnumConstantsAreImmutable() {
        // Verify that the same instance is returned for each enum constant
        assertSame(PreCheckFailureReason.NO_USABLE_TEXT, PreCheckFailureReason.valueOf("NO_USABLE_TEXT"));
        assertSame(PreCheckFailureReason.PAGE_LIMIT_EXCEEDED, PreCheckFailureReason.valueOf("PAGE_LIMIT_EXCEEDED"));
        assertSame(PreCheckFailureReason.CONTENT_NOT_EXTRACTABLE, PreCheckFailureReason.valueOf("CONTENT_NOT_EXTRACTABLE"));
    }
}