package com.lingniu.ingest.identity.config;

import com.lingniu.ingest.identity.VehicleIdentityRegistry;
import com.lingniu.ingest.identity.VehicleIdentityResolver;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

import java.nio.file.Files;
import java.nio.file.Path;

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

class VehicleIdentityAutoConfigurationTest {

    private final ApplicationContextRunner runner = new ApplicationContextRunner()
            .withConfiguration(AutoConfigurations.of(VehicleIdentityAutoConfiguration.class));

    @Test
    void createsMysqlIdentityServiceByDefault() {
        runner
                .withPropertyValues(
                        "lingniu.ingest.identity.mysql.jdbc-url=jdbc:h2:mem:auto-identity-default;MODE=MySQL;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1",
                        "lingniu.ingest.identity.mysql.username=sa",
                        "lingniu.ingest.identity.mysql.password=",
                        "lingniu.ingest.identity.mysql.table-name=vehicle_identity_bindings")
                .run(context -> {
                    assertThat(context).hasSingleBean(VehicleIdentityResolver.class);
                    assertThat(context).hasSingleBean(VehicleIdentityRegistry.class);
                    assertThat(context.getBean(VehicleIdentityResolver.class))
                            .isSameAs(context.getBean(VehicleIdentityRegistry.class));
                    assertThat(context.getBean(VehicleIdentityResolver.class).getClass().getSimpleName())
                            .isEqualTo("MySqlVehicleIdentityService");
                });
    }

    @Test
    void createsMysqlIdentityServiceWhenConfigured() {
        runner
                .withPropertyValues(
                        "lingniu.ingest.identity.store=mysql",
                        "lingniu.ingest.identity.mysql.jdbc-url=jdbc:h2:mem:auto-identity;MODE=MySQL;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1",
                        "lingniu.ingest.identity.mysql.username=sa",
                        "lingniu.ingest.identity.mysql.password=",
                        "lingniu.ingest.identity.mysql.table-name=vehicle_identity_bindings")
                .run(context -> {
                    assertThat(context).hasSingleBean(VehicleIdentityResolver.class);
                    assertThat(context).hasSingleBean(VehicleIdentityRegistry.class);
                    assertThat(context.getBean(VehicleIdentityResolver.class))
                            .isSameAs(context.getBean(VehicleIdentityRegistry.class));
                    assertThat(context.getBean(VehicleIdentityResolver.class).getClass().getSimpleName())
                            .isEqualTo("MySqlVehicleIdentityService");
                });
    }

    @Test
    void rejectsUnsupportedStoreMode() {
        runner
                .withPropertyValues("lingniu.ingest.identity.store=file")
                .run(context -> assertThat(context.getStartupFailure())
                        .hasRootCauseInstanceOf(IllegalStateException.class)
                        .hasMessageContaining("identity.store supports only mysql")
                        .hasMessageContaining("file"));
    }

    @Test
    void rejectsSqliteStoreModeWithSameMysqlOnlyRule() {
        runner
                .withPropertyValues("lingniu.ingest.identity.store=sqlite")
                .run(context -> assertThat(context.getStartupFailure())
                        .hasRootCauseInstanceOf(IllegalStateException.class)
                        .hasMessageContaining("identity.store supports only mysql")
                        .hasMessageContaining("sqlite"));
    }

    @Test
    void moduleDoesNotKeepAlternativeStoreImplementations() {
        Path sourceRoot = Path.of("src/main/java/com/lingniu/ingest/identity");

        assertThat(Files.exists(sourceRoot.resolve("InMemoryVehicleIdentityService.java")))
                .as("identity store is mysql-only; in-memory implementation must not be shipped")
                .isFalse();
    }
}
