//
// Licensed 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.

package org.apache.couchdb.nouveau.lucene9;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.couchdb.nouveau.api.DocumentDeleteRequest;
import org.apache.couchdb.nouveau.api.DocumentUpdateRequest;
import org.apache.couchdb.nouveau.api.DoubleField;
import org.apache.couchdb.nouveau.api.DoubleRange;
import org.apache.couchdb.nouveau.api.Field;
import org.apache.couchdb.nouveau.api.IndexDefinition;
import org.apache.couchdb.nouveau.api.IndexInfo;
import org.apache.couchdb.nouveau.api.SearchRequest;
import org.apache.couchdb.nouveau.api.SearchResults;
import org.apache.couchdb.nouveau.api.StringField;
import org.apache.couchdb.nouveau.core.Index;
import org.apache.couchdb.nouveau.core.UpdatesOutOfOrderException;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.misc.store.DirectIODirectory;
import org.apache.lucene.search.SearcherManager;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

public class Lucene9IndexTest {

    protected final Index setup(final Path path) throws IOException {
        final IndexDefinition indexDefinition = new IndexDefinition();
        indexDefinition.setDefaultAnalyzer("standard");
        final Analyzer analyzer = Lucene9AnalyzerFactory.fromDefinition(indexDefinition);
        final Directory dir = new DirectIODirectory(FSDirectory.open(path));
        final IndexWriterConfig config = new IndexWriterConfig(analyzer);
        config.setUseCompoundFile(false);
        final IndexWriter writer = new IndexWriter(dir, config);
        final SearcherManager searcherManager = new SearcherManager(writer, null);
        return new Lucene9Index(analyzer, writer, 0L, 0L, searcherManager);
    }

    protected final void cleanup(final Index index) throws IOException {
        index.setDeleteOnClose(true);
        index.close();
    }

    @Test
    public void testOpenClose(@TempDir Path path) throws IOException {
        final Index index = setup(path);
        cleanup(index);
    }

    @Test
    public void testSearching(@TempDir Path path) throws IOException {
        final Index index = setup(path);
        try {
            final int count = 100;
            List<String> ids = new ArrayList<String>(count);
            for (int i = 1; i <= count; i++) {
                final Collection<Field> fields = List.of(new StringField("foo", "bar", false));
                final DocumentUpdateRequest request = new DocumentUpdateRequest(i - 1, i, null, fields);
                final String id = "doc" + i;
                ids.add(id);
                index.update(id, request);
            }
            ids.sort(String::compareTo);
            final SearchRequest request = new SearchRequest();
            request.setQuery("*:*");
            request.setLimit(count);
            final SearchResults results = index.search(request);
            assertThat(results.getTotalHits()).isEqualTo(count);
            for (int i = 0; i < count; i++) {
                var hit = results.getHits().get(i);
                assertThat(hit.getId()).isEqualTo(ids.get(i));
                assertThat(hit.getSeq()).isEqualTo(Long.parseLong(ids.get(i).substring(3)));
            }
        } finally {
            cleanup(index);
        }
    }

    @Test
    public void testSort(@TempDir Path path) throws IOException {
        final Index index = setup(path);
        try {
            final int count = 100;
            for (int i = 1; i <= count; i++) {
                final Collection<Field> fields = List.of(new StringField("foo", "bar", false));
                final DocumentUpdateRequest request = new DocumentUpdateRequest(i - 1, i, null, fields);
                index.update("doc" + i, request);
            }
            final SearchRequest request = new SearchRequest();
            request.setQuery("*:*");
            request.setSort(List.of("foo<string>"));
            final SearchResults results = index.search(request);
            assertThat(results.getTotalHits()).isEqualTo(count);
        } finally {
            cleanup(index);
        }
    }

    @Test
    public void testCounts(@TempDir Path path) throws IOException {
        Index index = setup(path);
        try {
            final int count = 100;
            for (int i = 1; i <= count; i++) {
                final Collection<Field> fields = List.of(new StringField("bar", "baz", false));
                final DocumentUpdateRequest request = new DocumentUpdateRequest(i - 1, i, null, fields);
                index.update("doc" + i, request);
            }
            final SearchRequest request = new SearchRequest();
            request.setQuery("*:*");
            request.setCounts(List.of("bar"));
            final SearchResults results = index.search(request);
            assertThat(results.getCounts()).isEqualTo(Map.of("bar", Map.of("baz", count)));
        } finally {
            cleanup(index);
        }
    }

    @Test
    public void testRanges(@TempDir Path path) throws IOException {
        Index index = setup(path);
        try {
            final int count = 100;
            for (int i = 1; i <= count; i++) {
                final Collection<Field> fields = List.of(new DoubleField("bar", (double) i, false));
                final DocumentUpdateRequest request = new DocumentUpdateRequest(i - 1, i, null, fields);
                index.update("doc" + i, request);
            }
            final SearchRequest request = new SearchRequest();
            request.setQuery("*:*");
            request.setRanges(Map.of(
                    "bar",
                    List.of(
                            new DoubleRange("low", 0.0, true, (double) count / 2, true),
                            new DoubleRange("high", (double) count / 2, true, (double) count, true))));
            final SearchResults results = index.search(request);
            assertThat(results.getRanges()).isEqualTo(Map.of("bar", Map.of("low", count / 2, "high", count / 2 + 1)));
        } finally {
            cleanup(index);
        }
    }

    @Test
    public void testOutOfOrder(@TempDir Path path) throws IOException {
        Index index = setup(path);
        try {
            final Collection<Field> fields = Collections.emptyList();

            // get match seq wrong
            assertThrows(
                    UpdatesOutOfOrderException.class,
                    () -> index.update("foo", new DocumentUpdateRequest(1, 2, null, fields)));

            // Go to 2.
            index.update("foo", new DocumentUpdateRequest(0, 2, null, fields));

            // Should be prevented from going down to 1.
            assertThrows(
                    UpdatesOutOfOrderException.class,
                    () -> index.update("foo", new DocumentUpdateRequest(2, 1, null, fields)));
        } finally {
            cleanup(index);
        }
    }

    @Test
    public void testInfo(@TempDir Path path) throws IOException {
        Index index = setup(path);
        try {
            IndexInfo info = index.info();
            assertThat(info.getDiskSize()).isEqualTo(0);
            assertThat(info.getNumDocs()).isEqualTo(0);
            assertThat(info.getUpdateSeq()).isEqualTo(0);

            final Collection<Field> fields = List.of(new DoubleField("bar", 12.0, false));
            index.update("foo", new DocumentUpdateRequest(0, 2, null, fields));
            index.commit();

            info = index.info();
            assertThat(info.getDiskSize()).isGreaterThan(0);
            assertThat(info.getNumDocs()).isEqualTo(1);
            assertThat(info.getUpdateSeq()).isEqualTo(2);
        } finally {
            cleanup(index);
        }
    }

    @Test
    public void testDelete(@TempDir Path path) throws IOException {
        Index index = setup(path);
        try {
            final Collection<Field> fields = List.of(new DoubleField("bar", 12.0, false));
            index.update("foo", new DocumentUpdateRequest(0, 2, null, fields));
            index.commit();

            IndexInfo info = index.info();
            assertThat(info.getNumDocs()).isEqualTo(1);

            index.delete("foo", new DocumentDeleteRequest(2, 3, false));
            index.commit();

            info = index.info();
            assertThat(info.getNumDocs()).isEqualTo(0);
            assertThat(info.getUpdateSeq()).isEqualTo(3);
        } finally {
            cleanup(index);
        }
    }

    @Test
    public void testPurge(@TempDir Path path) throws IOException {
        Index index = setup(path);
        try {
            final Collection<Field> fields = List.of(new DoubleField("bar", 12.0, false));
            index.update("foo", new DocumentUpdateRequest(0, 2, null, fields));
            index.commit();

            IndexInfo info = index.info();
            assertThat(info.getNumDocs()).isEqualTo(1);

            index.delete("foo", new DocumentDeleteRequest(0, 3, true));
            index.commit();

            info = index.info();
            assertThat(info.getNumDocs()).isEqualTo(0);
            assertThat(info.getPurgeSeq()).isEqualTo(3);
        } finally {
            cleanup(index);
        }
    }
}
