package de.accso.flexinale.backoffice.application.services;

import de.accso.flexinale.backoffice.domain.dao.KinoDao;
import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.common.domain.dao.AbstractDao;
import de.accso.flexinale.common.application.services.AbstractExcelDataUploadService;
import de.accso.flexinale.common.shared_kernel.DeveloperMistakeException;
import de.accso.flexinale.common.shared_kernel.FlexinaleIllegalStateException;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import jakarta.transaction.Transactional;
import org.apache.poi.ss.usermodel.Row;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@Transactional
public class KinoUploadService extends AbstractExcelDataUploadService<Kino> {
    private static final Logger LOGGER = LoggerFactory.getLogger(KinoUploadService.class);

    private final KinoDao kinoDao;

    private final Map<Identifiable.Id, Collection<KinoSaal>> alleKinosUndIhreSaele = new HashMap<>();

    public KinoUploadService(KinoDao kinoDao) {
        this.kinoDao = kinoDao;
    }

    @Override
    public AbstractDao<Kino> getDao() {
        return kinoDao;
    }

    @Override
    public String getNameOfExcelDataType() {
        return Kino.class.getSimpleName();
    }

    @Override
    public void beforeLoad(Object... o) {
        if ((o.length != 1) && (!(o[0] instanceof Map))) {
            throw new DeveloperMistakeException("wrong type: expecting a " +
                    "Map<Identifiable.Id, Collection<KinoSaal>> of Kino and their KinoSaele");
        }

        @SuppressWarnings("unchecked")
        Map<Identifiable.Id, Collection<KinoSaal>> newKinoAndKinoSaele = (Map<Identifiable.Id, Collection<KinoSaal>>) o[0];
        this.alleKinosUndIhreSaele.putAll(newKinoAndKinoSaele);
    }

    @Override
    public void afterLoad(Object... o)  {
        alleKinosUndIhreSaele.clear();
    }

    @Override
    public Kino createDataFromExcelRow(final Row excelRow) {
        String kinoId = excelRow.getCell(0).getStringCellValue();

        Collection<KinoSaal> saeleImKino = alleKinosUndIhreSaele.get(Identifiable.Id.of(kinoId));
        if (saeleImKino == null || saeleImKino.isEmpty()) {
            throw new FlexinaleIllegalStateException("no Saele for Kino %s found".formatted(kinoId));
        }

        Kino kino = new Kino(
                Identifiable.Id.of(kinoId),
                new Kino.Name(excelRow.getCell(1).getStringCellValue()),
                new Kino.Adresse(excelRow.getCell(2).getStringCellValue()),
                new Kino.EmailAdresse(excelRow.getCell(3).getStringCellValue()),
                Set.copyOf(saeleImKino)
        );

        LOGGER.debug("New Kino created: " + kino);

        return kino;
    }
}
