/*
 * 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.accounting.api.v1.domain.AccountType;
import io.mifos.accounting.api.v1.domain.Creditor;
import io.mifos.accounting.api.v1.domain.Debtor;
import io.mifos.core.api.util.ApiFactory;
import io.mifos.core.lang.DateConverter;
import io.mifos.individuallending.api.v1.domain.caseinstance.CaseParameters;
import io.mifos.individuallending.api.v1.domain.caseinstance.PlannedPayment;
import io.mifos.individuallending.api.v1.domain.product.AccountDesignators;
import io.mifos.individuallending.api.v1.domain.product.ChargeIdentifiers;
import io.mifos.individuallending.api.v1.domain.product.ChargeProportionalDesignator;
import io.mifos.individuallending.api.v1.domain.workflow.Action;
import io.mifos.individuallending.api.v1.events.IndividualLoanCommandEvent;
import io.mifos.individuallending.api.v1.events.IndividualLoanEventConstants;
import io.mifos.portfolio.api.v1.domain.*;
import io.mifos.portfolio.api.v1.events.BalanceSegmentSetEvent;
import io.mifos.portfolio.api.v1.events.ChargeDefinitionEvent;
import io.mifos.portfolio.api.v1.events.EventConstants;
import io.mifos.rhythm.spi.v1.client.BeatListener;
import io.mifos.rhythm.spi.v1.domain.BeatPublish;
import io.mifos.rhythm.spi.v1.events.BeatPublishEvent;
import org.assertj.core.util.Sets;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static io.mifos.portfolio.Fixture.MINOR_CURRENCY_UNIT_DIGITS;

/**
 * @author Myrle Krantz
 */
public class TestAccountingInteractionInLoanWorkflow extends AbstractPortfolioTest {
  private static final BigDecimal PROCESSING_FEE_AMOUNT = BigDecimal.valueOf(50_00, MINOR_CURRENCY_UNIT_DIGITS);
  private static final BigDecimal LOAN_ORIGINATION_FEE_AMOUNT = BigDecimal.valueOf(50_00, MINOR_CURRENCY_UNIT_DIGITS);
  private static final BigDecimal DISBURSEMENT_FEE_LOWER_RANGE_AMOUNT = BigDecimal.valueOf(10_00, MINOR_CURRENCY_UNIT_DIGITS);
  private static final BigDecimal DISBURSEMENT_FEE_UPPER_RANGE_AMOUNT = BigDecimal.valueOf(1_00, MINOR_CURRENCY_UNIT_DIGITS);
  private static final String DISBURSEMENT_RANGES = "disbursement_ranges";
  private static final String DISBURSEMENT_LOWER_RANGE = "smaller";
  private static final String DISBURSEMENT_UPPER_RANGE = "larger";
  private static final String UPPER_RANGE_DISBURSEMENT_FEE_ID = ChargeIdentifiers.DISBURSEMENT_FEE_ID + "2";

  private BeatListener portfolioBeatListener;

  private Product product = null;
  private Case customerCase = null;
  private TaskDefinition taskDefinition = null;
  private String customerLoanPrincipalIdentifier = null;
  private String customerLoanInterestIdentifier = null;
  private String customerLoanFeeIdentifier = null;

  private BigDecimal expectedCurrentPrincipal = BigDecimal.ZERO.setScale(MINOR_CURRENCY_UNIT_DIGITS, RoundingMode.HALF_EVEN);
  private BigDecimal interestAccrued = BigDecimal.ZERO.setScale(MINOR_CURRENCY_UNIT_DIGITS, RoundingMode.HALF_EVEN);
  private BigDecimal nonLateFees = BigDecimal.ZERO.setScale(MINOR_CURRENCY_UNIT_DIGITS, RoundingMode.HALF_EVEN);
  private BigDecimal lateFees = BigDecimal.ZERO.setScale(MINOR_CURRENCY_UNIT_DIGITS, RoundingMode.HALF_EVEN);


  @Before
  public void prepBeatListener() {
    portfolioBeatListener = new ApiFactory(logger).create(BeatListener.class, testEnvironment.serverURI());
  }

  @Test
  public void workflowTerminatingInApplicationDenial() throws InterruptedException {
    final LocalDateTime today = midnightToday();
    step1CreateProduct();
    step2CreateCase();
    step3OpenCase(today);
    step4DenyCase(today);
  }

  @Test
  public void workflowTerminatingInEarlyLoanPayoff() throws InterruptedException {
    final LocalDateTime today = midnightToday();

    step1CreateProduct();
    step2CreateCase();
    step3OpenCase(today);
    step4ApproveCase(today);
    step5Disburse(
        BigDecimal.valueOf(2_000_00, MINOR_CURRENCY_UNIT_DIGITS),
        today,
        UPPER_RANGE_DISBURSEMENT_FEE_ID, BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS));
    step6CalculateInterestAccrualAndCheckForLateness(midnightToday(), BigDecimal.ZERO);
    step7PaybackPartialAmount(
        expectedCurrentPrincipal.add(nonLateFees).add(interestAccrued),
        today,
        BigDecimal.ZERO);
    step8Close(today);
  }

  @Test
  public void workflowWithTwoUnequalDisbursals() throws InterruptedException {
    final LocalDateTime today = midnightToday();

    step1CreateProduct();
    step2CreateCase();
    step3OpenCase(today);
    step4ApproveCase(today);
    step5Disburse(
        BigDecimal.valueOf(500_00, MINOR_CURRENCY_UNIT_DIGITS),
        today,
        ChargeIdentifiers.DISBURSEMENT_FEE_ID, BigDecimal.valueOf(10_00, MINOR_CURRENCY_UNIT_DIGITS));
    step5Disburse(
        BigDecimal.valueOf(1_500_00, MINOR_CURRENCY_UNIT_DIGITS),
        today,
        UPPER_RANGE_DISBURSEMENT_FEE_ID, BigDecimal.valueOf(15_00, MINOR_CURRENCY_UNIT_DIGITS));
    step6CalculateInterestAccrualAndCheckForLateness(midnightToday(), BigDecimal.ZERO);
    step7PaybackPartialAmount(
        expectedCurrentPrincipal.add(nonLateFees).add(interestAccrued),
        today,
        BigDecimal.ZERO);
    step8Close(today);
  }

  @Test
  public void workflowWithTwoNearlyEqualRepayments() throws InterruptedException {
    final LocalDateTime today = midnightToday();

    step1CreateProduct();
    step2CreateCase();
    step3OpenCase(today);
    step4ApproveCase(today);
    step5Disburse(
        BigDecimal.valueOf(2_000_00, MINOR_CURRENCY_UNIT_DIGITS),
        today,
        UPPER_RANGE_DISBURSEMENT_FEE_ID, BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS));
    step6CalculateInterestAccrualAndCheckForLateness(midnightToday(), BigDecimal.ZERO);
    final BigDecimal repayment1 = expectedCurrentPrincipal.divide(BigDecimal.valueOf(2), BigDecimal.ROUND_HALF_EVEN);
    step7PaybackPartialAmount(
        repayment1.setScale(MINOR_CURRENCY_UNIT_DIGITS, BigDecimal.ROUND_HALF_EVEN),
        today,
        BigDecimal.ZERO);
    step7PaybackPartialAmount(expectedCurrentPrincipal, today, BigDecimal.ZERO);
    step8Close(today);
  }

  @Test
  public void workflowWithNegativePaymentSize() throws InterruptedException {
    final LocalDateTime today = midnightToday();

    step1CreateProduct();
    step2CreateCase();
    step3OpenCase(today);
    step4ApproveCase(today);
    try {
      step5Disburse(BigDecimal.valueOf(-2).setScale(MINOR_CURRENCY_UNIT_DIGITS, BigDecimal.ROUND_HALF_EVEN),
          today,
          UPPER_RANGE_DISBURSEMENT_FEE_ID, BigDecimal.ZERO.setScale(MINOR_CURRENCY_UNIT_DIGITS, BigDecimal.ROUND_HALF_EVEN));
      Assert.fail("Expected an IllegalArgumentException.");
    }
    catch (IllegalArgumentException ignored) { }
  }

  @Test
  public void workflowWithNormalRepayment() throws InterruptedException {
    final LocalDateTime today = midnightToday();

    step1CreateProduct();
    step2CreateCase();
    step3OpenCase(today);
    step4ApproveCase(today);

    final List<PlannedPayment> plannedPayments = individualLending.getPaymentScheduleForCaseStream(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        null)
        .collect(Collectors.toList());

    step5Disburse(
        BigDecimal.valueOf(2_000_00, MINOR_CURRENCY_UNIT_DIGITS),
        today,
        UPPER_RANGE_DISBURSEMENT_FEE_ID, BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS));

    int week = 0;
    final List<Payment> payments = new ArrayList<>();
    while (expectedCurrentPrincipal.compareTo(BigDecimal.ZERO) > 0) {
      logger.info("Simulating week {}. Expected current principal {}.", week, expectedCurrentPrincipal);
      step6CalculateInterestAndCheckForLatenessForWeek(today, week);
      final BigDecimal interestAccruedBeforePayment = interestAccrued;
      final BigDecimal nextRepaymentAmount = findNextRepaymentAmount(today.plusDays((week+1)*7));
      final Payment payment = step7PaybackPartialAmount(nextRepaymentAmount, today.plusDays((week + 1) * 7), BigDecimal.ZERO);
      payments.add(payment);
      final BigDecimal interestAccrual = payment.getBalanceAdjustments().remove(AccountDesignators.INTEREST_ACCRUAL); //Don't compare these with planned payment.
      final BigDecimal customerLoanInterest = payment.getBalanceAdjustments().remove(AccountDesignators.CUSTOMER_LOAN_INTEREST);
      Assert.assertEquals("week " + week, interestAccrual.negate(), customerLoanInterest);
      Assert.assertEquals("week " + week, interestAccruedBeforePayment, customerLoanInterest);
      //Assert.assertEquals("week " + week, plannedPayments.get(week+1).getPayment(), payment);
      week++;
    }

    step8Close(DateConverter.fromIsoString(plannedPayments.get(plannedPayments.size()-1).getPayment().getDate()));
  }

  @Test
  public void workflowWithOneLateRepayment() throws InterruptedException {
    final LocalDateTime today = midnightToday();

    step1CreateProduct();
    step2CreateCase();
    step3OpenCase(today);
    step4ApproveCase(today);

    final List<PlannedPayment> plannedPayments = individualLending.getPaymentScheduleForCaseStream(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        null)
        .collect(Collectors.toList());

    step5Disburse(
        BigDecimal.valueOf(2_000_00, MINOR_CURRENCY_UNIT_DIGITS),
        today,
        UPPER_RANGE_DISBURSEMENT_FEE_ID, BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS));

    int week = 0;
    final int weekOfLateRepayment = 3;
    while (expectedCurrentPrincipal.compareTo(BigDecimal.ZERO) > 0) {
      logger.info("Simulating week {}. Expected current balance {}.", week, expectedCurrentPrincipal);
      if (week == weekOfLateRepayment) {
        final BigDecimal lateFee = BigDecimal.valueOf(16_53, MINOR_CURRENCY_UNIT_DIGITS); //??? TODO: check the late fee value.
        step6CalculateInterestAndCheckForLatenessForRangeOfDays(
            today,
            (week * 7) + 1,
            (week + 1) * 7 + 2,
            8,
            lateFee);
        final BigDecimal nextRepaymentAmount = findNextRepaymentAmount(today.plusDays((week + 1) * 7 + 2));
        step7PaybackPartialAmount(nextRepaymentAmount, today.plusDays((week + 1) * 7 + 2), lateFee);
      }
      else {
        step6CalculateInterestAndCheckForLatenessForWeek(today, week);
        final BigDecimal nextRepaymentAmount = findNextRepaymentAmount(today.plusDays((week + 1) * 7));
        final Payment payment = step7PaybackPartialAmount(nextRepaymentAmount, today.plusDays((week + 1) * 7), BigDecimal.ZERO);
        final BigDecimal interestAccrual = payment.getBalanceAdjustments().remove(AccountDesignators.INTEREST_ACCRUAL); //Don't compare these with planned payment.
        final BigDecimal customerLoanInterest = payment.getBalanceAdjustments().remove(AccountDesignators.CUSTOMER_LOAN_INTEREST);
        Assert.assertEquals(interestAccrual.negate(), customerLoanInterest);
        //Assert.assertEquals(plannedPayments.get(week+1).getPayment(), payment);
      }
      week++;
    }

    step8Close(DateConverter.fromIsoString(plannedPayments.get(plannedPayments.size()-1).getPayment().getDate()));
  }

  private BigDecimal findNextRepaymentAmount(
      final LocalDateTime forDateTime) {
    final Payment nextPayment = portfolioManager.getCostComponentsForAction(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        Action.ACCEPT_PAYMENT.name(),
        null,
        null,
        DateConverter.toIsoString(forDateTime));
    final BigDecimal nextRepaymentAmount = nextPayment.getBalanceAdjustments()
        .getOrDefault(AccountDesignators.ENTRY, BigDecimal.ZERO).negate();
    Assert.assertTrue(nextRepaymentAmount.signum() != -1);
    return nextRepaymentAmount;
  }

  //Create product and set charges to fixed fees.
  private void step1CreateProduct() throws InterruptedException {
    logger.info("step1CreateProduct");
    product = createProduct();

    final BalanceSegmentSet balanceSegmentSet = new BalanceSegmentSet();
    balanceSegmentSet.setIdentifier(DISBURSEMENT_RANGES);
    balanceSegmentSet.setSegmentIdentifiers(Arrays.asList(DISBURSEMENT_LOWER_RANGE, DISBURSEMENT_UPPER_RANGE));
    balanceSegmentSet.setSegments(Arrays.asList(BigDecimal.ZERO, BigDecimal.valueOf(1_000_0000, 4)));
    portfolioManager.createBalanceSegmentSet(product.getIdentifier(), balanceSegmentSet);
    Assert.assertTrue(this.eventRecorder.wait(EventConstants.POST_BALANCE_SEGMENT_SET, new BalanceSegmentSetEvent(product.getIdentifier(), balanceSegmentSet.getIdentifier())));

    setFeeToFixedValue(product.getIdentifier(), ChargeIdentifiers.PROCESSING_FEE_ID, PROCESSING_FEE_AMOUNT);
    setFeeToFixedValue(product.getIdentifier(), ChargeIdentifiers.LOAN_ORIGINATION_FEE_ID, LOAN_ORIGINATION_FEE_AMOUNT);

    final ChargeDefinition lowerRangeDisbursementFeeChargeDefinition
        = portfolioManager.getChargeDefinition(product.getIdentifier(), ChargeIdentifiers.DISBURSEMENT_FEE_ID);
    lowerRangeDisbursementFeeChargeDefinition.setChargeMethod(ChargeDefinition.ChargeMethod.FIXED);
    lowerRangeDisbursementFeeChargeDefinition.setAmount(DISBURSEMENT_FEE_LOWER_RANGE_AMOUNT);
    lowerRangeDisbursementFeeChargeDefinition.setProportionalTo(ChargeProportionalDesignator.REQUESTED_DISBURSEMENT_DESIGNATOR.getValue());
    lowerRangeDisbursementFeeChargeDefinition.setForSegmentSet(DISBURSEMENT_RANGES);
    lowerRangeDisbursementFeeChargeDefinition.setFromSegment(DISBURSEMENT_LOWER_RANGE);
    lowerRangeDisbursementFeeChargeDefinition.setToSegment(DISBURSEMENT_LOWER_RANGE);

    portfolioManager.changeChargeDefinition(product.getIdentifier(), ChargeIdentifiers.DISBURSEMENT_FEE_ID, lowerRangeDisbursementFeeChargeDefinition);
    Assert.assertTrue(this.eventRecorder.wait(EventConstants.PUT_CHARGE_DEFINITION,
        new ChargeDefinitionEvent(product.getIdentifier(), ChargeIdentifiers.DISBURSEMENT_FEE_ID)));

    final ChargeDefinition upperRangeDisbursementFeeChargeDefinition = new ChargeDefinition();
    upperRangeDisbursementFeeChargeDefinition.setIdentifier(UPPER_RANGE_DISBURSEMENT_FEE_ID);
    upperRangeDisbursementFeeChargeDefinition.setName(UPPER_RANGE_DISBURSEMENT_FEE_ID);
    upperRangeDisbursementFeeChargeDefinition.setDescription(lowerRangeDisbursementFeeChargeDefinition.getDescription());
    upperRangeDisbursementFeeChargeDefinition.setFromAccountDesignator(lowerRangeDisbursementFeeChargeDefinition.getFromAccountDesignator());
    upperRangeDisbursementFeeChargeDefinition.setToAccountDesignator(lowerRangeDisbursementFeeChargeDefinition.getToAccountDesignator());
    upperRangeDisbursementFeeChargeDefinition.setAccrualAccountDesignator(lowerRangeDisbursementFeeChargeDefinition.getAccrualAccountDesignator());
    upperRangeDisbursementFeeChargeDefinition.setAccrueAction(lowerRangeDisbursementFeeChargeDefinition.getAccrueAction());
    upperRangeDisbursementFeeChargeDefinition.setChargeAction(lowerRangeDisbursementFeeChargeDefinition.getChargeAction());
    upperRangeDisbursementFeeChargeDefinition.setChargeMethod(ChargeDefinition.ChargeMethod.PROPORTIONAL);
    upperRangeDisbursementFeeChargeDefinition.setAmount(DISBURSEMENT_FEE_UPPER_RANGE_AMOUNT);
    upperRangeDisbursementFeeChargeDefinition.setProportionalTo(ChargeProportionalDesignator.REQUESTED_DISBURSEMENT_DESIGNATOR.getValue());
    upperRangeDisbursementFeeChargeDefinition.setForSegmentSet(DISBURSEMENT_RANGES);
    upperRangeDisbursementFeeChargeDefinition.setFromSegment(DISBURSEMENT_UPPER_RANGE);
    upperRangeDisbursementFeeChargeDefinition.setToSegment(DISBURSEMENT_UPPER_RANGE);

    portfolioManager.createChargeDefinition(product.getIdentifier(), upperRangeDisbursementFeeChargeDefinition);
    Assert.assertTrue(this.eventRecorder.wait(EventConstants.POST_CHARGE_DEFINITION,
        new ChargeDefinitionEvent(product.getIdentifier(), UPPER_RANGE_DISBURSEMENT_FEE_ID)));

    taskDefinition = createTaskDefinition(product);

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

  private void step2CreateCase() throws InterruptedException {
    logger.info("step2CreateCase");
    final CaseParameters caseParameters = Fixture.createAdjustedCaseParameters(x ->
        x.setPaymentCycle(new PaymentCycle(ChronoUnit.WEEKS, 1, null, null, null))
    );
    final String caseParametersAsString = new Gson().toJson(caseParameters);
    customerCase = createAdjustedCase(product.getIdentifier(), x -> x.setParameters(caseParametersAsString));

    checkNextActionsCorrect(product.getIdentifier(), customerCase.getIdentifier(), Action.OPEN);
  }

  //Open the case and accept a processing fee.
  private void step3OpenCase(final LocalDateTime forDateTime) throws InterruptedException {
    logger.info("step3OpenCase");
    checkCostComponentForActionCorrect(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        Action.OPEN,
        null,
        null,
        forDateTime);
    checkStateTransfer(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        Action.OPEN,
        Collections.singletonList(assignEntryToTeller()),
        IndividualLoanEventConstants.OPEN_INDIVIDUALLOAN_CASE,
        Case.State.PENDING);
    checkNextActionsCorrect(product.getIdentifier(), customerCase.getIdentifier(), Action.APPROVE, Action.DENY);
  }


  //Deny the case. Once this is done, no more actions are possible for the case.
  private void step4DenyCase(final LocalDateTime forDateTime) throws InterruptedException {
    logger.info("step4DenyCase");
    checkCostComponentForActionCorrect(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        Action.DENY,
        null,
        null, forDateTime);
    checkStateTransfer(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        Action.DENY,
        Collections.singletonList(assignEntryToTeller()),
        IndividualLoanEventConstants.DENY_INDIVIDUALLOAN_CASE,
        Case.State.CLOSED);
    checkNextActionsCorrect(product.getIdentifier(), customerCase.getIdentifier());
  }


  //Approve the case, accept a loan origination fee, and prepare to disburse the loan by earmarking the funds.
  private void step4ApproveCase(final LocalDateTime forDateTime) throws InterruptedException
  {
    logger.info("step4ApproveCase");

    markTaskExecuted(product, customerCase, taskDefinition);

    checkCostComponentForActionCorrect(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        Action.APPROVE,
        null,
        null, forDateTime);
    checkStateTransfer(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        Action.APPROVE,
        Collections.singletonList(assignEntryToTeller()),
        IndividualLoanEventConstants.APPROVE_INDIVIDUALLOAN_CASE,
        Case.State.APPROVED);
    checkNextActionsCorrect(product.getIdentifier(), customerCase.getIdentifier(), Action.DISBURSE, Action.CLOSE);

    final String customerLoanLedgerIdentifier = AccountingFixture.verifyLedgerCreation(
        ledgerManager,
        AccountingFixture.CUSTOMER_LOAN_LEDGER_IDENTIFIER,
        AccountType.ASSET);

    customerLoanPrincipalIdentifier =
        AccountingFixture.verifyAccountCreationMatchingDesignator(ledgerManager, customerLoanLedgerIdentifier, AccountDesignators.CUSTOMER_LOAN_PRINCIPAL, AccountType.ASSET);
    customerLoanInterestIdentifier =
        AccountingFixture.verifyAccountCreationMatchingDesignator(ledgerManager, customerLoanLedgerIdentifier, AccountDesignators.CUSTOMER_LOAN_INTEREST, AccountType.ASSET);
    customerLoanFeeIdentifier =
        AccountingFixture.verifyAccountCreationMatchingDesignator(ledgerManager, customerLoanLedgerIdentifier, AccountDesignators.CUSTOMER_LOAN_FEES, AccountType.ASSET);

    expectedCurrentPrincipal = BigDecimal.ZERO;
    interestAccrued = BigDecimal.ZERO;
    nonLateFees = BigDecimal.ZERO;
    lateFees = BigDecimal.ZERO;
    updateBalanceMock();
  }

  //Approve the case, accept a loan origination fee, and prepare to disburse the loan by earmarking the funds.
  private void step5Disburse(
      final BigDecimal amount,
      final LocalDateTime forDateTime,
      final String whichDisbursementFee,
      final BigDecimal disbursementFeeAmount) throws InterruptedException {
    logger.info("step5Disburse  '{}'", amount);
    checkCostComponentForActionCorrect(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        Action.DISBURSE,
        Sets.newLinkedHashSet(AccountDesignators.ENTRY, AccountDesignators.CUSTOMER_LOAN_GROUP),
        amount,
        forDateTime,
        new CostComponent(whichDisbursementFee, disbursementFeeAmount),
        new CostComponent(ChargeIdentifiers.LOAN_ORIGINATION_FEE_ID, LOAN_ORIGINATION_FEE_AMOUNT),
        new CostComponent(ChargeIdentifiers.PROCESSING_FEE_ID, PROCESSING_FEE_AMOUNT),
        new CostComponent(ChargeIdentifiers.DISBURSE_PAYMENT_ID, amount));
    checkStateTransfer(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        Action.DISBURSE,
        LocalDateTime.now(Clock.systemUTC()),
        Collections.singletonList(assignEntryToTeller()),
        amount,
        IndividualLoanEventConstants.DISBURSE_INDIVIDUALLOAN_CASE,
        midnightToday(),
        Case.State.ACTIVE);
    checkNextActionsCorrect(product.getIdentifier(), customerCase.getIdentifier(), Action.APPLY_INTEREST,
        Action.APPLY_INTEREST, Action.MARK_LATE, Action.ACCEPT_PAYMENT, Action.DISBURSE, Action.WRITE_OFF, Action.CLOSE);

    final Set<Debtor> debtors = new HashSet<>();
    debtors.add(new Debtor(customerLoanPrincipalIdentifier, amount.toPlainString()));
    debtors.add(new Debtor(customerLoanFeeIdentifier, PROCESSING_FEE_AMOUNT.add(disbursementFeeAmount).add(LOAN_ORIGINATION_FEE_AMOUNT).toPlainString()));

    final Set<Creditor> creditors = new HashSet<>();
    creditors.add(new Creditor(AccountingFixture.TELLER_ONE_ACCOUNT_IDENTIFIER, amount.toString()));
    creditors.add(new Creditor(AccountingFixture.PROCESSING_FEE_INCOME_ACCOUNT_IDENTIFIER, PROCESSING_FEE_AMOUNT.toPlainString()));
    creditors.add(new Creditor(AccountingFixture.DISBURSEMENT_FEE_INCOME_ACCOUNT_IDENTIFIER, disbursementFeeAmount.toPlainString()));
    creditors.add(new Creditor(AccountingFixture.LOAN_ORIGINATION_FEES_ACCOUNT_IDENTIFIER, LOAN_ORIGINATION_FEE_AMOUNT.toPlainString()));
    AccountingFixture.verifyTransfer(ledgerManager, debtors, creditors, product.getIdentifier(), customerCase.getIdentifier(), Action.DISBURSE);

    expectedCurrentPrincipal = expectedCurrentPrincipal.add(amount);
    interestAccrued = BigDecimal.ZERO;
    nonLateFees = nonLateFees.add(disbursementFeeAmount).add(PROCESSING_FEE_AMOUNT).add(LOAN_ORIGINATION_FEE_AMOUNT);
    lateFees = BigDecimal.ZERO;

    updateBalanceMock();
  }

  private void step6CalculateInterestAndCheckForLatenessForWeek(
      final LocalDateTime referenceDate,
      final int weekNumber) throws InterruptedException {
    step6CalculateInterestAndCheckForLatenessForRangeOfDays(
        referenceDate,
        (weekNumber * 7) + 1,
        (weekNumber + 1) * 7,
        -1,
        BigDecimal.ZERO);
  }

  private void step6CalculateInterestAndCheckForLatenessForRangeOfDays(
      final LocalDateTime referenceDate,
      final int startInclusive,
      final int endInclusive,
      final int relativeDayOfLateFee,
      final BigDecimal calculatedLateFee) throws InterruptedException {
    try {
      final LocalDateTime absoluteDayOfLateFee = referenceDate.plusDays(startInclusive + relativeDayOfLateFee);
      IntStream.rangeClosed(startInclusive, endInclusive)
          .mapToObj(referenceDate::plusDays)
          .forEach(day -> {
            try {
              if (day.equals(absoluteDayOfLateFee)) {
                step6CalculateInterestAccrualAndCheckForLateness(day, calculatedLateFee);
              }
              else {
                step6CalculateInterestAccrualAndCheckForLateness(day, BigDecimal.ZERO);
              }
            } catch (InterruptedException e) {
              throw new RuntimeException(e);
            }
          });
    }
    catch (RuntimeException e) {
      final Throwable cause = e.getCause();
      if (cause != null && cause.getClass().isAssignableFrom(InterruptedException.class))
        throw (InterruptedException)e.getCause();
      else
        throw e;
    }
  }

  //Perform daily interest calculation.
  private void step6CalculateInterestAccrualAndCheckForLateness(
      final LocalDateTime forDateTime,
      final BigDecimal calculatedLateFee) throws InterruptedException {
    logger.info("step6CalculateInterestAccrualAndCheckForLateness  '{}'", forDateTime);
    final String beatIdentifier = "alignment0";
    final String midnightTimeStamp = DateConverter.toIsoString(forDateTime);

    final BigDecimal dailyInterestRate = Fixture.INTEREST_RATE
        .divide(BigDecimal.valueOf(100), 8, BigDecimal.ROUND_HALF_EVEN)
        .divide(Fixture.ACCRUAL_PERIODS, 8, BigDecimal.ROUND_HALF_EVEN);

    final BigDecimal calculatedInterest = expectedCurrentPrincipal
        .add(interestAccrued)
        .multiply(dailyInterestRate)
        .setScale(MINOR_CURRENCY_UNIT_DIGITS, BigDecimal.ROUND_HALF_EVEN);

    logger.info("calculatedInterest '{}'", calculatedInterest);
    logger.info("calculatedLateFee '{}'", calculatedLateFee);


    checkCostComponentForActionCorrect(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        Action.APPLY_INTEREST,
        null,
        null,
        forDateTime);

    if (calculatedLateFee.compareTo(BigDecimal.ZERO) != 0) {
      checkCostComponentForActionCorrect(
          product.getIdentifier(),
          customerCase.getIdentifier(),
          Action.MARK_LATE,
          null,
          null,
          forDateTime);
    }
    final BeatPublish interestBeat = new BeatPublish(beatIdentifier, midnightTimeStamp);
    portfolioBeatListener.publishBeat(interestBeat);
    Assert.assertTrue(this.eventRecorder.wait(io.mifos.rhythm.spi.v1.events.EventConstants.POST_PUBLISHEDBEAT,
        new BeatPublishEvent(EventConstants.DESTINATION, beatIdentifier, midnightTimeStamp)));

    Assert.assertTrue(this.eventRecorder.wait(IndividualLoanEventConstants.CHECK_LATE_INDIVIDUALLOAN_CASE,
        new IndividualLoanCommandEvent(product.getIdentifier(), customerCase.getIdentifier(), midnightTimeStamp)));

    Assert.assertTrue(eventRecorder.wait(IndividualLoanEventConstants.APPLY_INTEREST_INDIVIDUALLOAN_CASE,
        new IndividualLoanCommandEvent(product.getIdentifier(), customerCase.getIdentifier(), midnightTimeStamp)));


    final Case customerCaseAfterStateChange = portfolioManager.getCase(product.getIdentifier(), customerCase.getIdentifier());
    Assert.assertEquals(customerCaseAfterStateChange.getCurrentState(), Case.State.ACTIVE.name());

    final Set<Debtor> debtors = new HashSet<>();
    debtors.add(new Debtor(
        customerLoanInterestIdentifier,
        calculatedInterest.toPlainString()));

    final Set<Creditor> creditors = new HashSet<>();
    creditors.add(new Creditor(
        AccountingFixture.LOAN_INTEREST_ACCRUAL_ACCOUNT_IDENTIFIER,
        calculatedInterest.toPlainString()));
    AccountingFixture.verifyTransfer(
        ledgerManager,
        debtors,
        creditors,
        product.getIdentifier(),
        customerCase.getIdentifier(), Action.APPLY_INTEREST);


    if (calculatedLateFee.compareTo(BigDecimal.ZERO) != 0) {
      final Set<Debtor> lateFeeDebtors = new HashSet<>();
      lateFeeDebtors.add(new Debtor(
          customerLoanFeeIdentifier,
          calculatedLateFee.toPlainString()));

      final Set<Creditor> lateFeeCreditors = new HashSet<>();
      lateFeeCreditors.add(new Creditor(
          AccountingFixture.LATE_FEE_ACCRUAL_ACCOUNT_IDENTIFIER,
          calculatedLateFee.toPlainString()));
      AccountingFixture.verifyTransfer(
          ledgerManager,
          lateFeeDebtors,
          lateFeeCreditors,
          product.getIdentifier(),
          customerCase.getIdentifier(),
          Action.MARK_LATE);
      lateFees = lateFees.add(calculatedLateFee);
    }
    interestAccrued = interestAccrued.add(calculatedInterest);

    updateBalanceMock();
    logger.info("Completed step6CalculateInterestAccrualAndCheckForLateness");
  }

  private Payment step7PaybackPartialAmount(
      final BigDecimal amount,
      final LocalDateTime forDateTime,
      final BigDecimal lateFee) throws InterruptedException {
    logger.info("step7PaybackPartialAmount '{}' '{}'", amount, forDateTime);
    final BigDecimal principal = amount.subtract(interestAccrued).subtract(lateFee.add(nonLateFees));

    final Payment payment = checkCostComponentForActionCorrect(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        Action.ACCEPT_PAYMENT,
        new HashSet<>(Arrays.asList(AccountDesignators.ENTRY, AccountDesignators.CUSTOMER_LOAN_GROUP, AccountDesignators.LOAN_FUNDS_SOURCE)),
        amount,
        forDateTime,
        new CostComponent(ChargeIdentifiers.REPAY_PRINCIPAL_ID, principal),
        new CostComponent(ChargeIdentifiers.REPAY_INTEREST_ID, interestAccrued),
        new CostComponent(ChargeIdentifiers.REPAY_FEES_ID, lateFee.add(nonLateFees)),
        new CostComponent(ChargeIdentifiers.INTEREST_ID, interestAccrued),
        new CostComponent(ChargeIdentifiers.LATE_FEE_ID, lateFee));
    checkStateTransfer(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        Action.ACCEPT_PAYMENT,
        forDateTime,
        Collections.singletonList(assignEntryToTeller()),
        amount,
        IndividualLoanEventConstants.ACCEPT_PAYMENT_INDIVIDUALLOAN_CASE,
        midnightToday(),
        Case.State.ACTIVE); //Close has to be done explicitly.
    checkNextActionsCorrect(product.getIdentifier(), customerCase.getIdentifier(), Action.APPLY_INTEREST,
        Action.APPLY_INTEREST, Action.MARK_LATE, Action.ACCEPT_PAYMENT, Action.DISBURSE, Action.WRITE_OFF, Action.CLOSE);

    final Set<Debtor> debtors = new HashSet<>();
    BigDecimal tellerOneDebit = principal;
    if (interestAccrued.compareTo(BigDecimal.ZERO) != 0) {
      tellerOneDebit = tellerOneDebit.add(interestAccrued);
      debtors.add(new Debtor(AccountingFixture.LOAN_INTEREST_ACCRUAL_ACCOUNT_IDENTIFIER, interestAccrued.toPlainString()));
    }
    if (lateFee.add(nonLateFees).compareTo(BigDecimal.ZERO) != 0) {
      tellerOneDebit = tellerOneDebit.add(lateFee.add(nonLateFees));
    }
    if (lateFee.compareTo(BigDecimal.ZERO) != 0) {
      debtors.add(new Debtor(AccountingFixture.LATE_FEE_ACCRUAL_ACCOUNT_IDENTIFIER, lateFee.toPlainString()));
    }
    debtors.add(new Debtor(AccountingFixture.TELLER_ONE_ACCOUNT_IDENTIFIER, tellerOneDebit.toPlainString()));

    final Set<Creditor> creditors = new HashSet<>();
    creditors.add(new Creditor(customerLoanPrincipalIdentifier, principal.toPlainString()));
    if (interestAccrued.compareTo(BigDecimal.ZERO) != 0) {
      creditors.add(new Creditor(customerLoanInterestIdentifier, interestAccrued.toPlainString()));
      creditors.add(new Creditor(AccountingFixture.CONSUMER_LOAN_INTEREST_ACCOUNT_IDENTIFIER, interestAccrued.toPlainString()));
    }
    if (lateFee.add(nonLateFees).compareTo(BigDecimal.ZERO) != 0) {
      creditors.add(new Creditor(customerLoanFeeIdentifier, lateFee.add(nonLateFees).toPlainString()));
    }
    if (lateFee.compareTo(BigDecimal.ZERO) != 0) {
      creditors.add(new Creditor(AccountingFixture.LATE_FEE_INCOME_ACCOUNT_IDENTIFIER, lateFee.toPlainString()));
    }

    AccountingFixture.verifyTransfer(ledgerManager, debtors, creditors, product.getIdentifier(), customerCase.getIdentifier(), Action.ACCEPT_PAYMENT);

    expectedCurrentPrincipal = expectedCurrentPrincipal.subtract(principal);
    interestAccrued = BigDecimal.ZERO.setScale(MINOR_CURRENCY_UNIT_DIGITS, RoundingMode.HALF_EVEN);
    nonLateFees = BigDecimal.ZERO.setScale(MINOR_CURRENCY_UNIT_DIGITS, RoundingMode.HALF_EVEN);
    lateFees = BigDecimal.ZERO.setScale(MINOR_CURRENCY_UNIT_DIGITS, RoundingMode.HALF_EVEN);

    updateBalanceMock();
    logger.info("Completed step7PaybackPartialAmount");
    return payment;
  }

  private void step8Close(
      final LocalDateTime forDateTime) throws InterruptedException
  {
    logger.info("step8Close");

    checkCostComponentForActionCorrect(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        Action.CLOSE,
        null,
        null,
        forDateTime);
    checkStateTransfer(
        product.getIdentifier(),
        customerCase.getIdentifier(),
        Action.CLOSE,
        Collections.singletonList(assignEntryToTeller()),
        IndividualLoanEventConstants.CLOSE_INDIVIDUALLOAN_CASE,
        Case.State.CLOSED); //Close has to be done explicitly.

    checkNextActionsCorrect(product.getIdentifier(), customerCase.getIdentifier());
  }

  private void updateBalanceMock() {
    logger.info("Updating balance mocks");
    final BigDecimal allFees = lateFees.add(nonLateFees);
    AccountingFixture.mockBalance(customerLoanPrincipalIdentifier, expectedCurrentPrincipal);
    AccountingFixture.mockBalance(customerLoanFeeIdentifier, allFees);
    AccountingFixture.mockBalance(customerLoanInterestIdentifier, interestAccrued);
    AccountingFixture.mockBalance(AccountingFixture.LOAN_INTEREST_ACCRUAL_ACCOUNT_IDENTIFIER, interestAccrued);
    AccountingFixture.mockBalance(AccountingFixture.LATE_FEE_ACCRUAL_ACCOUNT_IDENTIFIER, lateFees);
    logger.info("updated currentPrincipal '{}'", expectedCurrentPrincipal);
    logger.info("updated interestAccrued '{}'", interestAccrued);
    logger.info("updated nonLateFees '{}'", nonLateFees);
    logger.info("updated lateFees '{}'", lateFees);
  }
}