using Lucene.Net.Attributes;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Index.Extensions;
using Lucene.Net.Store;
using Lucene.Net.Util;
using NUnit.Framework;
using System.Collections.Generic;

#nullable enable

namespace Lucene.Net.Search.Grouping
{
    /*
     * 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.
     */

    /// <summary>
    /// Tests that validate the code examples from the package.md documentation.
    /// </summary>
    [SuppressCodecs("Lucene3x")]
    [LuceneNetSpecific]
    public class GroupingSearchDocExampleTest : LuceneTestCase
    {
        /// <summary>
        /// Tests the "typical usage for the generic two-pass grouping search" example
        /// from the package.md documentation using <see cref="GroupingSearch.ByField(string)"/>.
        /// </summary>
        [Test]
        public void TestFieldGroupingSearchDocExample()
        {
            Directory dir = NewDirectory();
            RandomIndexWriter w = new RandomIndexWriter(
                Random,
                dir,
                NewIndexWriterConfig(TEST_VERSION_CURRENT,
                    new Analysis.MockAnalyzer(Random)).SetMergePolicy(NewLogMergePolicy()));

            // Index some documents with an "author" group field and "content" text field
            Document doc = new Document();
            doc.Add(new SortedDocValuesField("author", new BytesRef("author1")));
            doc.Add(new TextField("author", "author1", Field.Store.YES));
            doc.Add(new TextField("content", "random text", Field.Store.YES));
            w.AddDocument(doc);

            doc = new Document();
            doc.Add(new SortedDocValuesField("author", new BytesRef("author1")));
            doc.Add(new TextField("author", "author1", Field.Store.YES));
            doc.Add(new TextField("content", "more random text", Field.Store.YES));
            w.AddDocument(doc);

            doc = new Document();
            doc.Add(new SortedDocValuesField("author", new BytesRef("author2")));
            doc.Add(new TextField("author", "author2", Field.Store.YES));
            doc.Add(new TextField("content", "random content", Field.Store.YES));
            w.AddDocument(doc);

            IndexSearcher indexSearcher = NewSearcher(w.GetReader());
            w.Dispose();

            // --- Code from package.md documentation ---
            Sort groupSort = Sort.RELEVANCE;
            const bool fillFields = true;
            const bool useCache = true;
            const bool requiredTotalGroupCount = true;
            const string searchTerm = "random";
            const int groupOffset = 0;
            const int groupLimit = 10;

            FieldGroupingSearch groupingSearch = GroupingSearch.ByField("author");
            groupingSearch.SetGroupSort(groupSort);
            groupingSearch.SetFillSortFields(fillFields);

            if (useCache)
            {
                // Sets cache in MB
                groupingSearch.SetCachingInMB(maxCacheRAMMB: 4.0, cacheScores: true);
            }

            if (requiredTotalGroupCount)
            {
                groupingSearch.SetAllGroups(true);
            }

            TermQuery query = new TermQuery(new Index.Term("content", searchTerm));
            TopGroups<BytesRef> result = groupingSearch.Search(indexSearcher, query, groupOffset, groupLimit);

            // Verify results
            Assert.IsNotNull(result);
            assertEquals(3, result.TotalHitCount);
            assertEquals(2, result.Groups.Length); // 2 groups: author1 and author2

            if (requiredTotalGroupCount)
            {
                int? totalGroupCount = result.TotalGroupCount;
                Assert.IsNotNull(totalGroupCount);
                assertEquals(2, totalGroupCount!.Value);
            }

            indexSearcher.IndexReader.Dispose();
            dir.Dispose();
        }

        /// <summary>
        /// Tests the "GroupingSearch convenience utility" example for doc block grouping
        /// from the package.md documentation using <see cref="GroupingSearch.ByDocBlock(Filter)"/>.
        /// </summary>
        [Test]
        public void TestDocBlockGroupingSearchDocExample()
        {
            Directory dir = NewDirectory();
            RandomIndexWriter w = new RandomIndexWriter(
                Random,
                dir,
                NewIndexWriterConfig(TEST_VERSION_CURRENT,
                    new Analysis.MockAnalyzer(Random)).SetMergePolicy(NewLogMergePolicy()));

            // --- Indexing code from package.md documentation ---
            // Group 1: two documents by author1
            List<Document> oneGroup = new List<Document>();
            Document doc = new Document();
            doc.Add(new TextField("content", "random text", Field.Store.YES));
            oneGroup.Add(doc);

            doc = new Document();
            doc.Add(new TextField("content", "more random text", Field.Store.YES));
            oneGroup.Add(doc);

            Field groupEndField = new StringField("groupEnd", "x", Field.Store.NO);
            oneGroup[oneGroup.Count - 1].Add(groupEndField);
            w.AddDocuments(oneGroup);

            // Group 2: one document by author2
            oneGroup = new List<Document>();
            doc = new Document();
            doc.Add(new TextField("content", "random content", Field.Store.YES));
            oneGroup.Add(doc);

            groupEndField = new StringField("groupEnd", "x", Field.Store.NO);
            oneGroup[oneGroup.Count - 1].Add(groupEndField);
            w.AddDocuments(oneGroup);

            IndexSearcher indexSearcher = NewSearcher(w.GetReader());
            w.Dispose();

            // --- Search code from package.md documentation ---
            Sort groupSort = Sort.RELEVANCE;
            const bool needsScores = true;
            const string searchTerm = "random";
            const int groupOffset = 0;
            const int groupLimit = 10;

            // Set this once in your app & save away for reusing across all queries:
            Filter groupEndDocs = new CachingWrapperFilter(new QueryWrapperFilter(new TermQuery(new Index.Term("groupEnd", "x"))));

            // Per search:
            DocBlockGroupingSearch groupingSearch = GroupingSearch.ByDocBlock(groupEndDocs);
            groupingSearch.SetGroupSort(groupSort);
            groupingSearch.SetIncludeScores(needsScores);
            TermQuery query = new TermQuery(new Index.Term("content", searchTerm));
            TopGroups<object?> groupsResult = groupingSearch.Search(indexSearcher, query, groupOffset, groupLimit);

            // Verify results
            Assert.IsNotNull(groupsResult);
            assertEquals(3, groupsResult.TotalHitCount);
            assertEquals(2, groupsResult.Groups.Length); // 2 doc block groups

            // Note that the groupValue of each GroupDocs will be null
            foreach (var group in groupsResult.Groups)
            {
                assertNull(group.GroupValue);
            }

            indexSearcher.IndexReader.Dispose();
            dir.Dispose();
        }
    }
}
