/**
 * 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.
 */
package org.apache.metron.solr.dao;

import org.apache.metron.common.Constants;
import org.apache.metron.indexing.dao.AccessConfig;
import org.apache.metron.indexing.dao.search.*;
import org.apache.metron.indexing.dao.update.Document;
import org.apache.metron.solr.matcher.ModifiableSolrParamsMatcher;
import org.apache.metron.solr.matcher.SolrQueryMatcher;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.response.FieldStatsInfo;
import org.apache.solr.client.solrj.response.PivotField;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.util.NamedList;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.*;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasItems;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.*;

public class SolrSearchDaoTest {
  private SolrClient client;
  private AccessConfig accessConfig;
  private SolrSearchDao solrSearchDao;
  private SolrRetrieveLatestDao solrRetrieveLatestDao;

  @BeforeEach
  public void setUp() {
    client = mock(SolrClient.class);
    accessConfig = mock(AccessConfig.class);
    when(accessConfig.getIndexSupplier()).thenReturn(sensorType -> sensorType);
    solrSearchDao = new SolrSearchDao(client, accessConfig);
    solrRetrieveLatestDao = new SolrRetrieveLatestDao(client, accessConfig);
  }

  @Test
  public void searchShouldProperlyReturnSearchResponse() throws Exception {
    SearchRequest searchRequest = mock(SearchRequest.class);
    SearchResponse searchResponse = mock(SearchResponse.class);
    SolrQuery solrQuery = mock(SolrQuery.class);
    QueryResponse queryResponse = mock(QueryResponse.class);

    solrSearchDao = spy(new SolrSearchDao(client, accessConfig));
    when(searchRequest.getQuery()).thenReturn("query");
    doReturn(solrQuery).when(solrSearchDao).buildSearchRequest(searchRequest, "*");
    when(client.query(solrQuery)).thenReturn(queryResponse);
    doReturn(searchResponse).when(solrSearchDao).buildSearchResponse(searchRequest, queryResponse);

    assertEquals(searchResponse, solrSearchDao.search(searchRequest, "*"));
    verify(solrSearchDao).buildSearchRequest(searchRequest, "*");
    verify(client).query(solrQuery);
    verify(solrSearchDao).buildSearchResponse(searchRequest, queryResponse);
    verifyNoMoreInteractions(client);
  }

  @Test
  public void searchShouldThrowInvalidSearchExceptionOnEmptyQuery() {
    InvalidSearchException e = assertThrows(InvalidSearchException.class, () -> solrSearchDao.search(new SearchRequest()));
    assertEquals("Search query is invalid: null", e.getMessage());
  }

  @Test
  public void searchShouldThrowInvalidSearchExceptionOnEmptyClient() {
    SearchRequest searchRequest = new SearchRequest();
    searchRequest.setQuery("query");
    InvalidSearchException e = assertThrows(InvalidSearchException.class,
            () -> new SolrSearchDao(null, accessConfig).search(searchRequest));
    assertEquals("Uninitialized Dao!  You must call init() prior to use.", e.getMessage());
  }

  @Test
  public void searchShouldThrowInvalidSearchExceptionOnNullGroup() {
    GroupRequest groupRequest = mock(GroupRequest.class);

    solrSearchDao = spy(new SolrSearchDao(client, accessConfig));
    when(groupRequest.getQuery()).thenReturn("query");
    when(groupRequest.getGroups()).thenReturn(null);
    when(groupRequest.getScoreField()).thenReturn(Optional.of("scoreField"));
    when(groupRequest.getIndices()).thenReturn(Arrays.asList("bro", "snort"));

    InvalidSearchException e = assertThrows(InvalidSearchException.class, () -> solrSearchDao.group(groupRequest));
    assertEquals("At least 1 group must be provided.", e.getMessage());
    verifyNoMoreInteractions(client);
  }

  @Test
  public void searchShouldThrowInvalidSearchExceptionOnEmptyGroup() {
    GroupRequest groupRequest = mock(GroupRequest.class);

    solrSearchDao = spy(new SolrSearchDao(client, accessConfig));
    when(groupRequest.getQuery()).thenReturn("query");
    when(groupRequest.getGroups()).thenReturn(Collections.EMPTY_LIST);
    when(groupRequest.getScoreField()).thenReturn(Optional.of("scoreField"));
    when(groupRequest.getIndices()).thenReturn(Arrays.asList("bro", "snort"));

    InvalidSearchException e = assertThrows(InvalidSearchException.class, () -> solrSearchDao.group(groupRequest));
    assertEquals("At least 1 group must be provided.", e.getMessage());
    verifyNoMoreInteractions(client);
  }

  @Test
  public void searchShouldThrowSearchResultSizeException() {
    when(accessConfig.getMaxSearchResults()).thenReturn(100);
    SearchRequest searchRequest = new SearchRequest();
    searchRequest.setQuery("query");
    searchRequest.setSize(200);
    InvalidSearchException e = assertThrows(InvalidSearchException.class, () -> solrSearchDao.search(searchRequest));
    assertEquals("Search result size must be less than 100", e.getMessage());
  }

  @Test
  public void groupShouldProperlyReturnGroupResponse() throws Exception {
    GroupRequest groupRequest = mock(GroupRequest.class);
    QueryResponse queryResponse = mock(QueryResponse.class);
    GroupResponse groupResponse = mock(GroupResponse.class);

    solrSearchDao = spy(new SolrSearchDao(client, accessConfig));
    Group group1 = new Group();
    group1.setField("field1");
    Group group2 = new Group();
    group2.setField("field2");
    when(groupRequest.getQuery()).thenReturn("query");
    when(groupRequest.getGroups()).thenReturn(Arrays.asList(group1, group2));
    when(groupRequest.getScoreField()).thenReturn(Optional.of("scoreField"));
    when(groupRequest.getIndices()).thenReturn(Arrays.asList("bro", "snort"));
    when(client.query(any())).thenReturn(queryResponse);
    doReturn(groupResponse).when(solrSearchDao).buildGroupResponse(groupRequest, queryResponse);
    SolrQuery expectedSolrQuery = new SolrQuery()
        .setStart(0)
        .setRows(0)
        .setQuery("query");
    expectedSolrQuery.set("collection", "bro,snort");
    expectedSolrQuery.set("stats", true);
    expectedSolrQuery.set("stats.field", "{!tag=piv1 sum=true}scoreField");
    expectedSolrQuery.set("facet", true);
    expectedSolrQuery.set("facet.pivot", "{!stats=piv1}field1,field2");

    // Feed back an appropriate response regarding the collections
    NamedList<Object> namedList = new NamedList<>();
    namedList.add("collections", Arrays.asList("bro","snort"));
    when(client.request(any(), any())).thenReturn(namedList);

    assertEquals(groupResponse, solrSearchDao.group(groupRequest));
    verify(client).query(argThat(new SolrQueryMatcher(expectedSolrQuery)));
    verify(client).request(any(), any());
    verify(solrSearchDao).buildGroupResponse(groupRequest, queryResponse);

    verifyNoMoreInteractions(client);
  }

  @Test
  public void getLatestShouldProperlyReturnDocument() throws Exception {
    SolrDocument solrDocument = createSolrDocument("bro", 123456789L);

    solrSearchDao = spy(new SolrSearchDao(client, accessConfig));
    when(client.getById("collection", "guid")).thenReturn(solrDocument);
    Document document = SolrUtilities.toDocument(solrDocument);

    assertEquals(document, solrRetrieveLatestDao.getLatest("guid", "collection"));

    verify(client).getById("collection", "guid");
    verifyNoMoreInteractions(client);
  }

  @Test
  public void getAllLatestShouldProperlyReturnDocuments() throws Exception {
    GetRequest broRequest1 = new GetRequest("bro-1", "bro");
    GetRequest broRequest2 = new GetRequest("bro-2", "bro");
    GetRequest snortRequest1 = new GetRequest("snort-1", "snort");
    GetRequest snortRequest2 = new GetRequest("snort-2", "snort");
    SolrDocument broSolrDoc1 = createSolrDocument("bro", 12345L);
    SolrDocument broSolrDoc2 = createSolrDocument("bro", 34567L);
    SolrDocument snortSolrDoc1 = createSolrDocument("snort", 12345L);
    SolrDocument snortSolrDoc2 = createSolrDocument("snort", 67890L);
    Document broDoc1 = SolrUtilities.toDocument(broSolrDoc1);
    Document broDoc2 = SolrUtilities.toDocument(broSolrDoc2);
    Document snortDoc1 = SolrUtilities.toDocument(snortSolrDoc1);
    Document snortDoc2 = SolrUtilities.toDocument(snortSolrDoc2);

    solrSearchDao = spy(new SolrSearchDao(client, accessConfig));
    SolrDocumentList broList = new SolrDocumentList();
    broList.add(broSolrDoc1);
    broList.add(broSolrDoc2);
    SolrDocumentList snortList = new SolrDocumentList();
    snortList.add(snortSolrDoc1);
    snortList.add(snortSolrDoc2);
    when(client.getById((List<String>) org.mockito.hamcrest.MockitoHamcrest.argThat(hasItems("bro-1", "bro-2")),
        argThat(
            new ModifiableSolrParamsMatcher(new ModifiableSolrParams().set("collection", "bro")))))
        .thenReturn(broList);
    when(client.getById((List<String>) org.mockito.hamcrest.MockitoHamcrest.argThat(hasItems("snort-1", "snort-2")),
        argThat(new ModifiableSolrParamsMatcher(
            new ModifiableSolrParams().set("collection", "snort"))))).thenReturn(snortList);
    assertEquals(Arrays.asList(broDoc1, broDoc2, snortDoc1, snortDoc2), solrRetrieveLatestDao
        .getAllLatest(Arrays.asList(broRequest1, broRequest2, snortRequest1, snortRequest2)));
  }

  @Test
  public void buildSearchRequestShouldReturnSolrQuery() throws Exception {
    SearchRequest searchRequest = new SearchRequest();
    searchRequest.setIndices(Arrays.asList("bro", "snort"));
    searchRequest.setSize(5);
    searchRequest.setFrom(10);
    searchRequest.setQuery("query");
    SortField sortField = new SortField();
    sortField.setField("sortField");
    sortField.setSortOrder("ASC");
    searchRequest.setSort(Collections.singletonList(sortField));
    searchRequest.setFields(Arrays.asList("field1", "field2"));
    searchRequest.setFacetFields(Arrays.asList("facetField1", "facetField2"));

    SolrQuery exceptedSolrQuery = new SolrQuery()
        .setStart(10)
        .setRows(5)
        .setQuery("query")
        .addSort("sortField", SolrQuery.ORDER.asc)
        .addField("field1").addField("field2")
        .addFacetField("facetField1", "facetField2");
    exceptedSolrQuery.set("collection", "bro,snort");

    // Feed back an appropriate response regarding the collections
    NamedList<Object> namedList = new NamedList<>();
    namedList.add("collections", Arrays.asList("bro","snort"));
    when(client.request(any(), any())).thenReturn(namedList);

    SolrQuery solrQuery = solrSearchDao.buildSearchRequest(searchRequest, "field1,field2");
    assertThat(solrQuery, new SolrQueryMatcher(exceptedSolrQuery).asHamcrestMatcher());
  }

  @Test
  public void buildSearchResponseShouldReturnSearchResponse() {
    SearchRequest searchRequest = new SearchRequest();
    searchRequest.setFields(Collections.singletonList("id"));
    searchRequest.setFacetFields(Collections.singletonList("facetField"));
    QueryResponse queryResponse = mock(QueryResponse.class);
    SolrDocument solrDocument1 = new SolrDocument();
    solrDocument1.setField(Constants.GUID, "id1");
    solrDocument1.setField("id", "id1");
    SolrDocument solrDocument2 = new SolrDocument();
    solrDocument2.setField(Constants.GUID, "id2");
    solrDocument2.setField("id", "id2");

    solrSearchDao = spy(new SolrSearchDao(client, accessConfig));
    SolrDocumentList solrDocumentList = new SolrDocumentList();
    solrDocumentList.add(solrDocument1);
    solrDocumentList.add(solrDocument2);
    solrDocumentList.setNumFound(100);
    when(queryResponse.getResults()).thenReturn(solrDocumentList);
    SearchResult searchResult1 = new SearchResult();
    searchResult1.setId("id1");
    HashMap<String, Object> source1 = new HashMap<>();
    source1.put("id", "id1");
    searchResult1.setSource(source1);
    SearchResult searchResult2 = new SearchResult();
    searchResult2.setId("id2");
    HashMap<String, Object> source2 = new HashMap<>();
    source2.put("id", "id2");
    searchResult2.setSource(source2);
    Map<String, Map<String, Long>> facetCounts = new HashMap<String, Map<String, Long>>() {{
      put("id", new HashMap<String, Long>() {{
        put("id1", 1L);
        put("id2", 1L);
      }});
    }};
    doReturn(facetCounts).when(solrSearchDao)
        .getFacetCounts(Collections.singletonList("facetField"), queryResponse);
    SearchResponse expectedSearchResponse = new SearchResponse();
    SearchResult expectedSearchResult1 = new SearchResult();
    expectedSearchResult1.setId("id1");
    expectedSearchResult1.setSource(source1);
    SearchResult expectedSearchResult2 = new SearchResult();
    expectedSearchResult2.setId("id2");
    expectedSearchResult2.setSource(source2);

    expectedSearchResponse.setResults(Arrays.asList(expectedSearchResult1, expectedSearchResult2));
    expectedSearchResponse.setTotal(100);
    expectedSearchResponse.setFacetCounts(facetCounts);

    assertEquals(expectedSearchResponse,
        solrSearchDao.buildSearchResponse(searchRequest, queryResponse));
  }

  @Test
  public void getSearchResultShouldProperlyReturnResults() {
    SolrDocument solrDocument = mock(SolrDocument.class);

    when(solrDocument.getFieldValue(Constants.GUID)).thenReturn("guid");
    when(solrDocument.getFieldValue(Constants.SENSOR_TYPE)).thenReturn("sensorType");
    when(solrDocument.getFieldValue("field1")).thenReturn("value1");
    when(solrDocument.getFieldValue("field2")).thenReturn("value2");
    when(solrDocument.getFieldNames()).thenReturn(Arrays.asList("field1", "field2"));

    SearchResult expectedSearchResult = new SearchResult();
    expectedSearchResult.setId("guid");
    expectedSearchResult.setIndex("sensorType");
    expectedSearchResult.setSource(new HashMap<String, Object>() {{
      put("field1", "value1");
    }});

    assertEquals(expectedSearchResult, SolrUtilities.getSearchResult(solrDocument,
        Collections.singletonList("field1"), solrSearchDao.getAccessConfig().getIndexSupplier()));

    SearchResult expectedSearchResultAllFields = new SearchResult();
    expectedSearchResultAllFields.setId("guid");
    expectedSearchResultAllFields.setIndex("sensorType");
    expectedSearchResultAllFields.setSource(new HashMap<String, Object>() {{
      put("field1", "value1");
      put("field2", "value2");
    }});

    assertEquals(expectedSearchResultAllFields,
        SolrUtilities.getSearchResult(solrDocument, null, solrSearchDao.getAccessConfig().getIndexSupplier()));
  }

  @Test
  public void getFacetCountsShouldProperlyReturnFacetCounts() {
    QueryResponse queryResponse = mock(QueryResponse.class);

    FacetField facetField1 = new FacetField("field1");
    facetField1.add("value1", 1);
    facetField1.add("value2", 2);
    FacetField facetField2 = new FacetField("field2");
    facetField2.add("value3", 3);
    facetField2.add("value4", 4);
    when(queryResponse.getFacetField("field1")).thenReturn(facetField1);
    when(queryResponse.getFacetField("field2")).thenReturn(facetField2);

    Map<String, Map<String, Long>> expectedFacetCounts = new HashMap<String, Map<String, Long>>() {{
      put("field1", new HashMap<String, Long>() {{
        put("value1", 1L);
        put("value2", 2L);
      }});
      put("field2", new HashMap<String, Long>() {{
        put("value3", 3L);
        put("value4", 4L);
      }});
    }};

    assertEquals(expectedFacetCounts,
        solrSearchDao.getFacetCounts(Arrays.asList("field1", "field2"), queryResponse));
  }

  @Test
  public void buildGroupResponseShouldProperlyReturnGroupReponse() {
    GroupRequest groupRequest = mock(GroupRequest.class);
    QueryResponse queryResponse = mock(QueryResponse.class);
    NamedList namedList = mock(NamedList.class);
    List pivotFields = mock(List.class);
    List groupResults = mock(List.class);

    solrSearchDao = spy(new SolrSearchDao(client, accessConfig));
    Group group1 = new Group();
    group1.setField("field1");
    Group group2 = new Group();
    group2.setField("field2");
    when(groupRequest.getGroups()).thenReturn(Arrays.asList(group1, group2));
    when(queryResponse.getFacetPivot()).thenReturn(namedList);
    when(namedList.get("field1,field2")).thenReturn(pivotFields);
    doReturn(groupResults).when(solrSearchDao).getGroupResults(groupRequest, 0, pivotFields);

    GroupResponse groupResponse = solrSearchDao.buildGroupResponse(groupRequest, queryResponse);
    assertEquals("field1", groupResponse.getGroupedBy());
    verify(namedList).get("field1,field2");
    verify(solrSearchDao).getGroupResults(groupRequest, 0, pivotFields);

  }

  @Test
  public void getGroupResultsShouldProperlyReturnGroupResults() {
    GroupRequest groupRequest = new GroupRequest();
    Group group1 = new Group();
    group1.setField("field1");
    GroupOrder groupOrder1 = new GroupOrder();
    groupOrder1.setSortOrder("ASC");
    groupOrder1.setGroupOrderType("TERM");
    group1.setOrder(groupOrder1);
    Group group2 = new Group();
    group2.setField("field2");
    GroupOrder groupOrder2 = new GroupOrder();
    groupOrder2.setSortOrder("DESC");
    groupOrder2.setGroupOrderType("COUNT");
    group2.setOrder(groupOrder2);
    groupRequest.setGroups(Arrays.asList(group1, group2));
    groupRequest.setScoreField("score");

    PivotField level1Pivot1 = mock(PivotField.class);
    PivotField level1Pivot2 = mock(PivotField.class);
    PivotField level2Pivot1 = mock(PivotField.class);
    PivotField level2Pivot2 = mock(PivotField.class);
    FieldStatsInfo level1Pivot1FieldStatsInfo = mock(FieldStatsInfo.class);
    FieldStatsInfo level1Pivot2FieldStatsInfo = mock(FieldStatsInfo.class);
    FieldStatsInfo level2Pivot1FieldStatsInfo = mock(FieldStatsInfo.class);
    FieldStatsInfo level2Pivot2FieldStatsInfo = mock(FieldStatsInfo.class);
    List<PivotField> level1Pivots = Arrays.asList(level1Pivot1, level1Pivot2);
    List<PivotField> level2Pivots = Arrays.asList(level2Pivot1, level2Pivot2);

    when(level1Pivot1.getValue()).thenReturn("field1value1");
    when(level1Pivot1.getCount()).thenReturn(1);
    when(level1Pivot1FieldStatsInfo.getSum()).thenReturn(1.0);
    when(level1Pivot1.getFieldStatsInfo()).thenReturn(new HashMap<String, FieldStatsInfo>() {{
      put("score", level1Pivot1FieldStatsInfo);
    }});
    when(level1Pivot2.getValue()).thenReturn("field1value2");
    when(level1Pivot2.getCount()).thenReturn(2);
    when(level1Pivot2FieldStatsInfo.getSum()).thenReturn(2.0);
    when(level1Pivot2.getFieldStatsInfo()).thenReturn(new HashMap<String, FieldStatsInfo>() {{
      put("score", level1Pivot2FieldStatsInfo);
    }});
    when(level2Pivot1.getValue()).thenReturn("field2value1");
    when(level2Pivot1.getCount()).thenReturn(3);
    when(level2Pivot1FieldStatsInfo.getSum()).thenReturn(3.0);
    when(level2Pivot1.getFieldStatsInfo()).thenReturn(new HashMap<String, FieldStatsInfo>() {{
      put("score", level2Pivot1FieldStatsInfo);
    }});
    when(level2Pivot2.getValue()).thenReturn("field2value2");
    when(level2Pivot2.getCount()).thenReturn(4);
    when(level2Pivot2FieldStatsInfo.getSum()).thenReturn(4.0);
    when(level2Pivot2.getFieldStatsInfo()).thenReturn(new HashMap<String, FieldStatsInfo>() {{
      put("score", level2Pivot2FieldStatsInfo);
    }});
    when(level1Pivot1.getPivot()).thenReturn(level2Pivots);

    List<GroupResult> level1GroupResults = solrSearchDao
        .getGroupResults(groupRequest, 0, level1Pivots);

    assertEquals("field1value1", level1GroupResults.get(0).getKey());
    assertEquals(1, level1GroupResults.get(0).getTotal());
    assertEquals(1.0, level1GroupResults.get(0).getScore(), 0.00001);
    assertEquals("field2", level1GroupResults.get(0).getGroupedBy());
    assertEquals("field1value2", level1GroupResults.get(1).getKey());
    assertEquals(2, level1GroupResults.get(1).getTotal());
    assertEquals(2.0, level1GroupResults.get(1).getScore(), 0.00001);
    assertEquals("field2", level1GroupResults.get(1).getGroupedBy());
    assertEquals(0, level1GroupResults.get(1).getGroupResults().size());

    List<GroupResult> level2GroupResults = level1GroupResults.get(0).getGroupResults();
    assertEquals("field2value2", level2GroupResults.get(0).getKey());
    assertEquals(4, level2GroupResults.get(0).getTotal());
    assertEquals(4.0, level2GroupResults.get(0).getScore(), 0.00001);
    assertNull(level2GroupResults.get(0).getGroupedBy());
    assertNull(level2GroupResults.get(0).getGroupResults());
    assertEquals("field2value1", level2GroupResults.get(1).getKey());
    assertEquals(3, level2GroupResults.get(1).getTotal());
    assertEquals(3.0, level2GroupResults.get(1).getScore(), 0.00001);
    assertNull(level2GroupResults.get(1).getGroupedBy());
    assertNull(level2GroupResults.get(1).getGroupResults());
  }

  private SolrDocument createSolrDocument(String sensorType, Long timestamp) {
    SolrDocument solrDocument = new SolrDocument();
    solrDocument.addField(SolrDao.VERSION_FIELD, 1.0);
    solrDocument.addField(Constants.GUID, UUID.randomUUID().toString());
    solrDocument.addField(Constants.SENSOR_TYPE, sensorType);
    solrDocument.addField(Constants.Fields.TIMESTAMP.getName(), timestamp);
    solrDocument.addField(Constants.Fields.SRC_ADDR.getName(), "192.168.1.1");
    return solrDocument;
  }
}
