package com.storycove.entity;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.Set;

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

@DisplayName("Tag Entity Tests")
class TagTest {

    private Validator validator;
    private Tag tag;

    @BeforeEach
    void setUp() {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
        tag = new Tag("sci-fi");
    }

    @Test
    @DisplayName("Should create tag with valid name")
    void shouldCreateTagWithValidName() {
        assertEquals("sci-fi", tag.getName());
        assertNotNull(tag.getStories());
        assertTrue(tag.getStories().isEmpty());
    }


    @Test
    @DisplayName("Should fail validation when name is blank")
    void shouldFailValidationWhenNameIsBlank() {
        tag.setName("");
        Set<ConstraintViolation<Tag>> violations = validator.validate(tag);
        assertEquals(1, violations.size());
        assertEquals("Tag name is required", violations.iterator().next().getMessage());
    }

    @Test
    @DisplayName("Should fail validation when name is null")
    void shouldFailValidationWhenNameIsNull() {
        tag.setName(null);
        Set<ConstraintViolation<Tag>> violations = validator.validate(tag);
        assertEquals(1, violations.size());
        assertEquals("Tag name is required", violations.iterator().next().getMessage());
    }

    @Test
    @DisplayName("Should fail validation when name exceeds 100 characters")
    void shouldFailValidationWhenNameTooLong() {
        String longName = "a".repeat(101);
        tag.setName(longName);
        Set<ConstraintViolation<Tag>> violations = validator.validate(tag);
        assertEquals(1, violations.size());
        assertEquals("Tag name must not exceed 100 characters", violations.iterator().next().getMessage());
    }




    @Test
    @DisplayName("Should handle equals and hashCode correctly")
    void shouldHandleEqualsAndHashCodeCorrectly() {
        Tag tag1 = new Tag("action");
        Tag tag2 = new Tag("romance");
        Tag tag3 = new Tag("action");

        assertNotEquals(tag1, tag2);
        assertNotEquals(tag1, tag3); // Different because IDs are null
        assertEquals(tag1, tag1);
        assertNotEquals(tag1, null);
        assertNotEquals(tag1, "not a tag");

        assertEquals(tag1.hashCode(), tag1.hashCode());
    }

    @Test
    @DisplayName("Should have proper toString representation")
    void shouldHaveProperToStringRepresentation() {
        String toString = tag.toString();
        assertTrue(toString.contains("sci-fi"));
        assertTrue(toString.contains("Tag{"));
    }

    @Test
    @DisplayName("Should pass validation with maximum allowed lengths")
    void shouldPassValidationWithMaxAllowedLengths() {
        String maxName = "a".repeat(100);
        
        tag.setName(maxName);
        
        Set<ConstraintViolation<Tag>> violations = validator.validate(tag);
        assertTrue(violations.isEmpty());
    }
}