package com.lingniu.ingest.historyapp;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;

import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Properties;

import static org.assertj.core.api.Assertions.assertThat;

class VehicleHistoryAppDefaultsTest {

    @Test
    void applicationDefaultsKeepHistoryAsDecoderConsumerAndStorageRuntime() throws IOException {
        Properties properties = applicationProperties();

        assertThat(properties)
                .containsEntry("spring.application.name", "vehicle-history-app")
                .containsEntry(
                        "spring.config.import[0]",
                        "optional:nacos:${spring.application.name}.${NACOS_CONFIG_FILE_EXTENSION:yml}?group=${NACOS_GROUP:DEFAULT_GROUP}&refreshEnabled=${NACOS_REFRESH_ENABLED:true}")
                .containsEntry("spring.cloud.nacos.config.server-addr", "${NACOS_SERVER_ADDR:127.0.0.1:8848}")
                .containsEntry("lingniu.ingest.gb32960.enabled", true)
                .containsEntry("lingniu.ingest.gb32960.server.enabled", false)
                .containsEntry("lingniu.ingest.tdengine-history.enabled", "${TDENGINE_HISTORY_ENABLED:false}")
                .containsEntry("lingniu.ingest.tdengine-history.database", "${TDENGINE_HISTORY_DATABASE:vehicle_history}")
                .containsEntry(
                        "lingniu.ingest.tdengine-history.jdbc-url",
                        "${TDENGINE_JDBC_URL:jdbc:TAOS-RS://${TDENGINE_HOST:127.0.0.1}:${TDENGINE_PORT:6041}/${TDENGINE_HISTORY_DATABASE:vehicle_history}}")
                .containsEntry("lingniu.ingest.tdengine-history.username", "${TDENGINE_USERNAME:root}")
                .containsEntry("lingniu.ingest.tdengine-history.password", "${TDENGINE_PASSWORD:taosdata}")
                .containsEntry(
                        "lingniu.ingest.tdengine-history.driver-class-name",
                        "${TDENGINE_DRIVER_CLASS_NAME:com.taosdata.jdbc.rs.RestfulDriver}")
                .containsEntry("lingniu.ingest.tdengine-history.maximum-pool-size", "${TDENGINE_MAX_POOL_SIZE:16}")
                .containsEntry("lingniu.ingest.tdengine-history.minimum-idle", "${TDENGINE_MIN_IDLE:0}")
                .containsEntry("lingniu.ingest.event-history.enabled", true)
                .containsEntry("lingniu.ingest.sink.kafka.enabled", true)
                .containsEntry("lingniu.ingest.sink.kafka.consumer.enabled", "${KAFKA_CONSUMER_ENABLED:true}")
                .containsEntry("lingniu.ingest.sink.kafka.consumer.max-poll-records", "${KAFKA_CONSUMER_MAX_POLL_RECORDS:2000}")
                .containsEntry("lingniu.ingest.sink.kafka.consumer.concurrency", "${KAFKA_CONSUMER_CONCURRENCY:3}")
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.max-poll-interval-millis",
                        "${KAFKA_CONSUMER_MAX_POLL_INTERVAL_MILLIS:1800000}")
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.enabled",
                        true)
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.group-id",
                        "${KAFKA_GROUP_HISTORY_GB32960_EVENT:${KAFKA_GROUP_HISTORY:vehicle-history}-gb32960-event}")
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960EnvelopeConsumerProcessor.topics[0]",
                        "${KAFKA_TOPIC_GB32960_EVENT:vehicle.event.gb32960.v1}")
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryJt808EnvelopeConsumerProcessor.enabled",
                        true)
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryJt808EnvelopeConsumerProcessor.group-id",
                        "${KAFKA_GROUP_HISTORY_JT808_EVENT:${KAFKA_GROUP_HISTORY:vehicle-history}-jt808-event}")
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryJt808EnvelopeConsumerProcessor.topics[0]",
                        "${KAFKA_TOPIC_JT808_EVENT:vehicle.event.jt808.v1}")
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryYutongMqttEnvelopeConsumerProcessor.enabled",
                        true)
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryYutongMqttEnvelopeConsumerProcessor.group-id",
                        "${KAFKA_GROUP_HISTORY_YUTONG_MQTT_EVENT:${KAFKA_GROUP_HISTORY:vehicle-history}-yutong-mqtt-event}")
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryYutongMqttEnvelopeConsumerProcessor.topics[0]",
                        "${KAFKA_TOPIC_YUTONG_MQTT_EVENT:vehicle.event.mqtt-yutong.v1}")
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960RawEnvelopeConsumerProcessor.enabled",
                        true)
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960RawEnvelopeConsumerProcessor.group-id",
                        "${KAFKA_GROUP_HISTORY_GB32960_RAW:${KAFKA_GROUP_HISTORY:vehicle-history}-gb32960-raw}")
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryGb32960RawEnvelopeConsumerProcessor.topics[0]",
                        "${KAFKA_TOPIC_GB32960_RAW:vehicle.raw.gb32960.v1}")
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryJt808RawEnvelopeConsumerProcessor.enabled",
                        true)
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryJt808RawEnvelopeConsumerProcessor.group-id",
                        "${KAFKA_GROUP_HISTORY_JT808_RAW:${KAFKA_GROUP_HISTORY:vehicle-history}-jt808-raw}")
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryJt808RawEnvelopeConsumerProcessor.topics[0]",
                        "${KAFKA_TOPIC_JT808_RAW:vehicle.raw.jt808.v1}")
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryYutongMqttRawEnvelopeConsumerProcessor.enabled",
                        true)
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryYutongMqttRawEnvelopeConsumerProcessor.group-id",
                        "${KAFKA_GROUP_HISTORY_YUTONG_MQTT_RAW:${KAFKA_GROUP_HISTORY:vehicle-history}-yutong-mqtt-raw}")
                .containsEntry(
                        "lingniu.ingest.sink.kafka.consumer.bindings.eventHistoryYutongMqttRawEnvelopeConsumerProcessor.topics[0]",
                        "${KAFKA_TOPIC_YUTONG_MQTT_RAW:vehicle.raw.mqtt-yutong.v1}")
                .containsEntry("management.endpoints.web.exposure.include", "health,info,metrics,prometheus");

        assertThat(properties.stringPropertyNames())
                .noneMatch(name -> name.startsWith("lingniu.ingest.vehicle-state."))
                .noneMatch(name -> name.startsWith("lingniu.ingest.vehicle-stat."))
                .noneMatch(name -> name.startsWith("lingniu.ingest.sink.archive."))
                .noneMatch(name -> name.startsWith("lingniu.ingest.event-file-store."))
                .noneMatch(name -> name.startsWith("lingniu.ingest.event-history.api."));
        assertThat(properties.stringPropertyNames())
                .noneMatch(name -> name.equals("lingniu.ingest.tdengine-history.telemetry-fields-enabled"));
        assertThat(applicationYaml())
                .doesNotContain("\n      archive:\n")
                .doesNotContain("sink.archive")
                .doesNotContain("EVENT_HISTORY_SPECIALIZED_API_ENABLED")
                .doesNotContain("KAFKA_ENABLED");
    }

    @Test
    void runtimeClasspathDoesNotContainLegacyCommonsLoggingJar() throws Exception {
        List<String> logFactoryResources = Collections.list(Thread.currentThread()
                .getContextClassLoader()
                .getResources("org/apache/commons/logging/LogFactory.class"))
                .stream()
                .map(URL::toExternalForm)
                .toList();

        assertThat(logFactoryResources)
                .noneMatch(resource -> resource.contains("/commons-logging-"));
    }

    private static Properties applicationProperties() {
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        factory.setResources(new ClassPathResource("application.yml"));

        Properties properties = factory.getObject();

        assertThat(properties).isNotNull();
        return properties;
    }

    private static String applicationYaml() throws IOException {
        return new String(new ClassPathResource("application.yml").getInputStream().readAllBytes(),
                StandardCharsets.UTF_8);
    }
}
