package de.accso.flexinale.besucherportal.application.services;

import de.accso.flexinale.backoffice.api_contract.event.model.FilmTO;
import de.accso.flexinale.backoffice.api_contract.event.model.VorfuehrungTO;
import de.accso.flexinale.common.shared_kernel.FlexinaleIllegalStateException;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import de.accso.flexinale.ticketing.api_contract.event.model.TicketTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

import static de.accso.flexinale.common.shared_kernel.RawWrapper.getRawOrNull;

public class TicketBundle {
    private static final Logger LOGGER = LoggerFactory.getLogger(TicketBundle.class);

    private final FKKsVTInMemoryCache cache;

    private final VorfuehrungService vorfuehrungService;

    private final long minZeitZwischenVorfuehrungenInMinuten;

    private final List<TicketTO>  gueltigeTicketsOfBesucher;

    public TicketBundle(final Identifiable.Id besucherId, final FKKsVTInMemoryCache cache,
                        final VorfuehrungService vorfuehrungService,
                        final long minZeitZwischenVorfuehrungenInMinuten) {
        this.cache = cache;
        this.vorfuehrungService = vorfuehrungService;
        this.minZeitZwischenVorfuehrungenInMinuten = minZeitZwischenVorfuehrungenInMinuten;

        this.gueltigeTicketsOfBesucher = cache.gueltigeTicketsByBesucher(besucherId);
    }

    public boolean mindestensEinGueltigesTicketImTicketBundleUeberlapptMit(final VorfuehrungTO vorfuehrung) {
        FilmTO filmOfVorfuehrung = vorfuehrung.film();

        return gueltigeTicketsOfBesucher.stream().anyMatch(ticket -> {
            VorfuehrungTO vorfuehrungOfTicket = cache.vorfuehrung(ticket.vorfuehrungId());
            if (vorfuehrungOfTicket == null)
                return false;
            else {
                FilmTO filmOfVorfuehrungOfTicket = vorfuehrungOfTicket.film();
                if (filmOfVorfuehrungOfTicket == null) {
                    String message = "Film for Vorfuehrung %s could not be found".formatted(vorfuehrungOfTicket.id());
                    LOGGER.error(message);
                    throw new FlexinaleIllegalStateException(message);
                }

                return vorfuehrungService.vorfuehrungUeberlapptMit(vorfuehrung, vorfuehrungOfTicket,
                        getRawOrNull(filmOfVorfuehrung.dauerInMinuten()),
                        getRawOrNull(filmOfVorfuehrungOfTicket.dauerInMinuten()),
                        minZeitZwischenVorfuehrungenInMinuten);
            }
        });
    }

    public boolean hatSchonGueltigesTicketFuer(final VorfuehrungTO vorfuehrung) {
        return gueltigeTicketsOfBesucher.stream()
                .map(TicketTO::vorfuehrungId)
                .toList()
                .contains(vorfuehrung.id());
    }
}
