/*
 * 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.geode.cache.query.internal.aggregate;

import static org.apache.geode.test.awaitility.GeodeAwaitility.await;
import static org.assertj.core.api.Assertions.assertThat;

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import junitparams.Parameters;
import junitparams.naming.TestCaseName;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.query.Query;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.cache.query.SelectResults;
import org.apache.geode.cache.query.data.Portfolio;
import org.apache.geode.cache.query.data.PortfolioPdx;
import org.apache.geode.test.junit.categories.OQLQueryTest;

@Category(OQLQueryTest.class)
public class MinIntegrationTest extends AggregateFunctionQueryBaseIntegrationTest {
  private Map<String, Comparable> queries = new HashMap<>();
  private Map<String, Comparable> equiJoinQueries = new HashMap<>();

  public void prepareStructures() {
    Supplier<Stream<Portfolio>> supplierOne =
        () -> regionOneLocalCopy.values().stream().map(Portfolio.class::cast);
    Supplier<Stream<Portfolio>> supplierTwo =
        () -> regionTwoLocalCopy.values().stream().map(Portfolio.class::cast);

    for (int i = 1; i <= 100; i++) {
      Portfolio portfolio = new Portfolio(i);
      portfolio.shortID = (short) ((short) i / 5);
      regionOneLocalCopy.put(i, portfolio);
    }

    for (int i = 50; i <= 150; i++) {
      Portfolio portfolio = new Portfolio(i);
      portfolio.shortID = (short) ((short) i / 5);
      regionTwoLocalCopy.put(i, portfolio);
    }

    // Simple Queries
    queries.put("SELECT MIN(ID) FROM /" + firstRegionName,
        supplierOne.get().mapToInt(Portfolio::getID).min().orElse(-1));
    queries.put("SELECT MIN(ID) FROM /" + firstRegionName + " WHERE ID > 0",
        supplierOne.get().filter(p -> p.getID() > 0).mapToInt(Portfolio::getID).min().orElse(-1));
    queries.put("SELECT MIN(ID) FROM /" + firstRegionName + " WHERE ID > 0 LIMIT 50",
        supplierOne.get().filter(p -> p.getID() > 0).mapToInt(Portfolio::getID).min().orElse(-1));
    queries.put("SELECT MIN(p.getType()) FROM /" + firstRegionName
        + " p WHERE p.ID > 0 OR p.status='active'",
        supplierOne.get().filter(p -> p.getID() > 0 || p.isActive())
            .min(Comparator.comparing(Portfolio::getType)).map(Portfolio::getType).orElse(""));
    queries.put("SELECT MIN(p.getType()) FROM /" + firstRegionName
        + " p WHERE p.ID > 0 OR p.status LIKE 'ina%'",
        supplierOne.get().filter(p -> p.getID() > 0 || p.status.startsWith("ina"))
            .min(Comparator.comparing(Portfolio::getType)).map(Portfolio::getType).orElse(""));
    queries.put(
        "SELECT MIN(p.shortID) FROM /" + firstRegionName + " p WHERE p.ID IN SET(1, 2, 3, 4, 5)",
        supplierOne.get().filter(p -> Arrays.asList(1, 2, 3, 4, 5).contains(p.getID()))
            .min(Comparator.comparing(p -> p.shortID)).map(p -> p.shortID).orElse((short) -1));
    queries.put("SELECT MIN(p.shortID) FROM /" + firstRegionName + " p WHERE NOT (p.ID > 5)",
        supplierOne.get().filter(p -> p.getID() <= 5).min(Comparator.comparing(p -> p.shortID))
            .map(p -> p.shortID).orElse((short) -1));

    // StructSet queries.
    queries.put("SELECT MIN(p.ID) FROM /" + firstRegionName
        + " p, p.positions.values pos WHERE p.ID > 0 AND pos.secId = 'IBM'",
        supplierOne.get().filter(p -> p.getID() > 0 && p.getPositions().containsKey("IBM"))
            .mapToInt(Portfolio::getID).min().orElse(-1));
    queries.put("SELECT MIN(p.getType()) FROM /" + firstRegionName
        + " p, p.positions.values pos WHERE p.ID > 0 AND pos.secId = 'IBM' LIMIT 5",
        supplierOne.get().filter(p -> p.getID() > 0 && p.getPositions().containsKey("IBM"))
            .min(Comparator.comparing(Portfolio::getType)).map(Portfolio::getType).orElse(""));
    queries.put("SELECT MIN(p.status) FROM /" + firstRegionName
        + " p, p.positions.values pos WHERE p.ID > 0 AND pos.secId = 'IBM'",
        supplierOne.get().filter(p -> p.getID() > 0 && p.getPositions().containsKey("IBM"))
            .min(Comparator.comparing(p -> p.status)).map(p -> p.status).orElse(""));
    queries.put("SELECT MIN(p.shortID) FROM /" + firstRegionName
        + " p, p.positions.values pos WHERE p.ID > 0 AND p.status = 'active' AND pos.secId = 'IBM'",
        supplierOne.get()
            .filter(p -> p.getID() > 0 && p.isActive() && p.getPositions().containsKey("IBM"))
            .min(Comparator.comparing(p -> p.shortID)).map(p -> p.shortID).orElse((short) -1));
    queries.put("SELECT MIN(p.shortID) FROM /" + firstRegionName
        + " p, p.positions.values pos WHERE p.ID > 0 OR p.status IN SET ('active', 'inactive') OR pos.secId = 'IBM' LIMIT 50",
        supplierOne.get()
            .filter(p -> p.getID() > 0 || p.isActive() || !p.isActive()
                || p.getPositions().containsKey("IBM"))
            .min(Comparator.comparing(p -> p.shortID)).map(p -> p.shortID).orElse((short) -1));

    // Aggregate used as as WHERE condition within inner query.
    queries.put("SELECT MIN(p.shortID) FROM /" + firstRegionName
        + " p WHERE p.ID IN (SELECT MIN(o.ID) FROM /" + firstRegionName + " o)",
        supplierOne.get()
            .filter(p -> p.getID() == supplierOne.get().mapToInt(Portfolio::getID).min().orElse(-1))
            .min(Comparator.comparing(p -> p.shortID)).map(p -> p.shortID).orElse((short) -1));
    queries.put("SELECT MIN(p.shortID) FROM /" + firstRegionName
        + " p WHERE p.ID = ELEMENT(SELECT MAX(o.ID) FROM /" + firstRegionName + " o)",
        supplierOne.get()
            .filter(p -> p.getID() == supplierOne.get().mapToInt(Portfolio::getID).max().orElse(-1))
            .min(Comparator.comparing(p -> p.shortID)).map(p -> p.shortID).orElse((short) -1));

    // Equi Join Queries
    equiJoinQueries.put("SELECT MIN(p.shortID) from /" + firstRegionName + " p, /"
        + secondRegionName + " e WHERE p.ID = e.ID AND p.ID > 0",
        supplierOne.get().filter(p -> regionTwoLocalCopy.containsKey(p.getID()))
            .filter(p -> p.getID() > 0).min(Comparator.comparing(p -> p.shortID))
            .map(p -> p.shortID).orElse((short) -1));
    equiJoinQueries.put("SELECT MIN(p.shortID) from /" + firstRegionName + " p, /"
        + secondRegionName + " e WHERE p.ID = e.ID AND p.ID > 20 AND e.ID > 40",
        supplierOne.get()
            .filter(p -> supplierTwo.get().filter(e -> e.getID() > 40)
                .collect(Collectors.toMap(Portfolio::getID, Function.identity()))
                .containsKey(p.getID()))
            .filter(p -> p.getID() > 20).min(Comparator.comparing(p -> p.shortID))
            .map(p -> p.shortID).orElse((short) -1));
    equiJoinQueries.put("SELECT MIN(p.shortID) from /" + firstRegionName + " p, /"
        + secondRegionName + " e WHERE p.ID = e.ID AND p.ID > 0 AND p.status = 'active'",
        supplierOne.get().filter(p -> regionTwoLocalCopy.containsKey(p.getID()))
            .filter(p -> p.getID() > 0 && p.isActive()).min(Comparator.comparing(p -> p.shortID))
            .map(p -> p.shortID).orElse((short) -1));
  }

  public void prepareStructuresWithPdx() {
    Supplier<Stream<PortfolioPdx>> supplierOne =
        () -> regionOneLocalCopy.values().stream().map(PortfolioPdx.class::cast);
    Supplier<Stream<PortfolioPdx>> supplierTwo =
        () -> regionTwoLocalCopy.values().stream().map(PortfolioPdx.class::cast);

    for (int i = 1; i <= 100; i++) {
      PortfolioPdx portfolio = new PortfolioPdx(i);
      portfolio.shortID = (short) ((short) i / 5);
      regionOneLocalCopy.put(i, portfolio);
    }

    for (int i = 50; i <= 150; i++) {
      PortfolioPdx portfolio = new PortfolioPdx(i);
      portfolio.shortID = (short) ((short) i / 5);
      regionTwoLocalCopy.put(i, portfolio);
    }

    // Simple Queries
    queries.put("SELECT MIN(ID) FROM /" + firstRegionName,
        supplierOne.get().mapToInt(PortfolioPdx::getID).min().orElse(-1));
    queries.put("SELECT MIN(ID) FROM /" + firstRegionName + " WHERE ID > 0",
        supplierOne.get().filter(p -> p.getID() > 0).mapToInt(PortfolioPdx::getID).min()
            .orElse(-1));
    queries.put("SELECT MIN(ID) FROM /" + firstRegionName + " WHERE ID > 0 LIMIT 50",
        supplierOne.get().filter(p -> p.getID() > 0).mapToInt(PortfolioPdx::getID).min()
            .orElse(-1));
    queries.put("SELECT MIN(p.getType()) FROM /" + firstRegionName
        + " p WHERE p.ID > 0 OR p.status='active'",
        supplierOne.get().filter(p -> p.getID() > 0 || p.isActive())
            .min(Comparator.comparing(PortfolioPdx::getType)).map(PortfolioPdx::getType)
            .orElse(""));
    queries.put("SELECT MIN(p.getType()) FROM /" + firstRegionName
        + " p WHERE p.ID > 0 OR p.status LIKE 'ina%'",
        supplierOne.get().filter(p -> p.getID() > 0 || p.status.startsWith("ina"))
            .min(Comparator.comparing(PortfolioPdx::getType)).map(PortfolioPdx::getType)
            .orElse(""));
    queries.put(
        "SELECT MIN(p.shortID) FROM /" + firstRegionName + " p WHERE p.ID IN SET(1, 2, 3, 4, 5)",
        supplierOne.get().filter(p -> Arrays.asList(1, 2, 3, 4, 5).contains(p.getID()))
            .min(Comparator.comparing(p -> p.shortID)).map(p -> p.shortID).orElse((short) -1));
    queries.put("SELECT MIN(p.shortID) FROM /" + firstRegionName + " p WHERE NOT (p.ID > 5)",
        supplierOne.get().filter(p -> p.getID() <= 5).min(Comparator.comparing(p -> p.shortID))
            .map(p -> p.shortID).orElse((short) -1));

    // StructSet queries.
    queries.put("SELECT MIN(p.ID) FROM /" + firstRegionName
        + " p, p.positions.values pos WHERE p.ID > 0 AND pos.secId = 'IBM'",
        supplierOne.get().filter(p -> p.getID() > 0 && p.getPositions().containsKey("IBM"))
            .mapToInt(PortfolioPdx::getID).min().orElse(-1));
    queries.put("SELECT MIN(p.getType()) FROM /" + firstRegionName
        + " p, p.positions.values pos WHERE p.ID > 0 AND pos.secId = 'IBM' LIMIT 5",
        supplierOne.get().filter(p -> p.getID() > 0 && p.getPositions().containsKey("IBM"))
            .min(Comparator.comparing(PortfolioPdx::getType)).map(PortfolioPdx::getType)
            .orElse(""));
    queries.put("SELECT MIN(p.status) FROM /" + firstRegionName
        + " p, p.positions.values pos WHERE p.ID > 0 AND pos.secId = 'IBM'",
        supplierOne.get().filter(p -> p.getID() > 0 && p.getPositions().containsKey("IBM"))
            .min(Comparator.comparing(p -> p.status)).map(p -> p.status).orElse(""));
    queries.put("SELECT MIN(p.shortID) FROM /" + firstRegionName
        + " p, p.positions.values pos WHERE p.ID > 0 AND p.status = 'active' AND pos.secId = 'IBM'",
        supplierOne.get()
            .filter(p -> p.getID() > 0 && p.isActive() && p.getPositions().containsKey("IBM"))
            .min(Comparator.comparing(p -> p.shortID)).map(p -> p.shortID).orElse((short) -1));
    queries.put("SELECT MIN(p.shortID) FROM /" + firstRegionName
        + " p, p.positions.values pos WHERE p.ID > 0 OR p.status IN SET ('active', 'inactive') OR pos.secId = 'IBM' LIMIT 50",
        supplierOne.get()
            .filter(p -> p.getID() > 0 || p.isActive() || !p.isActive()
                || p.getPositions().containsKey("IBM"))
            .min(Comparator.comparing(p -> p.shortID)).map(p -> p.shortID).orElse((short) -1));

    // Aggregate used as as WHERE condition within inner query.
    queries.put("SELECT MIN(p.shortID) FROM /" + firstRegionName
        + " p WHERE p.ID IN (SELECT MIN(o.ID) FROM /" + firstRegionName + " o)",
        supplierOne.get()
            .filter(
                p -> p.getID() == supplierOne.get().mapToInt(PortfolioPdx::getID).min().orElse(-1))
            .min(Comparator.comparing(p -> p.shortID)).map(p -> p.shortID).orElse((short) -1));
    queries.put("SELECT MIN(p.shortID) FROM /" + firstRegionName
        + " p WHERE p.ID = ELEMENT(SELECT MAX(o.ID) FROM /" + firstRegionName + " o)",
        supplierOne.get()
            .filter(
                p -> p.getID() == supplierOne.get().mapToInt(PortfolioPdx::getID).max().orElse(-1))
            .min(Comparator.comparing(p -> p.shortID)).map(p -> p.shortID).orElse((short) -1));


    // Equi Join Queries
    equiJoinQueries.put("SELECT MIN(p.shortID) from /" + firstRegionName + " p, /"
        + secondRegionName + " e WHERE p.ID = e.ID AND p.ID > 0",
        supplierOne.get().filter(p -> regionTwoLocalCopy.containsKey(p.getID()))
            .filter(p -> p.getID() > 0).min(Comparator.comparing(p -> p.shortID))
            .map(p -> p.shortID).orElse((short) -1));
    equiJoinQueries.put("SELECT MIN(p.shortID) from /" + firstRegionName + " p, /"
        + secondRegionName + " e WHERE p.ID = e.ID AND p.ID > 20 AND e.ID > 40",
        supplierOne.get()
            .filter(p -> supplierTwo.get().filter(e -> e.getID() > 40)
                .collect(Collectors.toMap(PortfolioPdx::getID, Function.identity()))
                .containsKey(p.getID()))
            .filter(p -> p.getID() > 20).min(Comparator.comparing(p -> p.shortID))
            .map(p -> p.shortID).orElse((short) -1));
    equiJoinQueries.put("SELECT MIN(p.shortID) from /" + firstRegionName + " p, /"
        + secondRegionName + " e WHERE p.ID = e.ID AND p.ID > 0 AND p.status = 'active'",
        supplierOne.get().filter(p -> regionTwoLocalCopy.containsKey(p.getID()))
            .filter(p -> p.getID() > 0 && p.isActive()).min(Comparator.comparing(p -> p.shortID))
            .map(p -> p.shortID).orElse((short) -1));
  }

  public void parametrizedSetUp(boolean usePdx) {
    if (!usePdx) {
      prepareStructures();
    } else {
      prepareStructuresWithPdx();
    }
  }

  @Test
  @Parameters({
      "LOCAL, true", "LOCAL, false", "REPLICATE, true",
      "REPLICATE, false", "PARTITION, true", "PARTITION, false"
  })
  @TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1})")
  public void minShouldWorkCorrectlyOnDifferentRegionTypes(RegionShortcut regionShortcut,
      boolean usePdx) throws Exception {
    parametrizedSetUp(usePdx);
    createAndPopulateRegion(firstRegionName, regionShortcut, regionOneLocalCopy);
    QueryService queryService = server.getCache().getQueryService();

    for (String queryStr : queries.keySet()) {
      Query query = queryService.newQuery(queryStr);
      SelectResults result = (SelectResults) query.execute();
      assertThat(result.size()).isEqualTo(1);
      assertThat(result.asList().get(0)).isInstanceOf(Comparable.class);
      assertThat(result.asList().get(0))
          .as(String.format("Query %s didn't return expected results", queryStr))
          .isEqualTo(queries.get(queryStr));
    }
  }

  @Test
  @Parameters({
      "LOCAL, true", "LOCAL, false", "REPLICATE, true",
      "REPLICATE, false", "PARTITION, true", "PARTITION, false"
  })
  @TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1})")
  public void minShouldWorkCorrectlyOnDifferentRegionTypesWithIndexes(RegionShortcut regionShortcut,
      boolean usePdx) throws Exception {
    parametrizedSetUp(usePdx);
    createRegion(firstRegionName, regionShortcut);
    QueryService queryService = server.getCache().getQueryService();
    queryService.createIndex("sampleIndex-1", "p.ID", "/" + firstRegionName + " p");
    queryService.createIndex("sampleIndex-2", "p.status", "/" + firstRegionName + " p");
    queryService.createIndex("sampleIndex-3", "pos.secId",
        "/" + firstRegionName + " p, p.positions.values pos");
    await().untilAsserted(() -> assertThat(queryService.getIndexes().size()).isEqualTo(3));
    populateRegion(firstRegionName, regionOneLocalCopy);

    for (String queryStr : queries.keySet()) {
      Query query = queryService.newQuery(queryStr);
      SelectResults result = (SelectResults) query.execute();
      assertThat(result.size()).isEqualTo(1);
      assertThat(result.asList().get(0)).isInstanceOf(Comparable.class);
      assertThat(result.asList().get(0))
          .as(String.format("Query %s didn't return expected results", queryStr))
          .isEqualTo(queries.get(queryStr));
    }
  }

  @Test
  @TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1})")
  @Parameters({"LOCAL, true", "LOCAL, false", "REPLICATE, true", "REPLICATE, false"})
  public void minWithEquiJoinShouldWorkCorrectlyOnDifferentRegionTypes(
      RegionShortcut regionShortcut, boolean usePdx) throws Exception {
    parametrizedSetUp(usePdx);
    createAndPopulateRegion(firstRegionName, regionShortcut, regionOneLocalCopy);
    createAndPopulateRegion(secondRegionName, regionShortcut, regionTwoLocalCopy);
    QueryService queryService = server.getCache().getQueryService();

    for (String queryStr : equiJoinQueries.keySet()) {
      Query query = queryService.newQuery(queryStr);
      SelectResults result = (SelectResults) query.execute();
      assertThat(result.size()).isEqualTo(1);
      assertThat(result.asList().get(0)).isInstanceOf(Comparable.class);
      assertThat(result.asList().get(0))
          .as(String.format("Query %s didn't return expected results", queryStr))
          .isEqualTo(equiJoinQueries.get(queryStr));
    }
  }

  @Test
  @TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1})")
  @Parameters({"LOCAL, true", "LOCAL, false", "REPLICATE, true", "REPLICATE, false"})
  public void minWithEquiJoinShouldWorkCorrectlyOnDifferentRegionTypesWithIndexes(
      RegionShortcut regionShortcut, boolean usePdx) throws Exception {
    parametrizedSetUp(usePdx);
    createRegion(firstRegionName, regionShortcut);
    createRegion(secondRegionName, regionShortcut);
    QueryService queryService = server.getCache().getQueryService();
    queryService.createIndex("sampleIndex-1", "p.ID", "/" + firstRegionName + " p");
    queryService.createIndex("sampleIndex-2", "p.status", "/" + firstRegionName + " p");
    queryService.createIndex("sampleIndex-3", "e.ID", "/" + secondRegionName + " e");
    queryService.createIndex("sampleIndex-4", "e.status", "/" + secondRegionName + " e");
    await().untilAsserted(() -> assertThat(queryService.getIndexes().size()).isEqualTo(4));
    populateRegion(firstRegionName, regionOneLocalCopy);
    populateRegion(secondRegionName, regionTwoLocalCopy);

    for (String queryStr : equiJoinQueries.keySet()) {
      Query query = queryService.newQuery(queryStr);
      SelectResults result = (SelectResults) query.execute();
      assertThat(result.size()).isEqualTo(1);
      assertThat(result.asList().get(0)).isInstanceOf(Comparable.class);
      assertThat(result.asList().get(0))
          .as(String.format("Query %s didn't return expected results", queryStr))
          .isEqualTo(equiJoinQueries.get(queryStr));
    }
  }
}
