package com.codebyte.api.item;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import com.codebyte.api.item.domain.Item;
import com.codebyte.api.item.repository.ItemRepository;
import com.codebyte.api.support.AbstractPostgresIT;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.transaction.annotation.Transactional;

/**
 * Persistence-layer integration tests for {@link Item}: auditing, uniqueness, optimistic locking.
 */
@SpringBootTest
@Transactional
class ItemPersistenceIT extends AbstractPostgresIT {

    @Autowired private ItemRepository itemRepository;

    @Test
    void should_generate_id_and_audit_timestamps_when_item_saved() {
        Item saved = itemRepository.saveAndFlush(new Item("Widget", "a widget"));

        assertThat(saved.getId()).isNotNull();
        assertThat(saved.getCreatedAt()).isNotNull();
        assertThat(saved.getUpdatedAt()).isNotNull();
        assertThat(saved.getVersion()).isZero();
    }

    @Test
    void should_reject_duplicate_name_case_insensitively_when_saving() {
        itemRepository.saveAndFlush(new Item("Widget", "first"));

        assertThatThrownBy(() -> itemRepository.saveAndFlush(new Item("widget", "second")))
                .isInstanceOf(DataIntegrityViolationException.class);
    }

    @Test
    void should_increment_version_when_item_updated() {
        Item saved = itemRepository.saveAndFlush(new Item("Gadget", "v0"));
        assertThat(saved.getVersion()).isZero();

        saved.setDescription("v1");
        Item updated = itemRepository.saveAndFlush(saved);

        assertThat(updated.getVersion()).isEqualTo(1L);
    }

    @Test
    void should_find_item_by_name_ignoring_case() {
        itemRepository.saveAndFlush(new Item("Sprocket", "desc"));

        assertThat(itemRepository.findByNameIgnoreCase("SPROCKET")).isPresent();
        assertThat(itemRepository.existsByNameIgnoreCase("sprocket")).isTrue();
    }
}
