package de.accso.flexinale.shared_code_for_test;

import de.accso.flexinale.domain.model.*;
import de.accso.flexinale.infrastructure.persistence.KinoEntity;
import de.accso.flexinale.infrastructure.persistence.KinoSaalEntity;
import de.accso.flexinale.infrastructure.security.BenutzerEntity;
import de.accso.flexinale.shared_kernel.DoNotCheckInArchitectureTests;
import de.accso.flexinale.shared_kernel.Identifiable;
import de.accso.flexinale.shared_kernel.Versionable;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;

@DoNotCheckInArchitectureTests
public final class TestDataBuilder {

    public static Film createFilm() {
        return createFilm("testfilm", "testurl", 42);
    }

    public static Film createFilm(String titel, String imdbUrl, Integer dauerInMinuten) {
        return new Film(Identifiable.Id.of(), new Film.Titel(titel), new Film.ImdbUrl(imdbUrl),
                new Film.DauerInMinuten(dauerInMinuten));
    }

    public static Kino createKinoWithKinosaele() {
        return createKinoWithKinosaele(120, 111, 112);
    }

    public static Kino createKinoWithKinosaele(int... anzahlPlaetze) {
        Kino kino = new Kino(Identifiable.Id.of(), new Kino.Name("Helion"), new Kino.Adresse("Kinostrasse 1"),
                new Kino.EmailAdresse("contact.helion@fl.ex"), new HashSet<>());

        Set<KinoSaal> saele = new HashSet<>();
        int counter = 1;
        for (int anzahl: anzahlPlaetze) {
            saele.add(new KinoSaal(Identifiable.Id.of(), new KinoSaal.Name("saal " + counter),
                    new KinoSaal.AnzahlPlaetze(anzahl), kino));
        }
        kino.addSaele(saele);

        return kino;
    }

    public static KinoEntity createKinoEntityWithKinosaele() {
        return createKinoEntityWithKinosaele(120, 111, 112);
    }

    public static KinoEntity createKinoEntityWithKinosaele(int... anzahlPlaetze) {
        KinoEntity kino = new KinoEntity(Identifiable.Id.of().id(), Versionable.unknownVersion().version(), "Helion", "Kinostrasse 1",
                "contact.helion@fl.ex");

        Set<KinoSaalEntity> saele = new HashSet<>();
        int counter = 1;
        for (int anzahl: anzahlPlaetze) {
            saele.add(new KinoSaalEntity(Identifiable.Id.of().id(), Versionable.unknownVersion().version(), "saal " + counter, anzahl, kino));
        }
        kino.kinoSaele = saele;

        return kino;
    }

    public static BenutzerEntity createBenutzerEntity() {
        String benutzerId = Identifiable.Id.of().id();
        return new BenutzerEntity(benutzerId,
                "testlogin" + benutzerId, // needs to be unique
                "test" + benutzerId + "@fl.ex",   // needs to be unique
                "testname", "testvorname");
    }

    public static Besucher createBesucher() {
        Identifiable.Id benutzerId = Identifiable.Id.of();
        return new Besucher(benutzerId,
                new Besucher.Login("testlogin" + benutzerId), // needs to be unique
                new Besucher.EmailAdresse("test" + benutzerId + "@fl.ex"),   // needs to be unique
                new Besucher.Name("testname"), new Besucher.Vorname("testvorname"));
    }

    public static Vorfuehrung createVorfuehrung(LocalDateTime zeit, Film film, KinoSaal kinoSaal) {
        return createVorfuehrung(zeit, film, kinoSaal, 33); // one third
    }

    public static Vorfuehrung createVorfuehrung(LocalDateTime zeit, Film film, KinoSaal kinoSaal, int quoteOnline) {
        return new Vorfuehrung(Identifiable.Id.of(), new Vorfuehrung.Zeit(zeit), film, kinoSaal, quoteOnline);
    }

    public static Vorfuehrung createVorfuehrung(LocalDateTime zeit, Film film, KinoSaal kinoSaal, Kontingent kontingent) {
        return new Vorfuehrung(Identifiable.Id.of(), new Vorfuehrung.Zeit(zeit), film, kinoSaal, kontingent);
    }

    public static Ticket createTicket(Film film, Vorfuehrung vorfuehrung, Besucher besucher) {
        return createTicket(film, vorfuehrung, besucher, Ticket.VerkaufsKanal.ONLINE);
    }

    public static Ticket createTicket(Film film, Vorfuehrung vorfuehrung, Besucher besucher, Ticket.VerkaufsKanal kanal) {
        return new Ticket(Identifiable.Id.of(), film, vorfuehrung, besucher, kanal);
    }

    public static Kontingent createKontingent(int gesamtKapazitaetVerkauf, int quoteOnline) {
        return new Kontingent(Identifiable.Id.of(), gesamtKapazitaetVerkauf, quoteOnline);
    }

    public static Kontingent createKontingent(int restKontingentOnline, int restKontingentZentral,
                                              int restKontingentKinokasse) {
        return new Kontingent(Identifiable.Id.of(),
                new Kontingent.RestKontingent(restKontingentOnline),
                new Kontingent.RestKontingent(restKontingentZentral),
                new Kontingent.RestKontingent(restKontingentKinokasse));
    }
}
