/*
 * Copyright 2017 The Mifos Initiative.
 *
 * Licensed 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 io.mifos.portfolio;

import com.google.gson.Gson;
import io.mifos.core.api.util.NotFoundException;
import io.mifos.core.test.domain.TimeStampChecker;
import io.mifos.individuallending.api.v1.domain.product.ProductParameters;
import io.mifos.individuallending.api.v1.domain.workflow.Action;
import io.mifos.portfolio.api.v1.client.ProductAlreadyExistsException;
import io.mifos.portfolio.api.v1.client.ProductDefinitionIncomplete;
import io.mifos.portfolio.api.v1.client.ProductInUseException;
import io.mifos.portfolio.api.v1.domain.*;
import io.mifos.portfolio.api.v1.events.ChargeDefinitionEvent;
import io.mifos.portfolio.api.v1.events.EventConstants;
import org.apache.commons.lang.StringUtils;
import org.junit.Assert;
import org.junit.Test;

import java.math.BigDecimal;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author Myrle Krantz
 */
public class TestProducts extends AbstractPortfolioTest {

  @Test
  public void shouldCreateAndEnableProduct() throws InterruptedException {
    final Product product = createAdjustedProduct(x -> {});

    final Product productAsSaved = portfolioManager.getProduct(product.getIdentifier());

    Assert.assertEquals(product, productAsSaved);
    Assert.assertFalse(productAsSaved.isEnabled());

    Assert.assertFalse(portfolioManager.getProductEnabled(product.getIdentifier()));

    {
      final ProductPage productsPage = portfolioManager.getProducts(true, null, 0, 100, null, null);
      Assert.assertTrue(productsPage.getElements().contains(productAsSaved));
    }

    {
      final ProductPage productsPage = portfolioManager.getProducts(true, product.getIdentifier().substring(2, 5), 0, 100, null, null);
      Assert.assertTrue(productsPage.getElements().contains(productAsSaved));
    }

    {
      final ProductPage productsPage = portfolioManager.getProducts(false, null, 0, 100, null, null);
      Assert.assertFalse(productsPage.getElements().contains(productAsSaved));
    }

    {
      final ProductPage productsPage = portfolioManager.getProducts(false, product.getIdentifier().substring(2, 5), 0, 100, null, null);
      Assert.assertFalse(productsPage.getElements().contains(productAsSaved));
    }

    portfolioManager.enableProduct(product.getIdentifier(), true);
    Assert.assertTrue(this.eventRecorder.wait(EventConstants.PUT_PRODUCT_ENABLE, product.getIdentifier()));

    final Product productAfterEnable = portfolioManager.getProduct(product.getIdentifier());

    Assert.assertTrue(productAfterEnable.isEnabled());
    Assert.assertTrue(portfolioManager.getProductEnabled(product.getIdentifier()));

    {
      final ProductPage productsPage = portfolioManager.getProducts(false, null, 0, 100, null, null);
      Assert.assertTrue(productsPage.getElements().contains(productAsSaved));
    }

    {
      final ProductPage productsPage = portfolioManager.getProducts(false, product.getIdentifier().substring(2, 5), 0, 100, null, null);
      Assert.assertTrue(productsPage.getElements().contains(productAsSaved));
    }
  }

  @Test
  public void shouldCorrectlyOrderProducts() throws InterruptedException {

    final Product productA = createAdjustedProduct(x -> {
      x.setIdentifier("aaaaaaaa");
      x.setName("ZZZZZZZ");
    });
    final Product productZ = createAdjustedProduct(x -> {
      x.setIdentifier("zzzzzzzz");
      x.setName("AAAAAAA");
    });

    final Product productASaved = portfolioManager.getProduct(productA.getIdentifier());
    final Product productZSaved = portfolioManager.getProduct(productZ.getIdentifier());

    {
      final ProductPage productsPage = portfolioManager.getProducts(true, null, 0, 100, null, null);
      Assert.assertEquals(productZSaved, productsPage.getElements().get(0)); //Modified by ordering.
    }

    {
      final ProductPage productsPage = portfolioManager.getProducts(true, null, 0, 100, "identifier", "ASC");
      Assert.assertEquals(productASaved, productsPage.getElements().get(0)); //Alphabetic ordering by identifier
    }

    {
      final ProductPage productsPage = portfolioManager.getProducts(true, null, 0, 100, "name", "DESC");
      Assert.assertEquals(productASaved, productsPage.getElements().get(0)); //Alphabetic ordering by name. Descending.
    }
  }

  @Test
  public void badArgumentsToSortOrderAndDirectionShouldThrow() throws InterruptedException {
    try {
      portfolioManager.getProducts(true, null, 0, 100, null, "asc");
      Assert.fail("Should've thrown");
    }
    catch (final IllegalArgumentException ignored) { }

    try {
      portfolioManager.getProducts(true, null, 0, 100, null, "ACS");
      Assert.fail("Should've thrown");
    }
    catch (final IllegalArgumentException ignored) { }

    try {
      portfolioManager.getProducts(true, null, 0, 100, "non-existent-column", null);
      Assert.fail("Should've thrown");
    }
    catch (final IllegalArgumentException ignored) { }

    try {
      portfolioManager.getProducts(true, null, 0, 100, "", null);
      Assert.fail("Should've thrown");
    }
    catch (final IllegalArgumentException ignored) { }
  }

  @Test
  public void shouldCreateProductWithMaximumLengthEverything() throws InterruptedException {
    final Product product = getTestProductWithMaximumLengthEverything();
    portfolioManager.createProduct(product);

    Assert.assertTrue(this.eventRecorder.wait(EventConstants.POST_PRODUCT, product.getIdentifier()));

    final Product productAsSaved = portfolioManager.getProduct(product.getIdentifier());

    Assert.assertEquals(product, productAsSaved);

  }

  @Test
  public void shouldChangeProductAccountAssignments() throws InterruptedException {
    final Product product = createAdjustedProduct(x -> x.setAccountAssignments(Collections.emptySet()));

    //Add account assignments
    final Set<AccountAssignment> incompleteAccountAssignments = portfolioManager.getIncompleteAccountAssignments(product.getIdentifier());

    final Set<AccountAssignment> accountAssignments = incompleteAccountAssignments.stream()
            .map(x -> new AccountAssignment(x.getDesignator(), testEnvironment.generateUniqueIdentifer("account")))
            .collect(Collectors.toSet());

    product.setAccountAssignments(accountAssignments);

    TimeUnit.SECONDS.sleep(3);

    final TimeStampChecker timeStampChecker = TimeStampChecker.roughlyNow();
    portfolioManager.changeProduct(product.getIdentifier(), product);
    Assert.assertTrue(this.eventRecorder.wait(EventConstants.PUT_PRODUCT, product.getIdentifier()));

    {
      final Product productAsSaved = portfolioManager.getProduct(product.getIdentifier());

      Assert.assertEquals(product, productAsSaved);
      Assert.assertEquals(TEST_USER, productAsSaved.getLastModifiedBy());
      timeStampChecker.assertCorrect(productAsSaved.getLastModifiedOn());
    }

    //Remove account assignments
    product.setAccountAssignments(Collections.emptySet());
    portfolioManager.changeProduct(product.getIdentifier(), product);
    Assert.assertTrue(this.eventRecorder.wait(EventConstants.PUT_PRODUCT, product.getIdentifier()));

    {
      final Product productAsSaved = portfolioManager.getProduct(product.getIdentifier());

      Assert.assertEquals(product, productAsSaved);
    }
  }

  @Test
  public void shouldRemoveProductAccountAssignments() throws InterruptedException {
    final Product product = createAdjustedProduct(x -> {});

    final Set<AccountAssignment> incompleteAccountAssignments = portfolioManager.getIncompleteAccountAssignments(product.getIdentifier());
    Assert.assertTrue(incompleteAccountAssignments.isEmpty());

    product.setAccountAssignments(Collections.emptySet());
    portfolioManager.changeProduct(product.getIdentifier(), product);
    Assert.assertTrue(this.eventRecorder.wait(EventConstants.PUT_PRODUCT, product.getIdentifier()));

    final Product productAsSaved = portfolioManager.getProduct(product.getIdentifier());
    Assert.assertTrue("Account assignments should be empty, but contain: " + productAsSaved.getAccountAssignments(),
            productAsSaved.getAccountAssignments().isEmpty());
    Assert.assertEquals(product, productAsSaved);

    final Set<AccountAssignment> incompleteAccountAssignmentsAfterChange
            = portfolioManager.getIncompleteAccountAssignments(product.getIdentifier());
    Assert.assertFalse("Incomplete account assignments should not be empty, but is. (Beware the double negative.)",
            incompleteAccountAssignmentsAfterChange.isEmpty());
  }

  @Test
  public void incompleteProductDefinitionCantBeActivated() throws InterruptedException {
    final Product product = Fixture.createAdjustedProduct(x -> {});
    portfolioManager.createProduct(product);
    final ChargeDefinition chargeDefinitionContainingIncompleteAccountAssignment = new ChargeDefinition();
    chargeDefinitionContainingIncompleteAccountAssignment.setIdentifier("rando123456");
    chargeDefinitionContainingIncompleteAccountAssignment.setName("ditto12356");
    chargeDefinitionContainingIncompleteAccountAssignment.setFromAccountDesignator("not-there");
    chargeDefinitionContainingIncompleteAccountAssignment.setToAccountDesignator("not-here");
    chargeDefinitionContainingIncompleteAccountAssignment.setAmount(BigDecimal.ONE);
    chargeDefinitionContainingIncompleteAccountAssignment.setChargeMethod(ChargeDefinition.ChargeMethod.FIXED);
    chargeDefinitionContainingIncompleteAccountAssignment.setChargeAction(Action.OPEN.name());
    chargeDefinitionContainingIncompleteAccountAssignment.setDescription("who cares what the description is?");
    portfolioManager.createChargeDefinition(product.getIdentifier(), chargeDefinitionContainingIncompleteAccountAssignment);
    Assert.assertTrue(this.eventRecorder.wait(EventConstants.POST_CHARGE_DEFINITION,
            new ChargeDefinitionEvent(product.getIdentifier(), chargeDefinitionContainingIncompleteAccountAssignment.getIdentifier())));

    try {
      portfolioManager.enableProduct(product.getIdentifier(), true);
      Assert.fail("Enable should fail if product definition contains an non-existant account assignment.");
    }
    catch (ProductDefinitionIncomplete ignored) {

    }

  }

  @Test(expected = IllegalArgumentException.class)
  public void nonExistentPatternPackageShouldThrow() throws InterruptedException {
    createAdjustedProduct(product -> product.setPatternPackage("be.bop.do.wap"));
  }

  @Test(expected = ProductAlreadyExistsException.class)
  public void duplicateProductIdentifierShouldThrow() throws InterruptedException {
    createAdjustedProduct(product -> product.setIdentifier("ditto"));
    createAdjustedProduct(product -> product.setIdentifier("ditto"));
  }

  @Test
  public void shouldFailToChangeProductAfterCaseHasBeenCreated() throws InterruptedException {
    final Product product = createAndEnableProduct();

    createCase(product.getIdentifier());

    final Product slightlyChangedProduct = Fixture.createAdjustedProduct(x -> x.setDescription("changed description."));
    slightlyChangedProduct.setIdentifier(product.getIdentifier());
    try {
      portfolioManager.changeProduct(product.getIdentifier(), slightlyChangedProduct);
      Assert.fail("This should throw a ProductInUseException.");
    }
    catch (final ProductInUseException ignore) {
    }

    final Product productAsSaved = portfolioManager.getProduct(product.getIdentifier());

    Assert.assertEquals(product, productAsSaved);
    Assert.assertNotEquals(slightlyChangedProduct, productAsSaved);
    Assert.assertEquals(TEST_USER, productAsSaved.getLastModifiedBy());

    portfolioManager.enableProduct(product.getIdentifier(), false);
    Assert.assertTrue(this.eventRecorder.wait(EventConstants.PUT_PRODUCT_ENABLE, product.getIdentifier()));

    Assert.assertFalse(portfolioManager.getProductEnabled(product.getIdentifier()));
  }

  @Test(expected = ProductInUseException.class)
  public void shouldFailToDeleteProductAfterCaseHasBeenCreated() throws InterruptedException {
    final Product product = createAndEnableProduct();

    createCase(product.getIdentifier());

    portfolioManager.deleteProduct(product.getIdentifier());
  }

  @Test(expected = NotFoundException.class)
  public void shouldFailToDeleteNonExistentProduct() throws InterruptedException {
    portfolioManager.deleteProduct("habberdash");
  }

  @Test(expected = IllegalArgumentException.class)
  public void shouldFailToCreateProductDirectlyAsEnabled() throws InterruptedException {
    final Product product = Fixture.createAdjustedProduct(x -> {});
    product.setEnabled(true);
    portfolioManager.createProduct(product);
  }

  @Test
  public void shouldDeleteProduct() throws InterruptedException {
    final Product product = createAndEnableProduct();

    try {
      portfolioManager.deleteProduct(product.getIdentifier());
      Assert.fail("Product is enabled.  It shouldn't be possible to delete it.");
    }
    catch (final ProductInUseException ignored) {}

    portfolioManager.enableProduct(product.getIdentifier(), false);
    Assert.assertTrue(this.eventRecorder.wait(EventConstants.PUT_PRODUCT_ENABLE, product.getIdentifier()));

    portfolioManager.deleteProduct(product.getIdentifier());
    Assert.assertTrue(this.eventRecorder.wait(EventConstants.DELETE_PRODUCT, product.getIdentifier()));

    try {
      portfolioManager.getProduct(product.getIdentifier());
      Assert.fail("product should not be found after delete.");
    }
    catch (final NotFoundException ignored) {}
  }

  private Product getTestProductWithMaximumLengthEverything()
  {
    final Product product = new Product();
    product.setPatternPackage("io.mifos.individuallending.api.v1");
    product.setIdentifier(StringUtils.repeat("x", 8));
    product.setName(StringUtils.repeat("x", 256));
    product.setDescription(StringUtils.repeat("x", 4096));
    product.setTermRange(new TermRange(ChronoUnit.MONTHS, 12));
    product.setBalanceRange(new BalanceRange(BigDecimal.ZERO.setScale(4, BigDecimal.ROUND_UNNECESSARY), new BigDecimal(10000).setScale(4, BigDecimal.ROUND_UNNECESSARY)));
    product.setInterestRange(new InterestRange(new BigDecimal("999.98"), new BigDecimal("999.99")));
    product.setInterestBasis(InterestBasis.CURRENT_BALANCE);
    product.setCurrencyCode("XTS");
    product.setMinorCurrencyUnitDigits(4);

    final Set<AccountAssignment> accountAssignments = new HashSet<>();
    accountAssignments.add(new AccountAssignment(StringUtils.repeat("x", 32), StringUtils.repeat("x", 8)));
    product.setAccountAssignments(accountAssignments);

    final ProductParameters productParameters = new ProductParameters();

    productParameters.setMoratoriums(Collections.emptyList());
    productParameters.setMaximumDispersalCount(5);

    final Gson gson = new Gson();
    product.setParameters(gson.toJson(productParameters));
    return product;
  }
}