package de.accso.flexinale.api_in.rest;

import de.accso.flexinale.application.services.KinoUploadService;
import de.accso.flexinale.application.services.KinoSaalUploadService;
import de.accso.flexinale.domain.model.Kino;
import de.accso.flexinale.domain.model.KinoSaal;
import de.accso.flexinale.application.services.KinoService;
import de.accso.flexinale.shared_kernel.Identifiable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedInputStream;
import java.util.Collection;
import java.util.List;
import java.util.Map;

@RestController
public class KinoKinoSaalRestController extends AbstractExcelRestController {

    @Autowired
    private KinoService kinoService;

    @Autowired
    private KinoUploadService kinoUploadService;

    @Autowired
    private KinoSaalUploadService kinoSaalUploadService;

    @GetMapping(value = "/rest/kinos", produces = "application/json")
    @PreAuthorize("hasRole('ROLE_BESUCHER')")
    public List<Kino> kinos() {
        return kinoService.kinos();
    }

    @GetMapping(value = "/rest/kino/{id}", produces = "application/json")
    @PreAuthorize("hasRole('ROLE_BESUCHER')")
    public Kino kino(@PathVariable final String id) {
        Identifiable.Id kinoId = Identifiable.Id.of(id);
        Kino kino = kinoService.kino(kinoId);
        if (kino == null) {
            throw new RestResourceNotFoundException("no Kino %s found.".formatted(id));
        }

        return kino;
    }

    @PostMapping("/rest/kinos")
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public ResponseEntity<RestResponseMessage> uploadKinosKinoSaele(@RequestParam("file") final MultipartFile file) {
        try(BufferedInputStream stream = new BufferedInputStream(file.getInputStream())) {

            // load KinoSaele first
            Collection<KinoSaal> alleKinoSaele =
                    kinoSaalUploadService.loadDataFromExcelSheet(stream);
            Map<Identifiable.Id, Collection<KinoSaal>> alleKinosUndIhreSaele =
                    kinoSaalUploadService.mapKinoSaeleToKino(alleKinoSaele);

            // .. then persist them as part of a Kino
            RestUploadResult restUploadResult;
            try {
                kinoUploadService.beforeLoad(alleKinosUndIhreSaele); // fix state of Kino-KinoSaal in map
                restUploadResult = uploadViaRestCall(kinoUploadService, file);
            }
            finally {
                kinoUploadService.afterLoad(); // clear map
            }

            return ResponseEntity.status(restUploadResult.status())
                    .body(new RestResponseMessage(restUploadResult.message()));
        }
        catch (Exception ex) {
            String message = "Could not upload the Excel file: %s: %s".formatted(file.getOriginalFilename(), ex.getMessage());
            throw new RestBadRequestException(message, ex);
        }
    }
}
