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 java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.cache.expiry.TouchedExpiryPolicy;

import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.query.FieldsQueryCursor;
import org.apache.ignite.configuration.CacheConfiguration;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession;
import org.apache.ignite.spring.sessions.IgniteIndexedSessionRepository.IgniteSession;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;

/**
 * Tests for {@link IgniteIndexedSessionRepository}.
 */
class IgniteIndexedSessionRepositoryTests {

    private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";

    private final Ignite ignite = mock(Ignite.class);

    @SuppressWarnings("unchecked")
    private final IgniteCache<String, IgniteSession> sessions = mock(IgniteCache.class);

    private IgniteIndexedSessionRepository repository;

    @BeforeEach
    void setUp() {
        given(this.ignite.<String, IgniteSession>getOrCreateCache(
                ArgumentMatchers.<CacheConfiguration<String, IgniteSession>>any())).willReturn(this.sessions);
        given(this.sessions.withExpiryPolicy(ArgumentMatchers.any())).willReturn(this.sessions);
        this.repository = new IgniteIndexedSessionRepository(this.ignite);
        this.repository.init();
    }

    @Test
    void constructorNullIgnite() {
        assertThatIllegalArgumentException().isThrownBy(() -> new IgniteIndexedSessionRepository(null))
                .withMessage("Ignite must not be null");
    }

    @Test
    void setSaveModeNull() {
        assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setSaveMode(null))
                .withMessage("saveMode must not be null");
    }

    @Test
    void createSessionDefaultMaxInactiveInterval() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        IgniteSession session = this.repository.createSession();

        assertThat(session.getMaxInactiveInterval()).isEqualTo(new MapSession().getMaxInactiveInterval());
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void createSessionCustomMaxInactiveInterval() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        int interval = 1;
        this.repository.setDefaultMaxInactiveInterval(interval);

        IgniteSession session = this.repository.createSession();

        assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(interval));
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void saveNewFlushModeOnSave() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        IgniteSession session = this.repository.createSession();
        verifyNoMoreInteractions(this.sessions);

        this.repository.save(session);
        verify(this.sessions, times(1)).put(eq(session.getId()), eq(session));
        verify(this.sessions, times(1)).withExpiryPolicy(eq(createExpiryPolicy(session)));
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void saveNewFlushModeImmediate() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        this.repository.setFlushMode(FlushMode.IMMEDIATE);

        IgniteSession session = this.repository.createSession();
        verify(this.sessions, times(1)).put(eq(session.getId()), eq(session));
        verify(this.sessions, times(1)).withExpiryPolicy(eq(createExpiryPolicy(session)));
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void saveUpdatedAttributeFlushModeOnSave() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        IgniteSession session = this.repository.createSession();
        session.setAttribute("testName", "testValue");
        verifyNoMoreInteractions(this.sessions);

        this.repository.save(session);
        verify(this.sessions, times(1)).put(eq(session.getId()), eq(session));
        verify(this.sessions, times(1)).withExpiryPolicy(eq(createExpiryPolicy(session)));
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void saveUpdatedAttributeFlushModeImmediate() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        this.repository.setFlushMode(FlushMode.IMMEDIATE);

        IgniteSession session = this.repository.createSession();
        session.setAttribute("testName", "testValue");
        verify(this.sessions, times(1)).withExpiryPolicy(eq(createExpiryPolicy(session)));
        verify(this.sessions, times(1)).put(eq(session.getId()), eq(session));
        verify(this.sessions, times(1)).replace(eq(session.getId()), eq(session));

        this.repository.save(session);
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void removeAttributeFlushModeOnSave() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        IgniteSession session = this.repository.createSession();
        session.removeAttribute("testName");
        verifyNoMoreInteractions(this.sessions);

        this.repository.save(session);
        verify(this.sessions, times(1)).put(eq(session.getId()), eq(session));
        verify(this.sessions, times(1)).withExpiryPolicy(eq(createExpiryPolicy(session)));
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void removeAttributeFlushModeImmediate() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        this.repository.setFlushMode(FlushMode.IMMEDIATE);

        IgniteSession session = this.repository.createSession();
        session.removeAttribute("testName");
        verify(this.sessions, times(1)).put(eq(session.getId()), eq(session));
        verify(this.sessions, times(1)).replace(eq(session.getId()), eq(session));
        verify(this.sessions, times(1)).withExpiryPolicy(eq(createExpiryPolicy(session)));

        this.repository.save(session);
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void saveUpdatedLastAccessedTimeFlushModeOnSave() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        IgniteSession session = this.repository.createSession();
        session.setLastAccessedTime(Instant.now());
        verifyNoMoreInteractions(this.sessions);

        this.repository.save(session);
        verify(this.sessions, times(1)).put(eq(session.getId()), eq(session));
        verify(this.sessions, times(1)).withExpiryPolicy(eq(createExpiryPolicy(session)));
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void saveUpdatedLastAccessedTimeFlushModeImmediate() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        this.repository.setFlushMode(FlushMode.IMMEDIATE);

        IgniteSession session = this.repository.createSession();
        session.setLastAccessedTime(Instant.now());
        verify(this.sessions, times(1)).put(eq(session.getId()), eq(session));
        verify(this.sessions, times(1)).replace(eq(session.getId()), eq(session));
        verify(this.sessions, times(1)).withExpiryPolicy(eq(createExpiryPolicy(session)));

        this.repository.save(session);
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void saveUpdatedMaxInactiveIntervalInSecondsFlushModeOnSave() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        IgniteSession session = this.repository.createSession();
        session.setMaxInactiveInterval(Duration.ofSeconds(1));
        verifyNoMoreInteractions(this.sessions);

        this.repository.save(session);
        verify(this.sessions, times(1)).put(eq(session.getId()), eq(session));
        verify(this.sessions, times(1)).withExpiryPolicy(eq(createExpiryPolicy(session)));
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void saveUpdatedMaxInactiveIntervalInSecondsFlushModeImmediate() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        this.repository.setFlushMode(FlushMode.IMMEDIATE);

        IgniteSession session = this.repository.createSession();
        verify(this.sessions, times(1)).withExpiryPolicy(eq(createExpiryPolicy(session)));
        String sessionId = session.getId();
        session.setMaxInactiveInterval(Duration.ofSeconds(1));
        verify(this.sessions, times(1)).put(eq(sessionId), eq(session));
        verify(this.sessions, times(1)).replace(eq(sessionId), eq(session));
        verify(this.sessions, times(1)).withExpiryPolicy(eq(createExpiryPolicy(session)));

        this.repository.save(session);
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void saveUnchangedFlushModeOnSave() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        IgniteSession session = this.repository.createSession();
        this.repository.save(session);
        verify(this.sessions, times(1)).put(eq(session.getId()), eq(session));
        verify(this.sessions, times(1)).withExpiryPolicy(eq(createExpiryPolicy(session)));

        this.repository.save(session);
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void saveUnchangedFlushModeImmediate() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        this.repository.setFlushMode(FlushMode.IMMEDIATE);

        IgniteSession session = this.repository.createSession();
        verify(this.sessions, times(1)).put(eq(session.getId()), eq(session));
        verify(this.sessions, times(1)).withExpiryPolicy(eq(createExpiryPolicy(session)));

        this.repository.save(session);
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void getSessionNotFound() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        String sessionId = "testSessionId";

        IgniteSession session = this.repository.findById(sessionId);

        assertThat(session).isNull();
        verify(this.sessions, times(1)).get(eq(sessionId));
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void getSessionExpired() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        IgniteSession expired = this.repository.new IgniteSession(new MapSession(), true);

        expired.setLastAccessedTime(Instant.now().minusSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS + 1));
        given(this.sessions.get(eq(expired.getId()))).willReturn(expired);

        IgniteSession session = this.repository.findById(expired.getId());

        assertThat(session).isNull();
        verify(this.sessions, times(1)).get(eq(expired.getId()));
        verify(this.sessions, times(1)).remove(eq(expired.getId()));
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void getSessionFound() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        IgniteSession saved = this.repository.new IgniteSession(new MapSession(), true);
        saved.setAttribute("savedName", "savedValue");
        given(this.sessions.get(eq(saved.getId()))).willReturn(saved);

        IgniteSession session = this.repository.findById(saved.getId());

        assertThat(session.getId()).isEqualTo(saved.getId());
        assertThat(session.<String>getAttribute("savedName")).isEqualTo("savedValue");
        verify(this.sessions, times(1)).get(eq(saved.getId()));
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void delete() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        String sessionId = "testSessionId";

        this.repository.deleteById(sessionId);

        verify(this.sessions, times(1)).remove(eq(sessionId));
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void findByIndexNameAndIndexValueUnknownIndexName() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        String indexValue = "testIndexValue";

        Map<String, IgniteSession> sessions = this.repository.findByIndexNameAndIndexValue("testIndexName", indexValue);

        assertThat(sessions).isEmpty();
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void findByIndexNameAndIndexValuePrincipalIndexNameNotFound() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        String principal = "username";

        Map<String, IgniteSession> sessions = this.repository
                .findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principal);

        verify(this.sessions, times(1)).query(ArgumentMatchers
                .argThat((argument) -> ("SELECT * FROM IgniteSession WHERE principal='" + principal + "'")
                        .equals(argument.getSql())));

        assertThat(sessions).isEmpty();
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void findByIndexNameAndIndexValuePrincipalIndexNameFound() {
        verify(this.sessions, times(1)).registerCacheEntryListener(ArgumentMatchers.any());

        String principal = "username";
        Authentication authentication = new UsernamePasswordAuthenticationToken(principal, "notused",
                AuthorityUtils.createAuthorityList("ROLE_USER"));

        List<Object> saved = new ArrayList<>(2);

        final MapSession ses1 = new MapSession();
        ses1.setAttribute(SPRING_SECURITY_CONTEXT, authentication);
        IgniteSession saved1 = this.repository.new IgniteSession(ses1, true);
        saved.add(Arrays.asList(ses1, authentication.getPrincipal()));
        final MapSession ses2 = new MapSession();
        ses2.setAttribute(SPRING_SECURITY_CONTEXT, authentication);
        IgniteSession saved2 = this.repository.new IgniteSession(ses2, true);
        saved.add(Arrays.asList(ses2, authentication.getPrincipal()));

        given(this.sessions.query(ArgumentMatchers.any())).willReturn(new FieldsQueryCursor<List<?>>() {
            @Override
            public String getFieldName(int idx) {
                return null;
            }

            @Override
            public int getColumnsCount() {
                return 2;
            }

            @Override
            public List<List<?>> getAll() {
                return (List) saved;
            }

            @Override
            public void close() {

            }

            @NotNull
            @Override
            public Iterator<List<?>> iterator() {
                return (Iterator) saved.iterator();
            }
        });

        Map<String, IgniteSession> sessions = this.repository
                .findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, principal);

        assertThat(sessions).hasSize(2);
        verify(this.sessions, times(1)).query(any());
        verifyNoMoreInteractions(this.sessions);
    }

    @Test
    void getAttributeNamesAndRemove() {
        IgniteSession session = this.repository.createSession();
        session.setAttribute("attribute1", "value1");
        session.setAttribute("attribute2", "value2");

        for (String attributeName : session.getAttributeNames()) {
            session.removeAttribute(attributeName);
        }

        assertThat(session.getAttributeNames()).isEmpty();
    }

    private static TouchedExpiryPolicy createExpiryPolicy(IgniteSession session) {
        return new TouchedExpiryPolicy(
                new javax.cache.expiry.Duration(TimeUnit.SECONDS, session.getMaxInactiveInterval().getSeconds()));
    }

}

