package de.accso.flexinale.ticketing.infrastructure;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import de.accso.flexinale.common.application.Config;
import de.accso.flexinale.common.api.eventbus.EventBusFactory;
import de.accso.flexinale.ticketing.api_in.event.GutscheinEinloesenBeauftragtSubscriber;
import de.accso.flexinale.ticketing.api_out.event.OnlineKontingentChangedPublisher;
import de.accso.flexinale.ticketing.api_out.event.TicketPublisher;
import de.accso.flexinale.ticketing.api_in.event.VorfuehrungSubscriber;
import de.accso.flexinale.ticketing.application.services.OnlineKontingentChangedPublication;
import de.accso.flexinale.ticketing.application.services.TicketPublication;
import de.accso.flexinale.ticketing.application.services.TicketService;
import de.accso.flexinale.ticketing.domain.dao.KontingentDao;
import de.accso.flexinale.ticketing.domain.dao.TicketDao;
import de.accso.flexinale.ticketing.domain.services.KontingentService;
import de.accso.flexinale.ticketing.infrastructure.persistence.KontingentJpaRepository;
import de.accso.flexinale.ticketing.infrastructure.persistence.KontingentJpaRepositoryDelegate;
import de.accso.flexinale.ticketing.infrastructure.persistence.TicketJpaRepository;
import de.accso.flexinale.ticketing.infrastructure.persistence.TicketJpaRepositoryDelegate;
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-backoffice & !testdata-besucherportal" })
@EnableJpaRepositories({"de.accso.flexinale.ticketing.infrastructure.persistence"})
@EnableTransactionManagement
@EntityScan(basePackages={"de.accso.flexinale.ticketing.infrastructure.persistence"})
public class FlexinaleTicketingSpringFactory {

    @Bean
    public KontingentDao createTicketingKontingentDao(final KontingentJpaRepository kontingentJpaRepository) {
        return new KontingentJpaRepositoryDelegate(kontingentJpaRepository);
    }

    @Bean
    public TicketDao createTicketingTicketDao(final TicketJpaRepository ticketJpaRepository) {
        return new TicketJpaRepositoryDelegate(ticketJpaRepository);
    }

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

    @Bean
    public TicketService createTicketingTicketService(final TicketDao ticketDao,
                                                      final KontingentDao kontingentDao,
                                                      final OnlineKontingentChangedPublication onlineKontingentChangedPublisher,
                                                      final TicketPublication ticketPublisher,
                                                      final Config config) {
        return new TicketService(ticketDao,  kontingentDao, onlineKontingentChangedPublisher,
                ticketPublisher, config.getQuoteOnline());
    }

    @Bean
    public OnlineKontingentChangedPublication createTicketingOnlineKontingentChangedPublisher(
            final EventBusFactory eventBusFactory,
            final FlexinaleTicketingActuatorEndpointEventsPublished endpointEventsPublished) {
        return new OnlineKontingentChangedPublisher(eventBusFactory, endpointEventsPublished);
    }

    @Bean
    public KontingentService createTicketingKontingentService(final KontingentDao kontingentDao) {
        return new KontingentService(kontingentDao);
    }

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

    @Bean
    public GutscheinEinloesenBeauftragtSubscriber createTicketingGutscheinEinloesenBeauftragtSubscriber(
            final EventBusFactory eventBusFactory,
            final TicketService ticketService,
            final FlexinaleTicketingActuatorEndpointEventsConsumed endpointEventsConsumed) {
        return new GutscheinEinloesenBeauftragtSubscriber(eventBusFactory, ticketService, endpointEventsConsumed);
    }

    @Bean
    public TicketPublication createTicketingTicketPublisher(final EventBusFactory eventBusFactory,
                                                          final FlexinaleTicketingActuatorEndpointEventsPublished endpointEventsPublished) {
        return new TicketPublisher(eventBusFactory, endpointEventsPublished);
    }

    @Bean
    public VorfuehrungSubscriber createTicketingVorfuehrungSubscriber(final EventBusFactory eventBusFactory,
                                                                      final TicketService ticketService,
                                                                      final FlexinaleTicketingActuatorEndpointEventsConsumed endpointEventsConsumed) {
        return new VorfuehrungSubscriber(eventBusFactory, ticketService, endpointEventsConsumed);
    }

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

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