package org.raddatz.familienarchiv.timeline;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.junit.jupiter.api.Test;
import org.raddatz.familienarchiv.PostgresContainerConfig;
import org.raddatz.familienarchiv.document.Document;
import org.raddatz.familienarchiv.document.DocumentRepository;
import org.raddatz.familienarchiv.document.DocumentService;
import org.raddatz.familienarchiv.document.DocumentStatus;
import org.raddatz.familienarchiv.person.Person;
import org.raddatz.familienarchiv.person.PersonRepository;
import org.raddatz.familienarchiv.person.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.transaction.annotation.Transactional;
import software.amazon.awssdk.services.s3.S3Client;

import java.time.LocalDate;
import java.util.Set;
import java.util.UUID;

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

/**
 * Proves V77's FK {@code ON DELETE CASCADE} on the join tables: deleting a linked Person or
 * Document drops the join row and leaves the {@link TimelineEvent} intact (a person/document
 * delete must never 500 — V71-class regression guard). Needs the full Spring context for
 * {@link PersonService}/{@link DocumentService}, mirroring {@code PersonServiceIntegrationTest}.
 */
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
@ActiveProfiles("test")
@Import(PostgresContainerConfig.class)
@Transactional
class TimelineEventCascadeIntegrationTest {

    @MockitoBean S3Client s3Client;
    @Autowired TimelineEventRepository events;
    @Autowired PersonRepository personRepository;
    @Autowired PersonService personService;
    @Autowired DocumentRepository documentRepository;
    @Autowired DocumentService documentService;
    @Autowired JdbcTemplate jdbc;
    @PersistenceContext EntityManager em;

    private TimelineEvent.TimelineEventBuilder makeEvent() {
        return TimelineEvent.builder()
                .title("Hochzeit von Anna und Otto")
                .type(EventType.PERSONAL)
                .eventDate(LocalDate.of(1914, 7, 28))
                .createdBy(UUID.randomUUID())
                .updatedBy(UUID.randomUUID());
    }

    @Test
    void deleting_linked_person_keeps_event_and_drops_join_row() {
        Person anna = personRepository.save(Person.builder().firstName("Anna").lastName("Raddatz").build());
        TimelineEvent event = events.save(makeEvent().persons(Set.of(anna)).build());
        em.flush();
        em.clear();

        personService.deletePerson(anna.getId());
        em.flush();
        em.clear();

        assertThat(events.findById(event.getId())).isPresent();
        Integer joinRows = jdbc.queryForObject(
                "SELECT COUNT(*) FROM timeline_event_persons WHERE timeline_event_id = ?",
                Integer.class, event.getId());
        assertThat(joinRows).isZero();
    }

    @Test
    void deleting_linked_document_keeps_event_and_drops_join_row() {
        Document letter = documentRepository.save(Document.builder()
                .title("Brief").originalFilename("brief.pdf").status(DocumentStatus.UPLOADED).build());
        TimelineEvent event = events.save(makeEvent().documents(Set.of(letter)).build());
        em.flush();
        em.clear();

        documentService.deleteDocument(letter.getId(), UUID.randomUUID());
        em.flush();
        em.clear();

        assertThat(events.findById(event.getId())).isPresent();
        Integer joinRows = jdbc.queryForObject(
                "SELECT COUNT(*) FROM timeline_event_documents WHERE timeline_event_id = ?",
                Integer.class, event.getId());
        assertThat(joinRows).isZero();
    }
}
