package com.lingniu.ingest.sink.kafka;

import com.lingniu.ingest.api.consumer.EnvelopeConsumerProcessor;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

import java.time.Duration;
import java.util.List;
import java.util.Map;

@AutoConfiguration(after = KafkaSinkAutoConfiguration.class)
@AutoConfigureAfter(name = {
        "com.lingniu.ingest.eventhistory.config.EventHistoryAutoConfiguration",
        "com.lingniu.ingest.vehiclestate.config.VehicleStateAutoConfiguration",
        "com.lingniu.ingest.vehiclestat.config.VehicleStatAutoConfiguration"
})
@EnableConfigurationProperties(KafkaSinkProperties.class)
@ConditionalOnProperty(prefix = "lingniu.ingest.sink.kafka", name = "enabled", havingValue = "true", matchIfMissing = true)
public class KafkaSinkConsumerAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public KafkaEnvelopeConsumerFactory kafkaEnvelopeConsumerFactory() {
        return new KafkaEnvelopeConsumerFactory();
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "lingniu.ingest.sink.kafka.consumer", name = "enabled", havingValue = "true")
    public KafkaEnvelopeConsumerRunner kafkaEnvelopeConsumerRunner(ListableBeanFactory beanFactory,
                                                                   KafkaEnvelopeConsumerFactory consumerFactory,
                                                                   KafkaSinkProperties props) {
        return new KafkaEnvelopeConsumerRunner(
                () -> createWorkers(beanFactory, consumerFactory, props),
                Duration.ofMillis(props.getConsumer().getPollTimeoutMillis()),
                Duration.ofMillis(props.getConsumer().getLoopBackoffMillis()),
                props.getConsumer().isAutoStartup());
    }

    private List<KafkaEnvelopeConsumerWorker> createWorkers(ListableBeanFactory beanFactory,
                                                            KafkaEnvelopeConsumerFactory consumerFactory,
                                                            KafkaSinkProperties props) {
        Map<String, EnvelopeConsumerProcessor> processors = beanFactory.getBeansOfType(EnvelopeConsumerProcessor.class);
        return consumerFactory.createWorkers(processors, props);
    }
}
