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

import de.accso.flexinale.backoffice_api_contract.api_contract.VorfuehrungRetriever;
import de.accso.flexinale.backoffice_api_contract.api_contract.model.FilmTO;
import de.accso.flexinale.backoffice_api_contract.api_contract.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.api_contract.TicketRetriever;
import de.accso.flexinale.ticketing_api_contract.api_contract.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 VorfuehrungRetriever vorfuehrungRetriever;

    private final VorfuehrungService vorfuehrungService;

    private final long minZeitZwischenVorfuehrungenInMinuten;

    private final List<TicketTO>  ticketsOfBesucher;

    public TicketBundle(final Identifiable.Id besucherId, final TicketRetriever ticketRetriever,
                        final VorfuehrungRetriever vorfuehrungRetriever,
                        final VorfuehrungService vorfuehrungService,
                        long minZeitZwischenVorfuehrungenInMinuten) {
        this.vorfuehrungRetriever = vorfuehrungRetriever;
        this.vorfuehrungService = vorfuehrungService;
        this.minZeitZwischenVorfuehrungenInMinuten = minZeitZwischenVorfuehrungenInMinuten;
        this.ticketsOfBesucher = ticketRetriever.ticketsByBesucherOrderByZeit(besucherId);
    }

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

        return ticketsOfBesucher.stream().anyMatch(ticket -> {
            VorfuehrungTO vorfuehrungOfTicket = vorfuehrungRetriever.vorfuehrung(ticket.vorfuehrungId());
            if (vorfuehrungOfTicket == null)
                return false;
            else {
                FilmTO filmOfVorfuehrungOfTicket = vorfuehrungOfTicket.film();
                if (filmOfVorfuehrungOfTicket == null) {
                    String message = "no Film for Vorfuehrung %s 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 hatSchonTicketFuer(final VorfuehrungTO vorfuehrung) {
        return ticketsOfBesucher.stream()
                .map(TicketTO::vorfuehrungId)
                .toList()
                .contains(vorfuehrung.id());
    }
}
