/*
 * 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.solr.analytics;

import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.solr.JSONTestUtil;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.QueryRequest;
import org.apache.solr.client.solrj.request.UpdateRequest;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.cloud.AbstractDistribZkTestBase;
import org.apache.solr.cloud.SolrCloudTestCase;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.Utils;
import org.junit.BeforeClass;

public class SolrAnalyticsTestCase extends SolrCloudTestCase {
  private static final double DEFAULT_DELTA = .0000001;

  protected static final String COLLECTIONORALIAS = "collection1";
  protected static final int TIMEOUT = DEFAULT_TIMEOUT;
  protected static final String id = "id";

  private static UpdateRequest cloudReq;

  @BeforeClass
  public static void setupCollection() throws Exception {
    // Single-sharded core
    initCore("solrconfig-analytics.xml", "schema-analytics.xml");
    h.update("<delete><query>*:*</query></delete>");

    // Solr Cloud
    configureCluster(4)
        .addConfig("conf", configset("cloud-analytics"))
        .configure();

    CollectionAdminRequest.createCollection(COLLECTIONORALIAS, "conf", 2, 1).process(cluster.getSolrClient());
    AbstractDistribZkTestBase.waitForRecoveriesToFinish(COLLECTIONORALIAS, cluster.getSolrClient().getZkStateReader(),
        false, true, TIMEOUT);

    new UpdateRequest()
        .deleteByQuery("*:*")
        .commit(cluster.getSolrClient(), COLLECTIONORALIAS);

    cloudReq = new UpdateRequest();
  }

  protected static void cleanIndex() throws Exception {
    h.update("<delete><query>*:*</query></delete>");

    new UpdateRequest()
        .deleteByQuery("*:*")
        .commit(cluster.getSolrClient(), COLLECTIONORALIAS);
  }

  protected static void addDoc(List<String> fieldsAndValues) {
    assertU(adoc(fieldsAndValues.toArray(new String[0])));
    cloudReq.add(fieldsAndValues.toArray(new String[0]));
  }

  protected static void commitDocs() {
    assertU(commit());
    try {
      cloudReq.commit(cluster.getSolrClient(), COLLECTIONORALIAS);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    cloudReq = new UpdateRequest();
  }

  private void testResults(SolrParams params, String analyticsRequest, String... tests) {
    String coreJson = queryCoreJson(params);
    Object cloudObj = queryCloudObject(params);

    for (String test : tests) {
      if (test == null || test.length()==0) continue;
      // Single-Sharded
      String err = null;
      try {
        err = JSONTestUtil.match(coreJson, test, DEFAULT_DELTA);
      } catch (Exception e) {
        err = e.getMessage();
      } finally {
        assertNull("query failed JSON validation. test= Single-Sharded Collection" +
            "\n error=" + err +
            "\n expected =" + test +
            "\n response = " + coreJson +
            "\n analyticsRequest = " + analyticsRequest, err);
      }

      // Cloud
      err = null;
      try {
        err = JSONTestUtil.matchObj(cloudObj, test, DEFAULT_DELTA);
      } catch (Exception e) {
        err = e.getMessage();
      } finally {
        assertNull("query failed JSON validation. test= Solr Cloud Collection" +
            "\n error=" + err +
            "\n expected =" + test +
            "\n response = " + Utils.toJSONString(cloudObj) +
            "\n analyticsRequest = " + analyticsRequest, err);
      }
    }
  }

  private String queryCoreJson(SolrParams params) {
    try {
      return JQ(req(params));
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  private Object queryCloudObject(SolrParams params) {
    QueryResponse resp;
    try {
      cluster.waitForAllNodes(10);
      QueryRequest qreq = new QueryRequest(params);
      resp = qreq.process(cluster.getSolrClient(), COLLECTIONORALIAS);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    return convertDatesToStrings(resp.getResponse().asShallowMap());
  }

  protected void testAnalytics(String analyticsRequest, String... tests) throws IOException, InterruptedException, SolrServerException {
    ModifiableSolrParams params = new ModifiableSolrParams();
    params.set("q", "*:*");
    params.set("indent", "true");
    params.set("rows", "0");
    params.set("wt", "json");

    params.set("analytics", analyticsRequest);

    String[] revisedTests = Arrays.stream(tests).map( test -> "analytics_response/" + test).toArray( size -> new String[size]);
    testResults(params, analyticsRequest, revisedTests);
  }

  protected void testExpressions(Map<String, ETP> expressions) throws Exception {
    StringBuilder analyticsRequest = new StringBuilder("{ \"expressions\": {");
    String expressionsStr = expressions.entrySet()
        .stream()
        .map( entry -> '"' + entry.getKey() + "\":\"" + entry.getValue().expression + '"')
        .reduce((a,b) -> a + ',' + b)
        .orElseGet(() -> "");
    analyticsRequest.append(expressionsStr);
    analyticsRequest.append("}}");

    String results = expressions.entrySet()
        .stream()
        .map( entry -> '"' + entry.getKey() + "\":" + entry.getValue().expectedResultStr())
        .reduce((a,b) -> a + ',' + b)
        .orElseGet(() -> "");

    testAnalytics(analyticsRequest.toString(), "results=={"+results+", \"_UNORDERED_\":true}");
  }

  protected void testGrouping(String grouping,
                                Map<String, String> expressions,
                                Map<String, String> facets,
                                Map<String, List<FVP>> results,
                                boolean sortAscending) throws Exception {
    testGroupingSorted(grouping,
        expressions,
        facets,
        results,
        ", 'sort': { 'criteria' : [{'type': 'facetvalue', 'direction': '" + (sortAscending ? "ascending" : "descending") + "'}]}",
        (fvp1, fvp2) -> fvp1.facetValue.compareTo(fvp2.facetValue),
        sortAscending);
  }

  @SuppressWarnings("unchecked")
  protected void testGrouping(String grouping,
                                Map<String, String> expressions,
                                Map<String, String> facets,
                                Map<String, List<FVP>> results,
                                String sortExpression,
                                boolean sortAscending) throws Exception {
    testGroupingSorted(grouping,
        expressions,
        facets,
        results,
        ", 'sort': { 'criteria' : [{'type': 'expression', 'expression': '" + sortExpression + "', 'direction': '" + (sortAscending ? "ascending" : "descending") + "'}]}",
        (fvp1, fvp2) -> fvp1.expectedResults.get(sortExpression).compareTo(fvp2.expectedResults.get(sortExpression)),
        sortAscending);
  }

  protected void testGrouping(String grouping,
                              Map<String, String> expressions,
                              Map<String, String> facets,
                              Map<String, List<FVP>> results) throws Exception {
    testGroupingSorted(grouping,
        expressions,
        facets,
        results,
        "",
        (fvp1, fvp2) -> fvp1.compareTo(fvp2),
        true);
  }

  private void testGroupingSorted(String grouping,
                                    Map<String, String> expressions,
                                    Map<String, String> facets,
                                    Map<String, List<FVP>> results,
                                    String sort,
                                    Comparator<FVP> comparator,
                                    boolean sortAscending) throws Exception {
    StringBuilder analyticsRequest = new StringBuilder("{ \"groupings\": { \"" + grouping + "\" : { \"expressions\" : {");
    String expressionsStr = expressions.entrySet()
        .stream()
        .map( entry -> '"' + entry.getKey() + "\":\"" + entry.getValue() + '"')
        .collect(Collectors.joining(" , "));
    analyticsRequest.append(expressionsStr);
    analyticsRequest.append("}, \"facets\": {");
    String facetsStr = facets.entrySet()
        .stream()
        .map( entry -> '"' + entry.getKey() + "\":" + entry.getValue().replaceFirst("}\\s*$", sort) + "}")
        .collect(Collectors.joining(" , "));
    analyticsRequest.append(facetsStr);
    analyticsRequest.append("}}}}");

    String groupingResults = results.entrySet()
        .stream()
        .map( facet -> {
          String resultList = facet.getValue()
              .stream()
              .sorted(sortAscending ? comparator : comparator.reversed())
              .map( fvp -> fvp.toJsonResults() )
              .collect(Collectors.joining(" , "));
          return '"' + facet.getKey() + "\" : [ " + resultList + " ]";
        })
        .collect(Collectors.joining(" , "));

    testAnalytics(analyticsRequest.toString(), "groupings/" + grouping + "=={"+groupingResults+", \"_UNORDERED_\":true}");
  }

  private static String resultToJson(Object result) {
    if (result instanceof String) {
      return '"' + result.toString() + '"';
    }
    return result.toString();
  }

  /*
   * Expression Test Pair, contains the expression and the expected result
   */
  protected static class ETP {
    final String expression;
    final Object expectedResult;

    public ETP(String expression, Object expectedResult) {
      this.expression = expression;
      this.expectedResult = expectedResult;
    }

    public String expectedResultStr() {
      if (expectedResult instanceof String) {
        return '"' + expectedResult.toString() + '"';
      }
      return expectedResult.toString();
    }
  }

  /*
   * FacetValuePair, contains the expression and the expected result
   */
  @SuppressWarnings("rawtypes")
  protected static class FVP implements Comparable<FVP> {
    final private int order;
    final public String facetValue;
    final public Map<String, Comparable> expectedResults;

    public FVP(int order, String facetValue, Map<String, Comparable> expectedResults) {
      this.order = order;
      this.facetValue = facetValue;
      this.expectedResults = expectedResults;
    }

    public String toJsonResults() {
      String valueResults = expectedResults.entrySet()
          .stream()
          .map( result -> '"' + result.getKey() + "\":" + resultToJson(result.getValue()))
          .collect(Collectors.joining(" , "));
      return "{ \"value\" : \"" + facetValue + "\", \"results\": { " + valueResults + ", \"_UNORDERED_\":true } }";
    }

    @Override
    public int compareTo(FVP other) {
      return Integer.compare(order, other.order);
    }
  }

  /*
   * FacetValuePair, contains the expression and the expected result
   */
  @SuppressWarnings("rawtypes")
  protected static class PivotFVP extends FVP {
    final public String pivot;
    final public List<FVP> children;

    public PivotFVP(int order, String pivot, String facetValue, Map<String, Comparable> expectedResults) {
      super(order, facetValue, expectedResults);
      this.pivot = pivot;
      children = new ArrayList<>();
    }

    public void addChild(FVP child) {
      children.add(child);
    }
  }

  @SuppressWarnings("unchecked")
  protected static Object convertDatesToStrings(Object value) {
    if (value instanceof Date) {
      return Instant.ofEpochMilli(((Date)value).getTime()).toString();
    } else if (value instanceof Map) {
      ((Map<String,Object>)value).replaceAll( (key, obj) -> convertDatesToStrings(obj));
    } else if (value instanceof List) {
      ((List<Object>)value).replaceAll( obj -> convertDatesToStrings(obj));
    }
    return value;
  }
}
