package de.accso.flexinale.backoffice.infrastructure;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import de.accso.flexinale.backoffice.api_out.event.FilmPublisher;
import de.accso.flexinale.backoffice.api_out.event.KinoPublisher;
import de.accso.flexinale.backoffice.api_out.event.VorfuehrungPublisher;
import de.accso.flexinale.backoffice.application.services.FilmService;
import de.accso.flexinale.backoffice.application.services.KinoService;
import de.accso.flexinale.backoffice.application.services.VorfuehrungService;
import de.accso.flexinale.backoffice.application.services.FilmUploadService;
import de.accso.flexinale.backoffice.application.services.KinoUploadService;
import de.accso.flexinale.backoffice.application.services.KinoSaalUploadService;
import de.accso.flexinale.backoffice.application.services.VorfuehrungUploadService;
import de.accso.flexinale.backoffice.domain.dao.FilmDao;
import de.accso.flexinale.backoffice.domain.dao.KinoDao;
import de.accso.flexinale.backoffice.domain.dao.KinoSaalDao;
import de.accso.flexinale.backoffice.domain.dao.VorfuehrungDao;
import de.accso.flexinale.backoffice.infrastructure.persistence.*;
import de.accso.flexinale.common.api.eventbus.EventBusFactory;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@Profile({ "!testdata-besucherportal & !testdata-ticketing" })
@EnableJpaRepositories({"de.accso.flexinale.backoffice.infrastructure.persistence"})
@EnableTransactionManagement
@EntityScan(basePackages={"de.accso.flexinale.backoffice.infrastructure.persistence"})
public class FlexinaleBackofficeSpringFactory {

    @Bean
    public FilmService createApplicationFilmService(final de.accso.flexinale.backoffice.domain.services.FilmService filmService) {
        return new FilmService(filmService);
    }

    @Bean
    public de.accso.flexinale.backoffice.domain.services.FilmService createBackofficeFilmService(final FilmDao filmDao) {
        return new de.accso.flexinale.backoffice.domain.services.FilmService(filmDao);
    }

    @Bean
    public FilmUploadService createBackofficeFilmUploadService(final FilmDao filmDao) {
        return new FilmUploadService(filmDao);
    }

    @Bean
    public FilmDao createBackofficeFilmDao(final FilmJpaRepository filmJpaRepository) {
        return new FilmJpaRepositoryDelegate(filmJpaRepository);
    }

    @Bean
    public FilmPublisher createBackofficeFilmPublisher(final EventBusFactory eventBusFactory,
                                                       final FlexinaleBackofficeActuatorEndpointEventsPublished endpointEventsPublished) {
        return new FilmPublisher(eventBusFactory, endpointEventsPublished);
    }

    // ------------------------------------------------------------------------------------------------

    @Bean
    public KinoService createApplicationKinoService(final de.accso.flexinale.backoffice.domain.services.KinoService kinoService) {
        return new KinoService(kinoService);
    }

    @Bean
    public de.accso.flexinale.backoffice.domain.services.KinoService createBackofficeKinoService(final KinoDao KinoDao) {
        return new de.accso.flexinale.backoffice.domain.services.KinoService(KinoDao);
    }

    @Bean
    public KinoUploadService createBackofficeKinoUploadService(final KinoDao kinoDao) {
        return new KinoUploadService(kinoDao);
    }

    @Bean
    public KinoSaalUploadService createBackofficeKinoSaalUploadService(final KinoSaalDao kinoSaalDao) {
        return new KinoSaalUploadService(kinoSaalDao);
    }

    @Bean
    public KinoDao createBackofficeKinoDao(final KinoJpaRepository kinoJpaRepository) {
        return new KinoJpaRepositoryDelegate(kinoJpaRepository);
    }

    @Bean
    public KinoSaalDao createBackofficeKinoSaalDao(final KinoSaalJpaRepository kinoSaalJpaRepository) {
        return new KinoSaalJpaRepositoryDelegate(kinoSaalJpaRepository);
    }

    @Bean
    public KinoPublisher createBackofficeKinoPublisher(final EventBusFactory eventBusFactory,
                                                       final FlexinaleBackofficeActuatorEndpointEventsPublished endpointEventsPublished) {
        return new KinoPublisher(eventBusFactory, endpointEventsPublished);
    }

    // ------------------------------------------------------------------------------------------------

    @Bean
    public VorfuehrungService createApplicationVorfuehrungService(final de.accso.flexinale.backoffice.domain.services.VorfuehrungService vorfuehrungService) {
        return new VorfuehrungService(vorfuehrungService);
    }

    @Bean
    public de.accso.flexinale.backoffice.domain.services.VorfuehrungService createBackofficeVorfuehrungService(final VorfuehrungDao vorfuehrungDao) {
        return new de.accso.flexinale.backoffice.domain.services.VorfuehrungService(vorfuehrungDao);
    }

    @Bean
    public VorfuehrungUploadService createBackofficeVorfuehrungUploadService(final VorfuehrungDao vorfuehrungDao,
                                                                             final FilmDao filmDao,
                                                                             final KinoSaalDao kinoSaalDao) {
        return new VorfuehrungUploadService(vorfuehrungDao, filmDao, kinoSaalDao);
    }

    @Bean
    public VorfuehrungDao createBackofficeVorfuehrungDao(final VorfuehrungJpaRepository vorfuehrungJpaRepository) {
        return new VorfuehrungJpaRepositoryDelegate(vorfuehrungJpaRepository);
    }

    @Bean
    public VorfuehrungPublisher createBackofficeVorfuehrungPublisher(final EventBusFactory eventBusFactory,
                                                                     final FlexinaleBackofficeActuatorEndpointEventsPublished endpointEventsPublished) {
        return new VorfuehrungPublisher(eventBusFactory, endpointEventsPublished);
    }

    // ------------------------------------------------------------------------------------------------

    // Actuator Event serialization
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jsonBackofficeCustomizer() {
        return builder -> builder.visibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
    }
}
