package de.accso.flexinale.web;

import de.accso.flexinale.application.KontingentBereitsAusgeschoepftException;
import de.accso.flexinale.application.TicketService;
import de.accso.flexinale.application.VorfuehrungService;
import de.accso.flexinale.data.model.*;
import de.accso.flexinale.security.BenutzerDetailsService;
import jakarta.transaction.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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
@Transactional
public class TicketWebController {

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

    @Autowired
    private TicketService ticketService;

    @Autowired
    private VorfuehrungService vorfuehrungService;

    @Autowired
    private BenutzerDetailsService benutzerService;

    @GetMapping(value="/tickets")
    @PreAuthorize("hasRole('ROLE_BESUCHER')")
    public String listTickets(final Model model) {
        Benutzer loggedInBenutzer = benutzerService.getLoggedInBenutzer();

        List<Ticket> allTickets = ticketService.findByBesucherOrderByZeit(loggedInBenutzer);
        List<List<VorfuehrungMitAnzahlTicketsTO>> ticketsByDay = TicketSorter.sortAndMapTicketsPerDay(allTickets);

        model.addAttribute("ticketsByDay", ticketsByDay);

        int totalNumberOfTickets = ticketService.gesamtZahlDerTicketsFuer(loggedInBenutzer);
        model.addAttribute("totalNumberOfTickets", totalNumberOfTickets);

        return ("tickets");
    }

    @PostMapping("/vorfuehrung/loeseGutscheineOnlineEin")
    @PreAuthorize("hasRole('ROLE_BESUCHER')")
    public String loeseGutscheineOnlineEin(
                       @RequestParam("vorfuehrungId") final String vorfuehrungId,
                       @RequestParam("anzahl")        final int anzahl,
                       final RedirectAttributes redirAttrs) {
        Benutzer loggedInBenutzer = benutzerService.getLoggedInBenutzer();

        try {
            ticketService.loeseGutscheineOnlineFuerVorfuehrungEin(vorfuehrungId, loggedInBenutzer, anzahl);
        }
        catch (KontingentBereitsAusgeschoepftException kbaEx) {
            String message = "Kontingent exceeded: no %d tickets for Vorfuehrung %s and Besucher %s available"
                    .formatted(anzahl, vorfuehrungId, loggedInBenutzer.login);
            LOGGER.info(message);

            Vorfuehrung vorfuehrung = vorfuehrungService.vorfuehrung(vorfuehrungId);
            String filmId = vorfuehrung.film.id;

            redirAttrs.addFlashAttribute("error", "Keine %d Tickets mehr vorhanden".formatted(anzahl));
            return "redirect:/film/" + filmId;
        }
        redirAttrs.addFlashAttribute("success", "%d Ticket(s) erfolgreich gekauft".formatted(anzahl));
        return "redirect:/tickets";
    }
}

// class used to "flatten" Vorfuehrung and number of Tickets for Vorfuehrung for Clients
record VorfuehrungMitAnzahlTicketsTO(LocalDateTime zeit, Film film, KinoSaal kinoSaal, int anzahlTickets) { }