package org.apache.ignite.spring.sessions;

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.configuration.CacheConfiguration;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers;

import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.session.FlushMode;
import org.springframework.session.IndexResolver;
import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.session.config.SessionRepositoryCustomizer;
import org.springframework.test.util.ReflectionTestUtils;

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

/**
 * Tests for {@link IgniteHttpSessionConfiguration}.
 */
class IgniteHttpSessionConfigurationTests {

    private static final String MAP_NAME = "spring:test:sessions";

    private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 600;

    private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

    @AfterEach
    void closeContext() {
        if (this.context != null)
            this.context.close();
    }

    @Test
    void noIgniteConfiguration() {
        assertThatExceptionOfType(BeanCreationException.class)
                .isThrownBy(() -> registerAndRefresh(NoIgniteConfiguration.class)).withMessageContaining("Ignite");
    }

    @Test
    void defaultConfiguration() {
        registerAndRefresh(DefaultConfiguration.class);

        assertThat(this.context.getBean(IgniteIndexedSessionRepository.class)).isNotNull();
    }

    @Test
    void customTableName() {
        registerAndRefresh(CustomSessionMapNameConfiguration.class);

        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
        IgniteHttpSessionConfiguration configuration = this.context.getBean(IgniteHttpSessionConfiguration.class);
        assertThat(repository).isNotNull();
        assertThat(ReflectionTestUtils.getField(configuration, "sessionMapName")).isEqualTo(MAP_NAME);
    }

    @Test
    void setCustomSessionMapName() {
        registerAndRefresh(BaseConfiguration.class, CustomSessionMapNameSetConfiguration.class);

        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
        IgniteHttpSessionConfiguration configuration = this.context.getBean(IgniteHttpSessionConfiguration.class);
        assertThat(repository).isNotNull();
        assertThat(ReflectionTestUtils.getField(configuration, "sessionMapName")).isEqualTo(MAP_NAME);
    }

    @Test
    void setCustomMaxInactiveIntervalInSeconds() {
        registerAndRefresh(BaseConfiguration.class, CustomMaxInactiveIntervalInSecondsSetConfiguration.class);

        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
        assertThat(repository).isNotNull();
        assertThat(ReflectionTestUtils.getField(repository, "defaultMaxInactiveInterval"))
                .isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
    }

    @Test
    void customMaxInactiveIntervalInSeconds() {
        registerAndRefresh(CustomMaxInactiveIntervalInSecondsConfiguration.class);

        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
        assertThat(repository).isNotNull();
        assertThat(ReflectionTestUtils.getField(repository, "defaultMaxInactiveInterval"))
                .isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
    }

    @Test
    void customFlushImmediately() {
        registerAndRefresh(CustomFlushImmediatelyConfiguration.class);

        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
        assertThat(repository).isNotNull();
        assertThat(ReflectionTestUtils.getField(repository, "flushMode")).isEqualTo(FlushMode.IMMEDIATE);
    }

    @Test
    void setCustomFlushImmediately() {
        registerAndRefresh(BaseConfiguration.class, CustomFlushImmediatelySetConfiguration.class);

        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
        assertThat(repository).isNotNull();
        assertThat(ReflectionTestUtils.getField(repository, "flushMode")).isEqualTo(FlushMode.IMMEDIATE);
    }

    @Test
    void customSaveModeAnnotation() {
        registerAndRefresh(BaseConfiguration.class, CustomSaveModeExpressionAnnotationConfiguration.class);
        assertThat(this.context.getBean(IgniteIndexedSessionRepository.class)).hasFieldOrPropertyWithValue("saveMode",
                SaveMode.ALWAYS);
    }

    @Test
    void customSaveModeSetter() {
        registerAndRefresh(BaseConfiguration.class, CustomSaveModeExpressionSetterConfiguration.class);
        assertThat(this.context.getBean(IgniteIndexedSessionRepository.class)).hasFieldOrPropertyWithValue("saveMode",
                SaveMode.ALWAYS);
    }

    @Test
    void qualifiedIgniteConfiguration() {
        registerAndRefresh(QualifiedIgniteConfiguration.class);

        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
        Ignite ignite = this.context.getBean("qualifiedIgnite", Ignite.class);
        assertThat(repository).isNotNull();
        assertThat(ignite).isNotNull();
        assertThat(ReflectionTestUtils.getField(repository, "sessions"))
                .isEqualTo(QualifiedIgniteConfiguration.qualifiedIgniteSessions);
    }

    @Test
    void primaryIgniteConfiguration() {
        registerAndRefresh(PrimaryIgniteConfiguration.class);

        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
        Ignite ignite = this.context.getBean("primaryIgnite", Ignite.class);
        assertThat(repository).isNotNull();
        assertThat(ignite).isNotNull();
        assertThat(ReflectionTestUtils.getField(repository, "sessions"))
                .isEqualTo(PrimaryIgniteConfiguration.primaryIgniteSessions);
    }

    @Test
    void qualifiedAndPrimaryIgniteConfiguration() {
        registerAndRefresh(QualifiedAndPrimaryIgniteConfiguration.class);

        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
        Ignite ignite = this.context.getBean("qualifiedIgnite", Ignite.class);
        assertThat(repository).isNotNull();
        assertThat(ignite).isNotNull();
        assertThat(ReflectionTestUtils.getField(repository, "sessions"))
                .isEqualTo(QualifiedAndPrimaryIgniteConfiguration.qualifiedIgniteSessions);
    }

    @Test
    void namedIgniteConfiguration() {
        registerAndRefresh(NamedIgniteConfiguration.class);

        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
        Ignite ignite = this.context.getBean("ignite", Ignite.class);
        assertThat(repository).isNotNull();
        assertThat(ignite).isNotNull();
        assertThat(ReflectionTestUtils.getField(repository, "sessions"))
                .isEqualTo(NamedIgniteConfiguration.igniteSessions);
    }

    @Test
    void multipleIgniteConfiguration() {
        assertThatExceptionOfType(BeanCreationException.class)
                .isThrownBy(() -> registerAndRefresh(MultipleIgniteConfiguration.class))
                .withMessageContaining("expected single matching bean but found 2");
    }

    @Test
    void customIndexResolverConfiguration() {
        registerAndRefresh(CustomIndexResolverConfiguration.class);
        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
        @SuppressWarnings("unchecked")
        IndexResolver<Session> indexResolver = this.context.getBean(IndexResolver.class);
        assertThat(repository).isNotNull();
        assertThat(indexResolver).isNotNull();
        assertThat(repository).hasFieldOrPropertyWithValue("indexResolver", indexResolver);
    }

    @Test
    void sessionRepositoryCustomizer() {
        registerAndRefresh(SessionRepositoryCustomizerConfiguration.class);
        IgniteIndexedSessionRepository sessionRepository = this.context.getBean(IgniteIndexedSessionRepository.class);
        assertThat(sessionRepository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
                MAX_INACTIVE_INTERVAL_IN_SECONDS);
    }

    private void registerAndRefresh(Class<?>... annotatedClasses) {
        this.context.register(annotatedClasses);
        this.context.refresh();
    }

    @Configuration
    @EnableIgniteHttpSession
    static class NoIgniteConfiguration {

    }

    static class BaseConfiguration {

        @SuppressWarnings("unchecked")
        static IgniteCache<Object, Object> defaultIgniteSessions = mock(IgniteCache.class);

        @Bean
        Ignite defaultIgnite() {
            Ignite ignite = mock(Ignite.class);
            given(ignite.getOrCreateCache(ArgumentMatchers.<CacheConfiguration<Object, Object>>any()))
                    .willReturn(defaultIgniteSessions);
            return ignite;
        }

    }

    @Configuration
    @EnableIgniteHttpSession
    static class DefaultConfiguration extends BaseConfiguration {

    }

    @Configuration
    @EnableIgniteHttpSession(sessionMapName = MAP_NAME)
    static class CustomSessionMapNameConfiguration extends BaseConfiguration {

    }

    @Configuration
    static class CustomSessionMapNameSetConfiguration extends IgniteHttpSessionConfiguration {

        CustomSessionMapNameSetConfiguration() {
            setSessionMapName(MAP_NAME);
        }

    }

    @Configuration
    static class CustomMaxInactiveIntervalInSecondsSetConfiguration extends IgniteHttpSessionConfiguration {

        CustomMaxInactiveIntervalInSecondsSetConfiguration() {
            setMaxInactiveIntervalInSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS);
        }

    }

    @Configuration
    @EnableIgniteHttpSession(maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
    static class CustomMaxInactiveIntervalInSecondsConfiguration extends BaseConfiguration {

    }

    @Configuration
    static class CustomFlushImmediatelySetConfiguration extends IgniteHttpSessionConfiguration {

        CustomFlushImmediatelySetConfiguration() {
            setFlushMode(FlushMode.IMMEDIATE);
        }

    }

    @EnableIgniteHttpSession(saveMode = SaveMode.ALWAYS)
    static class CustomSaveModeExpressionAnnotationConfiguration {

    }

    @Configuration
    static class CustomSaveModeExpressionSetterConfiguration extends IgniteHttpSessionConfiguration {

        CustomSaveModeExpressionSetterConfiguration() {
            setSaveMode(SaveMode.ALWAYS);
        }

    }

    @Configuration
    @EnableIgniteHttpSession(flushMode = FlushMode.IMMEDIATE)
    static class CustomFlushImmediatelyConfiguration extends BaseConfiguration {

    }

    @Configuration
    @EnableIgniteHttpSession
    static class QualifiedIgniteConfiguration extends BaseConfiguration {

        @SuppressWarnings("unchecked")
        static IgniteCache<Object, Object> qualifiedIgniteSessions = mock(IgniteCache.class);

        @Bean
        @SpringSessionIgnite
        Ignite qualifiedIgnite() {
            Ignite ignite = mock(Ignite.class);
            given(ignite.getOrCreateCache(ArgumentMatchers.<CacheConfiguration<Object, Object>>any()))
                    .willReturn(qualifiedIgniteSessions);
            return ignite;
        }

    }

    @Configuration
    @EnableIgniteHttpSession
    static class PrimaryIgniteConfiguration extends BaseConfiguration {

        @SuppressWarnings("unchecked")
        static IgniteCache<Object, Object> primaryIgniteSessions = mock(IgniteCache.class);

        @Bean
        @Primary
        Ignite primaryIgnite() {
            Ignite ignite = mock(Ignite.class);
            given(ignite.getOrCreateCache(ArgumentMatchers.<CacheConfiguration<Object, Object>>any()))
                    .willReturn(primaryIgniteSessions);
            return ignite;
        }

    }

    @Configuration
    @EnableIgniteHttpSession
    static class QualifiedAndPrimaryIgniteConfiguration extends BaseConfiguration {

        @SuppressWarnings("unchecked")
        static IgniteCache<Object, Object> qualifiedIgniteSessions = mock(IgniteCache.class);

        @SuppressWarnings("unchecked")
        static IgniteCache<Object, Object> primaryIgniteSessions = mock(IgniteCache.class);

        @Bean
        @SpringSessionIgnite
        Ignite qualifiedIgnite() {
            Ignite ignite = mock(Ignite.class);
            given(ignite.getOrCreateCache(ArgumentMatchers.<CacheConfiguration<Object, Object>>any()))
                    .willReturn(qualifiedIgniteSessions);
            return ignite;
        }

        @Bean
        @Primary
        Ignite primaryIgnite() {
            Ignite ignite = mock(Ignite.class);
            given(ignite.getOrCreateCache(ArgumentMatchers.<CacheConfiguration<Object, Object>>any()))
                    .willReturn(primaryIgniteSessions);
            return ignite;
        }

    }

    @Configuration
    @EnableIgniteHttpSession
    static class NamedIgniteConfiguration extends BaseConfiguration {

        @SuppressWarnings("unchecked")
        static IgniteCache<Object, Object> igniteSessions = mock(IgniteCache.class);

        @Bean
        Ignite ignite() {
            Ignite ignite = mock(Ignite.class);
            given(ignite.getOrCreateCache(ArgumentMatchers.<CacheConfiguration<Object, Object>>any()))
                    .willReturn(igniteSessions);
            return ignite;
        }

    }

    @Configuration
    @EnableIgniteHttpSession
    static class MultipleIgniteConfiguration extends BaseConfiguration {

        @SuppressWarnings("unchecked")
        static IgniteCache<Object, Object> secondaryIgniteSessions = mock(IgniteCache.class);

        @Bean
        Ignite secondaryIgnite() {
            Ignite ignite = mock(Ignite.class);
            given(ignite.getOrCreateCache(ArgumentMatchers.<CacheConfiguration<Object, Object>>any()))
                    .willReturn(secondaryIgniteSessions);
            return ignite;
        }

    }

    @EnableIgniteHttpSession
    static class CustomIndexResolverConfiguration extends BaseConfiguration {

        @Bean
        @SuppressWarnings("unchecked")
        IndexResolver<Session> indexResolver() {
            return mock(IndexResolver.class);
        }

    }

    @EnableIgniteHttpSession
    static class SessionRepositoryCustomizerConfiguration extends BaseConfiguration {

        @Bean
        @Order(0)
        SessionRepositoryCustomizer<IgniteIndexedSessionRepository> sessionRepositoryCustomizerOne() {
            return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(0);
        }

        @Bean
        @Order(1)
        SessionRepositoryCustomizer<IgniteIndexedSessionRepository> sessionRepositoryCustomizerTwo() {
            return (sessionRepository) -> sessionRepository
                    .setDefaultMaxInactiveInterval(MAX_INACTIVE_INTERVAL_IN_SECONDS);
        }
    }
}

