/*
 * 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.management.internal.cli.commands;

import static org.apache.geode.cache.Region.SEPARATOR;
import static org.assertj.core.api.Assertions.assertThat;

import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import org.apache.geode.cache.Cache;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.configuration.CacheConfig;
import org.apache.geode.cache.configuration.RegionConfig;
import org.apache.geode.distributed.internal.InternalConfigurationPersistenceService;
import org.apache.geode.test.dunit.IgnoredException;
import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.dunit.rules.MemberVM;
import org.apache.geode.test.junit.assertions.CommandResultAssert;
import org.apache.geode.test.junit.assertions.TabularResultModelAssert;
import org.apache.geode.test.junit.categories.OQLIndexTest;
import org.apache.geode.test.junit.rules.GfshCommandRule;


@Category({OQLIndexTest.class})
public class CreateIndexCommandDUnitTest {

  @ClassRule
  public static ClusterStartupRule cluster = new ClusterStartupRule();

  @ClassRule
  public static GfshCommandRule gfsh = new GfshCommandRule();

  private static MemberVM locator, server1, server2;

  @BeforeClass
  public static void beforeClass() throws Exception {
    locator = cluster.startLocatorVM(0);
    server1 = cluster.startServerVM(1, locator.getPort());
    server2 = cluster.startServerVM(2, "group2", locator.getPort());
    gfsh.connectAndVerify(locator);

    // create a region on server-2 in group 2
    gfsh.executeAndAssertThat("create region --name=regionB --group=group2 --type=REPLICATE")
        .statusIsSuccess();
    locator.waitUntilRegionIsReadyOnExactlyThisManyServers(SEPARATOR + "regionB", 1);

    // cache config in cluster group is null
    locator.invoke(() -> {
      CacheConfig cacheConfig = ClusterStartupRule.getLocator().getConfigurationPersistenceService()
          .getCacheConfig("cluster");
      assertThat(cacheConfig).isNull();
    });
  }

  @Test
  public void createIndexOnSubRegion() throws Exception {
    gfsh.executeAndAssertThat(
        "create region --name=regionB" + SEPARATOR + "child --group=group2 --type=REPLICATE")
        .statusIsSuccess();

    // make sure index on sub region can be created successfully
    CommandResultAssert commandResultAssert =
        gfsh.executeAndAssertThat(
            "create index --name=childIndex --region='" + SEPARATOR + "regionB" + SEPARATOR
                + "child c' --expression=id")
            .statusIsSuccess();
    commandResultAssert.hasTableSection()
        .hasColumn("Message")
        .containsExactly("Index successfully created");
    commandResultAssert.hasInfoSection("groupStatus")
        .hasOutput().isEqualTo("Cluster configuration for group 'group2' is updated.");

    // make sure cluster config is updated correctly
    locator.invoke(() -> {
      InternalConfigurationPersistenceService configurationService =
          ClusterStartupRule.getLocator().getConfigurationPersistenceService();
      CacheConfig cacheConfig = configurationService.getCacheConfig("group2");
      assertThat(cacheConfig.getRegions()).extracting(RegionConfig::getName)
          .containsExactly("regionB");

      RegionConfig regionB = cacheConfig.getRegions().get(0);
      assertThat(regionB.getRegions()).extracting(RegionConfig::getName)
          .containsExactly("child");

      assertThat(regionB.getRegions().get(0).getRegions()).isEmpty();
    });
  }

  @Test
  // index can't be created on region name with ".".
  // GEODE-7523
  public void createIndexOnRegionNameWithDot() throws Exception {
    gfsh.executeAndAssertThat("create region --name=A.B --type=REPLICATE")
        .statusIsSuccess();
    gfsh.executeAndAssertThat("create index --name=indexWithDot --region=A.B --expression=id")
        .statusIsError().containsOutput("Region A does not exist");
  }

  @Test
  public void regionNotExistInClusterConfig() {
    gfsh.executeAndAssertThat(
        "create index --name=myIndex --expression=id --region=" + SEPARATOR + "noExist")
        .statusIsError()
        .hasInfoSection()
        .hasOutput().contains("Region noExist does not exist");
  }

  @Test
  public void regionNotExistInThatMember() throws Exception {
    gfsh.executeAndAssertThat(
        "create index --name=myIndex --expression=id --region=" + SEPARATOR
            + "regionB --member=server-1")
        .statusIsError()
        .hasTableSection()
        .hasRowSize(1)
        .hasRow(0)
        .contains("ERROR", "Region not found : \"" + SEPARATOR + "regionB\"");
  }

  @Test
  public void regionExistOnServerButNotInClusterConfig() {
    IgnoredException.addIgnoredException(
        "org.apache.geode.management.internal.exceptions.EntityNotFoundException");
    server1.invoke(() -> {
      Cache cache = ClusterStartupRule.getCache();
      cache.createRegionFactory(RegionShortcut.REPLICATE).create("regionA");
    });

    // regionA does not exist as far as cluster configuration is concerned
    gfsh.executeAndAssertThat("create index --name=myIndex --expression=id --region=regionA")
        .statusIsError()
        .hasInfoSection()
        .hasOutput().contains("Region regionA does not exist");

    // you can only create index on regionA when specifying a --member option
    gfsh.executeAndAssertThat(
        "create index --name=myIndex --expression=id --region=regionA --member=server-1")
        .statusIsSuccess()
        .hasTableSection()
        .hasRowSize(1)
        .hasRow(0)
        .contains("OK", "Index successfully created");

    // after index is created, the cluster config is not updated with regionA nor index
    locator.invoke(() -> {
      InternalConfigurationPersistenceService configurationService =
          ClusterStartupRule.getLocator().getConfigurationPersistenceService();
      assertThat(
          configurationService.getCacheConfig("cluster", true).findRegionConfiguration("regionA"))
              .isNull();
    });
  }

  @Test
  public void regionExistInGroup2ClusterConfig() {
    locator.invoke(() -> {
      InternalConfigurationPersistenceService configurationService =
          ClusterStartupRule.getLocator().getConfigurationPersistenceService();
      assertThat(configurationService.getConfiguration("group2").getCacheXmlContent())
          .contains("<region name=\"regionB\"");
    });

    // make sure index is created on server-2 (which is only in group-2)
    CommandResultAssert commandAssert =
        gfsh.executeAndAssertThat("create index --name=myIndex --expression=id --region=regionB")
            .statusIsSuccess();
    TabularResultModelAssert createIndexTableAssert =
        commandAssert.hasTableSection("createIndex");
    createIndexTableAssert.hasRowSize(1).hasRow(0).contains("OK", "Index successfully created");
    createIndexTableAssert.hasColumn("Member").asList().first().toString().contains("server-2");
    commandAssert.containsOutput("Cluster configuration for group 'group2' is updated.");

    // make sure index is inserted in group2's cluster configuration
    locator.invoke(() -> {
      InternalConfigurationPersistenceService configurationService =
          ClusterStartupRule.getLocator().getConfigurationPersistenceService();
      assertThat(configurationService.getConfiguration("group2").getCacheXmlContent())
          .contains("<region name=\"regionB\"").contains("<index").contains("expression=\"id\" ")
          .contains("from-clause=\"" + SEPARATOR + "regionB\"").contains("name=\"myIndex\"")
          .contains("type=\"range\"");
    });
  }

  @Test
  public void regionExistInClusterConfigButDifferentGroup() {
    // regionB is only in group2, not in group1
    CommandResultAssert commandAssert =
        gfsh.executeAndAssertThat(
            "create index --name=index2 --expression=key --region=regionB --group=group1")
            .statusIsError();

    commandAssert.hasInfoSection().hasOutput()
        .contains("Region regionB does not exist in some of the groups.");
  }
}
