package com.lingniu.ingest.vehiclestat.config;

import com.lingniu.ingest.api.consumer.EnvelopeConsumerProcessor;
import com.lingniu.ingest.api.consumer.EnvelopeDeadLetterSink;
import com.lingniu.ingest.vehiclestat.JdbcVehicleStatMetricRepository;
import com.lingniu.ingest.vehiclestat.VehicleStatController;
import com.lingniu.ingest.vehiclestat.VehicleStatEnvelopeIngestor;
import com.lingniu.ingest.vehiclestat.VehicleStatRepository;
import com.lingniu.ingest.vehiclestat.jt808.Jt808LocationPointExtractor;
import com.lingniu.ingest.vehiclestat.jt808.Jt808MileageStreamProcessor;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
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 org.springframework.jdbc.core.JdbcTemplate;

import java.time.ZoneId;

@AutoConfiguration(after = {
        DataSourceAutoConfiguration.class,
        JdbcTemplateAutoConfiguration.class
})
@EnableConfigurationProperties(VehicleStatProperties.class)
@ConditionalOnProperty(prefix = "lingniu.ingest.vehicle-stat", name = "enabled", havingValue = "true")
public class VehicleStatAutoConfiguration {

    @Bean
    @ConditionalOnProperty(prefix = "lingniu.ingest.vehicle-stat.jt808", name = "state-store")
    public Object rejectedLegacyJt808MileageStateStore() {
        throw new IllegalStateException(
                "vehicle-stat.jt808.state-store has been removed; JT808 daily mileage uses vehicle_stat_metric only");
    }

    @Bean
    @ConditionalOnBean(JdbcTemplate.class)
    @ConditionalOnMissingBean
    public VehicleStatRepository jdbcVehicleStatMetricRepository(JdbcTemplate jdbcTemplate) {
        return new JdbcVehicleStatMetricRepository(jdbcTemplate);
    }

    @Bean
    @ConditionalOnProperty(prefix = "lingniu.ingest.vehicle-stat.jt808", name = "enabled", havingValue = "true")
    @ConditionalOnMissingBean
    public Jt808LocationPointExtractor jt808LocationPointExtractor() {
        return new Jt808LocationPointExtractor();
    }

    @Bean
    @ConditionalOnBean({Jt808LocationPointExtractor.class, VehicleStatRepository.class})
    @ConditionalOnMissingBean
    public Jt808MileageStreamProcessor jt808MileageStreamProcessor(Jt808LocationPointExtractor extractor,
                                                                    VehicleStatRepository repository,
                                                                    VehicleStatProperties props) {
        return new Jt808MileageStreamProcessor(extractor, repository, ZoneId.of(props.getZoneId()));
    }

    @Bean
    @ConditionalOnBean(Jt808MileageStreamProcessor.class)
    @ConditionalOnMissingBean
    public VehicleStatEnvelopeIngestor vehicleStatEnvelopeIngestor(
            Jt808MileageStreamProcessor jt808MileageProcessor) {
        return new VehicleStatEnvelopeIngestor(jt808MileageProcessor);
    }

    @Bean
    @ConditionalOnBean(VehicleStatRepository.class)
    @ConditionalOnMissingBean
    public VehicleStatController vehicleStatController(VehicleStatRepository repository) {
        return new VehicleStatController(repository);
    }

    @Bean
    @ConditionalOnBean({VehicleStatEnvelopeIngestor.class, EnvelopeDeadLetterSink.class})
    @ConditionalOnMissingBean(name = "vehicleStatEnvelopeConsumerProcessor")
    public EnvelopeConsumerProcessor vehicleStatEnvelopeConsumerProcessor(VehicleStatEnvelopeIngestor ingestor,
                                                                         EnvelopeDeadLetterSink deadLetterSink) {
        // Bean 名必须和 Kafka 默认 binding 对齐，KafkaEnvelopeConsumerFactory 才能自动创建 worker。
        return new EnvelopeConsumerProcessor("vehicle-stat", ingestor, deadLetterSink);
    }
}
