package de.accso.flexinale.besucherportal.api_in.event;

import de.accso.flexinale.FlexinaleDistributedApplicationTestIntegrated;
import de.accso.flexinale.backoffice.api_contract.event.model.VorfuehrungTO;
import de.accso.flexinale.backoffice.api_out.event.VorfuehrungPublisher;
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.DoNotCheckInArchitectureTests;
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.Collection;
import java.util.Iterator;
import java.util.List;

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

@SpringBootTest(classes = {FlexinaleDistributedApplicationTestIntegrated.class})
@ActiveProfiles("test-integrated")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@ExtendWith(SpringExtension.class)
@DoNotCheckInArchitectureTests
public class VorfuehrungSubscriberTest {

    @Autowired
    VorfuehrungSubscriber vorfuehrungSubscriber;

    @Autowired
    VorfuehrungPublisher vorfuehrungPublisher;

    @Test
    void testPublishAndSubscribeOfVorfuehrungen() {
        // arrange
        Film film1 = createFilm();
        Film film2 = createFilm();

        Kino kino = createKinoWithKinosaele();
        Iterator<KinoSaal> kinoSaalIterator = kino.kinoSaele.iterator();

        KinoSaal kinosaal1 = kinoSaalIterator.next();
        KinoSaal kinosaal2 = kinoSaalIterator.next();

        Vorfuehrung vorfuehrung1 = createVorfuehrung(LocalDateTime.now(), film1, kinosaal1);
        Vorfuehrung vorfuehrung2 = createVorfuehrung(LocalDateTime.now(), film2, kinosaal2);

        Collection<Vorfuehrung> newVorfuehrungen = List.of(vorfuehrung1, vorfuehrung2);
        vorfuehrungPublisher.publishNewVorfuehrungen(newVorfuehrungen);

        // act
        VorfuehrungTO vorfuehrungTO1 = vorfuehrungSubscriber.getCache().vorfuehrung(vorfuehrung1.id());
        VorfuehrungTO vorfuehrungTO2 = vorfuehrungSubscriber.getCache().vorfuehrung(vorfuehrung2.id());

        // assert
        assertThat(vorfuehrungTO1).isNotNull();
        assertThat(vorfuehrungTO1.id()).isEqualTo(vorfuehrung1.id());
        assertThat(vorfuehrungTO1.kinoSaal().id()).isEqualTo(vorfuehrung1.kinoSaal.id());

        assertThat(vorfuehrungTO2).isNotNull();
        assertThat(vorfuehrungTO2.id()).isEqualTo(vorfuehrung2.id());
        assertThat(vorfuehrungTO2.kinoSaal().id()).isEqualTo(vorfuehrung2.kinoSaal.id());

        // act
        Collection<Vorfuehrung> sameVorfuehrungAgain = List.of(vorfuehrung2);
        vorfuehrungPublisher.publishNewVorfuehrungen(sameVorfuehrungAgain);

        // act
        List<VorfuehrungTO> vorfuehrungTOSbyFilmId = vorfuehrungSubscriber.getCache().vorfuehrungenByFilmId(film2.id());

        // assert
        assertThat(vorfuehrungTOSbyFilmId.size()).isEqualTo(1);
        VorfuehrungTO vorfuehrungTOByFilmId = vorfuehrungTOSbyFilmId.getFirst();
        assertThat(vorfuehrungTOByFilmId.id()).isEqualTo(vorfuehrung2.id());
    }
}
