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

import de.accso.flexinale.backoffice.api_contract.event.model.FilmTO;
import de.accso.flexinale.backoffice.api_contract.event.model.KinoSaalTO;
import de.accso.flexinale.backoffice.api_contract.event.model.KinoTO;
import de.accso.flexinale.besucherportal.application.services.FKKsVTInMemoryCache;
import de.accso.flexinale.besucherportal.application.services.TicketService;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import de.accso.flexinale.common.shared_kernel.RawWrapper;
import de.accso.flexinale.security.api_contract.BesucherRetriever;
import de.accso.flexinale.ticketing.api_contract.event.model.TicketTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.time.LocalDateTime;
import java.util.List;

@Controller
@Profile({ "!testdata-backoffice & !testdata-ticketing" })
public class TicketWebController {

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

    @Autowired
    private TicketService ticketService;

    @Autowired
    private FKKsVTInMemoryCache cache;

    @Autowired
    private BesucherRetriever besucherRetriever;

    @GetMapping(value="/tickets")
    @PreAuthorize("hasRole('ROLE_BESUCHER')")
    public String listTickets(final Model model) {
        Identifiable.Id besucherId = besucherRetriever.getIdOfLoggedInBesucher();

        List<TicketTO> allTickets = cache.ticketsByBesucher(besucherId);

        List<List<VorfuehrungMitAnzahlTicketsTO>> ticketsByDay
                = TicketSorter.sortAndMapTicketsPerDay(allTickets, cache);
        model.addAttribute("ticketsByDay", ticketsByDay);

        int totalNumberOfTickets = cache.gesamtZahlDerTicketsFuer(besucherId);
        model.addAttribute("totalNumberOfTickets", totalNumberOfTickets);

        return ("tickets");
    }

    @PostMapping("/vorfuehrung/loeseGutscheineOnlineEin")
    @PreAuthorize("hasRole('ROLE_BESUCHER')")
    public String loeseGutscheineOnlineEin(
                         @RequestParam("vorfuehrungId") final String vId,
                         @RequestParam("filmId")        final String fId,
                         @RequestParam("anzahl")        final int anzahl,
                         RedirectAttributes redirAttrs) {
        Identifiable.Id vorfuehrungId = Identifiable.Id.of(vId);
        Identifiable.Id filmId = Identifiable.Id.of(fId);
        Identifiable.Id besucherId = besucherRetriever.getIdOfLoggedInBesucher();

        ticketService.loeseGutscheineOnlineFuerVorfuehrungEin(vorfuehrungId, filmId, besucherId, anzahl);

        redirAttrs.addFlashAttribute("success",
                "Kauf von %d Ticket(s) beauftragt".formatted(anzahl));
        return "redirect:/tickets";
    }
}

// class used to "flatten" Vorfuehrung and number of Tickets for Vorfuehrung for Clients
record VorfuehrungMitAnzahlTicketsTO(Zeit zeit, FilmTO film,
                                     KinoSaalTO kinoSaal, KinoTO kino,
                                     AnzahlTickets anzahlGueltigeTickets, AnzahlTickets anzahlUngueltigeTickets) {
    public record Zeit(LocalDateTime raw) implements RawWrapper<LocalDateTime> {
        public Zeit(LocalDateTime raw) {
            this.raw = raw.withNano(0); // precision is second
        }
    }

    public record AnzahlTickets(Integer raw) implements RawWrapper<Integer> {}
}
