package com.lingniu.ingest.session.config;

import com.lingniu.ingest.session.RedisSessionStore;
import com.lingniu.ingest.session.SessionStore;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.data.redis.core.StringRedisTemplate;

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

class SessionCoreAutoConfigurationTest {

    private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
            .withConfiguration(AutoConfigurations.of(SessionCoreAutoConfiguration.class));

    @Test
    void doesNotCreateImplicitInMemorySessionStoreByDefault() {
        contextRunner.run(context -> {
            assertThat(context).doesNotHaveBean(SessionStore.class);
        });
    }

    @Test
    void doesNotPublishInMemorySessionStoreImplementation() {
        assertThatThrownBy(() -> Class.forName("com.lingniu.ingest.session.InMemorySessionStore"))
                .isInstanceOf(ClassNotFoundException.class);
    }

    @Test
    void usesRedisSessionStoreWhenEnabledAndRedisTemplateExists() {
        contextRunner
                .withBean(StringRedisTemplate.class, () -> mock(StringRedisTemplate.class))
                .withPropertyValues(
                        "lingniu.ingest.session.store=redis",
                        "lingniu.ingest.session.ttl=45m")
                .run(context -> {
                    assertThat(context).hasSingleBean(SessionStore.class);
                    assertThat(context).hasSingleBean(RedisSessionStore.class);
                });
    }

    @Test
    void usesRedisSessionStoreByDefaultWhenRedisTemplateExists() {
        contextRunner
                .withBean(StringRedisTemplate.class, () -> mock(StringRedisTemplate.class))
                .run(context -> {
                    assertThat(context).hasSingleBean(SessionStore.class);
                    assertThat(context).hasSingleBean(RedisSessionStore.class);
                });
    }

    @Test
    void rejectsMemorySessionStoreModeWithRedisOnlyRule() {
        contextRunner
                .withPropertyValues("lingniu.ingest.session.store=memory")
                .run(context -> assertThat(context.getStartupFailure())
                        .hasRootCauseInstanceOf(IllegalStateException.class)
                        .hasStackTraceContaining("session.store supports only redis")
                        .hasStackTraceContaining("memory"));
    }

    @Test
    void sessionPropertiesDoNotExposeLegacyStoreEnum() {
        assertThatThrownBy(() -> Class.forName("com.lingniu.ingest.session.SessionProperties$Store"))
                .isInstanceOf(ClassNotFoundException.class);
    }
}
