package de.accso.flexinale.domain.services;

import de.accso.flexinale.domain.dao.KontingentDao;
import de.accso.flexinale.domain.dao.TicketDao;
import de.accso.flexinale.domain.dao.VorfuehrungDao;
import de.accso.flexinale.domain.model.Besucher;
import de.accso.flexinale.domain.model.Ticket;
import de.accso.flexinale.domain.model.Vorfuehrung;
import de.accso.flexinale.shared_kernel.Identifiable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

public class TicketService {

    private static final Logger LOGGER = LoggerFactory.getLogger(TicketService.class);

    private final TicketDao ticketDao;

    private final VorfuehrungDao vorfuehrungDao;

    private final KontingentDao kontingentDao;

    public TicketService(final TicketDao ticketDao, final VorfuehrungDao vorfuehrungDao,
                         final KontingentDao kontingentDao) {
        this.ticketDao = ticketDao;
        this.vorfuehrungDao = vorfuehrungDao;
        this.kontingentDao = kontingentDao;
    }

    public void loeseGutscheineOnlineFuerVorfuehrungEin(final Identifiable.Id vorfuehrungId, final Besucher besucher, final int anzahlGutscheine) {
        loeseGutscheineFuerVorfuehrungEin(vorfuehrungId, besucher, anzahlGutscheine, Ticket.VerkaufsKanal.ONLINE);
    }

    @SuppressWarnings("SameParameterValue")
    private void loeseGutscheineFuerVorfuehrungEin(final Identifiable.Id vorfuehrungId, final Besucher besucher,
                                                   final int anzahlGutscheine,
                                                   final Ticket.VerkaufsKanal verkaufsKanal) {
        Vorfuehrung vorfuehrung = vorfuehrungDao.findById(vorfuehrungId).get(); //TODO check isPresent() first!
        vorfuehrung.verkaufeTickets(verkaufsKanal, anzahlGutscheine);

        for (int i = 0; i < anzahlGutscheine; i++) {
            Ticket ticket = new Ticket(Identifiable.Id.of(), vorfuehrung.film, vorfuehrung, besucher, verkaufsKanal);
            ticketDao.save(ticket);
        }

        // save reduction of the Kontingent reduction
        kontingentDao.save(vorfuehrung.getKontingent());

        LOGGER.info("%d ticket(s) bought for Vorfuehrung %s, Besucher %s, using Verkaufskanal %s"
                .formatted(anzahlGutscheine, vorfuehrung.id, besucher.login, verkaufsKanal));
    }

    public int gesamtZahlDerTicketsFuer(final Besucher eingeloggterBesucher) {
        return ticketDao.gesamtZahlDerTicketsFuer(eingeloggterBesucher);
    }

    public List<Ticket> findByBesucherOrderByZeit(final Besucher eingeloggterBesucher) {
        return ticketDao.findByBesucherOrderByZeit(eingeloggterBesucher);
    }
}
