package com.lingniu.ingest.yutongmqttapp;

import com.lingniu.ingest.core.config.IngestCoreAutoConfiguration;
import com.lingniu.ingest.identity.MySqlVehicleIdentityService;
import com.lingniu.ingest.identity.config.VehicleIdentityAutoConfiguration;
import com.lingniu.ingest.inbound.mqtt.client.MqttEndpointManager;
import com.lingniu.ingest.inbound.mqtt.config.MqttInboundAutoConfiguration;
import com.lingniu.ingest.inbound.mqtt.handler.MqttRealtimeHandler;
import com.lingniu.ingest.inbound.mqtt.profile.MqttProfileRegistry;
import com.lingniu.ingest.sink.archive.ArchiveStore;
import com.lingniu.ingest.sink.archive.RawArchiveEventSink;
import com.lingniu.ingest.sink.archive.config.SinkArchiveAutoConfiguration;
import com.lingniu.ingest.sink.kafka.KafkaEnvelopeDeadLetterSink;
import com.lingniu.ingest.sink.kafka.KafkaEventSink;
import com.lingniu.ingest.sink.kafka.KafkaSinkAutoConfiguration;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;

@ExtendWith(OutputCaptureExtension.class)
class YutongMqttAppCompositionTest {

    private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
            .withConfiguration(AutoConfigurations.of(
                    IngestCoreAutoConfiguration.class,
                    VehicleIdentityAutoConfiguration.class,
                    KafkaSinkAutoConfiguration.class,
                    SinkArchiveAutoConfiguration.class,
                    MqttInboundAutoConfiguration.class))
            .withAllowBeanDefinitionOverriding(true)
            .withBean("kafkaProducer", KafkaProducer.class, YutongMqttAppCompositionTest::kafkaProducer)
            .withPropertyValues(
                    "lingniu.ingest.mqtt.enabled=true",
                    "lingniu.ingest.mqtt.auto-startup=false",
                    "lingniu.ingest.mqtt.endpoints[0].name=yutong-test",
                    "lingniu.ingest.mqtt.endpoints[0].uri=tcp://127.0.0.1:1883",
                    "lingniu.ingest.mqtt.endpoints[0].topic=/yutong/#",
                    "lingniu.ingest.mqtt.endpoints[0].profile=yutong",
                    "lingniu.ingest.identity.store=mysql",
                    "lingniu.ingest.identity.mysql.initialize-schema=false",
                    "lingniu.ingest.sink.kafka.enabled=true",
                    "lingniu.ingest.sink.kafka.bootstrap-servers=localhost:9092",
                    "lingniu.ingest.sink.kafka.consumer.enabled=false",
                    "lingniu.ingest.sink.archive.enabled=true",
                    "lingniu.ingest.sink.archive.path=target/test-archive-yutong",
                    "lingniu.ingest.event-history.enabled=false");

    @Test
    void createsMqttIngressAndKafkaSinksWithoutHistoryStorage(CapturedOutput output) {
        contextRunner.run(context -> {
            assertThat(context).hasSingleBean(MqttEndpointManager.class);
            assertThat(context).hasSingleBean(MqttProfileRegistry.class);
            assertThat(context).hasSingleBean(MqttRealtimeHandler.class);
            assertThat(context).hasSingleBean(MySqlVehicleIdentityService.class);
            assertThat(context).hasSingleBean(KafkaEventSink.class);
            assertThat(context).hasSingleBean(KafkaEnvelopeDeadLetterSink.class);
            assertThat(context).hasSingleBean(ArchiveStore.class);
            assertThat(context).hasSingleBean(RawArchiveEventSink.class);
            assertThat(context).doesNotHaveBean("mqttEndpointStartupRunner");
        });
        assertThat(output).doesNotContain("mqtt endpoint [yutong-test] initializing");
        assertThat(output).doesNotContain("mqtt endpoint [yutong-test] init failed");
    }

    @Test
    void createsStartupRunnerWhenAutoStartupIsEnabled() {
        contextRunner.withPropertyValues("lingniu.ingest.mqtt.auto-startup=true").run(context -> {
            assertThat(context).hasSingleBean(MqttEndpointManager.class);
            assertThat(context).hasBean("mqttEndpointStartupRunner");
        });
    }

    @SuppressWarnings("unchecked")
    private static KafkaProducer<String, byte[]> kafkaProducer() {
        return mock(KafkaProducer.class);
    }
}
