package de.accso.flexinale.ticketing.infrastructure.persistence;

import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.domain.dao.FilmDao;
import de.accso.flexinale.backoffice.domain.dao.KinoDao;
import de.accso.flexinale.backoffice.domain.dao.VorfuehrungDao;
import de.accso.flexinale.backoffice.domain.model.Film;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.backoffice.domain.model.Vorfuehrung;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import de.accso.flexinale.security.infrastructure.persistence.BenutzerEntity;
import de.accso.flexinale.common.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.shared_code_for_test.TestDataBuilder;
import de.accso.flexinale.ticketing.domain.dao.TicketDao;
import de.accso.flexinale.ticketing.domain.model.Ticket;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

import static de.accso.flexinale.shared_code_for_test.TestDataBuilder.*;
import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ActiveProfiles("test-integrated")
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
public class TicketPersistenceTest {
    @Autowired
    private TicketDao ticketDao;

    @Autowired
    private VorfuehrungDao vorfuehrungDao;

    @Autowired
    private KinoDao kinoDao;

    @Autowired
    private FilmDao filmDao;

    @Test
    void saveAndDeleteTicket() {
        // arrange
        BenutzerEntity benutzer = createBenutzerEntity();

        Film film = createFilm();
        Kino kino = TestDataBuilder.createKinoWithKinosaele(100);
        KinoSaal kinoSaal = kino.kinoSaele.iterator().next();

        Vorfuehrung vorfuehrung = createVorfuehrung(LocalDateTime.now(), film, kinoSaal);
        Ticket ticket = createTicket(film, vorfuehrung, benutzer);

        // act
        ticketDao.save(ticket);

        // assert
        Optional<Ticket> optionalSearchedTicket = ticketDao.findById(ticket.id());
        assertThat(optionalSearchedTicket.isPresent()).isTrue();
        Ticket searchedTicket = optionalSearchedTicket.get();
        assertThat(searchedTicket.equalsByContent(ticket)).isTrue();

        // cleanup
        ticketDao.deleteById(ticket.id());
        // assert
        assertThat(ticketDao.findById(ticket.id())).isEmpty();
    }

    @Test
    void saveTicketAndFindByBenutzerOrderByZeitAndDelete() {
        // arrange
        LocalDateTime now = LocalDateTime.now();
        BenutzerEntity benutzer = createBenutzerEntity();

        Film film = createFilm();
        filmDao.save(film);

        Kino kino = createKinoWithKinosaele();
        kinoDao.save(kino);
        KinoSaal kinoSaal = kino.kinoSaele.iterator().next();

        Vorfuehrung vorfuehrung1 = createVorfuehrung(now, film, kinoSaal);
        Vorfuehrung vorfuehrung2 = createVorfuehrung(now.plusDays(1), film, kinoSaal);
        vorfuehrungDao.save(vorfuehrung1);
        vorfuehrungDao.save(vorfuehrung2);

        Ticket ticket1 = createTicket(film, vorfuehrung1, benutzer);
        Ticket ticket2 = createTicket(film, vorfuehrung2, benutzer);

        // act
        ticketDao.save(ticket1);
        ticketDao.save(ticket2);

        List<Ticket> tickets = ticketDao.findByBesucher(Identifiable.Id.of(benutzer.id));
        assertThat(tickets).hasSize(2);
    }
}
