/*
 * 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.individuallending.internal.service.schedule;

import io.mifos.individuallending.api.v1.domain.caseinstance.CaseParameters;
import io.mifos.individuallending.api.v1.domain.workflow.Action;
import io.mifos.portfolio.api.v1.domain.PaymentCycle;
import io.mifos.portfolio.api.v1.domain.TermRange;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

import static io.mifos.individuallending.internal.service.Fixture.*;

/**
 * @author Myrle Krantz
 */
@RunWith(Parameterized.class)
public class ScheduledActionHelpersTest {
  private static class TestCase
  {
    final String description;
    LocalDate initialDisbursementDate;
    CaseParameters caseParameters;
    List<ScheduledAction> expectedResultContents = Collections.emptyList();
    long expectedPaymentCount;
    long expectedInterestCount;
    private LocalDate earliestActionDate;
    private LocalDate latestActionDate;

    TestCase(final String description) {
      this.description = description;
    }

    TestCase initialDisbursementDate(final LocalDate newVal) {
      this.initialDisbursementDate = newVal;
      return this;
    }

    TestCase caseParameters(final CaseParameters newVal) {
      this.caseParameters = newVal;
      return this;
    }

    TestCase expectedResultContents(final List<ScheduledAction> newVal) {
      this.expectedResultContents = newVal;
      return this;
    }

    TestCase expectedDateRangeOfSchedule(final LocalDate from, final LocalDate to) {
      this.earliestActionDate = from;
      this.latestActionDate = to;
      return this;
    }

    TestCase expectedPaymentCount(final long newVal) {
      this.expectedPaymentCount = newVal;
      return this;
    }

    TestCase expectedInterestCount(final long newVal) {
      this.expectedInterestCount = newVal;
      return this;
    }

    @Override
    public String toString() {
      return "TestCase{" +
              "description='" + description + '\'' +
              '}';
    }
  }

  @Parameterized.Parameters
  public static Collection testCases() {
    final Collection<TestCase> ret = new ArrayList<>();
    ret.add(simpleTestCase());
    ret.add(monthlyPaymentNotAlignedCase());
    ret.add(monthlyPaymentAlignedByDayCase());
    ret.add(biWeeklyPaymentAlignedByDayOfWeekCase());
    ret.add(endOfMonthLeapYearPaymentCase());
    ret.add(firstMondayQuarterlyPaymentCase());
    ret.add(lastMondayQuarterlyPaymentCase());
    ret.add(lastWeekNoDayCase());
    ret.add(yearlyPaymentCase());
    ret.add(yearlyPaymentFirstDayOfSecondMonthCase());
    ret.add(yearlyPaymentThirdMonthCase());
    return ret;
  }

  private static TestCase simpleTestCase()
  {
    final LocalDate initialDisbursementDate = LocalDate.of(2017, 1, 20);
    final Period firstRepaymentPeriod = new Period(initialDisbursementDate, 1);

    return new TestCase("simple").caseParameters(getTestCaseParameters()).initialDisbursementDate(initialDisbursementDate)
            .expectedResultContents(Collections.singletonList(scheduledInterestAction(initialDisbursementDate, 1, firstRepaymentPeriod)))
            .expectedInterestCount(2)
            .expectedPaymentCount(2)
            .expectedDateRangeOfSchedule(initialDisbursementDate, initialDisbursementDate.plusDays(2));
  }

  private static TestCase monthlyPaymentNotAlignedCase()
  {
    final LocalDate initialDisbursementDate = LocalDate.of(2017, 1, 20);
    final CaseParameters caseParameters = getTestCaseParameters();
    caseParameters.setTermRange(new TermRange(ChronoUnit.YEARS, 1));
    caseParameters.setPaymentCycle(new PaymentCycle(ChronoUnit.MONTHS, 1, null, null, null));

    return new TestCase("monthlyPaymentNotAligned")
            .caseParameters(caseParameters)
            .initialDisbursementDate(initialDisbursementDate)
            .expectedInterestCount(365)
            .expectedPaymentCount(12)
            .expectedDateRangeOfSchedule(initialDisbursementDate, initialDisbursementDate.plusDays(365));
  }

  private static TestCase monthlyPaymentAlignedByDayCase()
  {
    final LocalDate initialDisbursementDate = LocalDate.of(2017, 1, 20);
    final CaseParameters caseParameters = getTestCaseParameters();
    caseParameters.setTermRange(new TermRange(ChronoUnit.YEARS, 1));
    caseParameters.setPaymentCycle(new PaymentCycle(ChronoUnit.MONTHS, 1, 0, null, null));

    return new TestCase("monthlyPaymentAlignedByDay")
            .caseParameters(caseParameters)
            .initialDisbursementDate(initialDisbursementDate)
            .expectedResultContents(scheduledRepaymentActions(initialDisbursementDate,
                    LocalDate.of(2017, 2, 1),
                    LocalDate.of(2017, 3, 1),
                    LocalDate.of(2017, 4, 1),
                    LocalDate.of(2017, 5, 1),
                    LocalDate.of(2017, 6, 1),
                    LocalDate.of(2017, 7, 1),
                    LocalDate.of(2017, 8, 1),
                    LocalDate.of(2017, 9, 1),
                    LocalDate.of(2017, 10, 1),
                    LocalDate.of(2017, 11, 1),
                    LocalDate.of(2017, 12, 1),
                    LocalDate.of(2018, 1, 1),
                    LocalDate.of(2018, 2, 1)))
            .expectedInterestCount(377)
            .expectedPaymentCount(13)
            .expectedDateRangeOfSchedule(initialDisbursementDate, LocalDate.of(2018, 2, 1));
  }

  private static TestCase biWeeklyPaymentAlignedByDayOfWeekCase()
  {
    final LocalDate initialDisbursementDate = LocalDate.of(2017, 1, 20);
    final CaseParameters caseParameters = getTestCaseParameters();
    caseParameters.setTermRange(new TermRange(ChronoUnit.MONTHS, 3));
    caseParameters.setPaymentCycle(new PaymentCycle(ChronoUnit.WEEKS, 2, 3, null, null));


    return new TestCase("biWeeklyPaymentAlignedByDayOfWeekCase")
            .caseParameters(caseParameters)
            .initialDisbursementDate(initialDisbursementDate)
            .expectedResultContents(scheduledRepaymentActions(initialDisbursementDate,
                    LocalDate.of(2017, 2, 2),
                    LocalDate.of(2017, 2, 16),
                    LocalDate.of(2017, 3, 2),
                    LocalDate.of(2017, 3, 16),
                    LocalDate.of(2017, 3, 30),
                    LocalDate.of(2017, 4, 13),
                    LocalDate.of(2017, 4, 27)))
            .expectedInterestCount(97)
            .expectedPaymentCount(7)
            .expectedDateRangeOfSchedule(initialDisbursementDate, LocalDate.of(2018, 4, 27));
  }

  private static TestCase endOfMonthLeapYearPaymentCase()
  {
    final LocalDate initialDisbursementDate = LocalDate.of(2019, 12, 31);
    final CaseParameters caseParameters = getTestCaseParameters();
    caseParameters.setTermRange(new TermRange(ChronoUnit.YEARS, 1));
    caseParameters.setPaymentCycle(new PaymentCycle(ChronoUnit.MONTHS, 1, 31, null, null));


    return new TestCase("endOfMonthLeapYearPaymentCase")
            .caseParameters(caseParameters)
            .initialDisbursementDate(initialDisbursementDate)
            .expectedResultContents(scheduledRepaymentActions(initialDisbursementDate,
                    LocalDate.of(2020, 1, 31),
                    LocalDate.of(2020, 2, 29),
                    LocalDate.of(2020, 3, 31),
                    LocalDate.of(2020, 4, 30),
                    LocalDate.of(2020, 5, 31),
                    LocalDate.of(2020, 6, 30),
                    LocalDate.of(2020, 7, 31),
                    LocalDate.of(2020, 8, 31),
                    LocalDate.of(2020, 9, 30),
                    LocalDate.of(2020, 10, 31),
                    LocalDate.of(2020, 11, 30),
                    LocalDate.of(2020, 12, 31)))
            .expectedInterestCount(366)
            .expectedPaymentCount(12)
            .expectedDateRangeOfSchedule(initialDisbursementDate, LocalDate.of(2020, 12, 31));

  }

  private static TestCase firstMondayQuarterlyPaymentCase()
  {
    final LocalDate initialDisbursementDate = LocalDate.of(2017, 1, 1);
    final CaseParameters caseParameters = getTestCaseParameters();
    caseParameters.setTermRange(new TermRange(ChronoUnit.YEARS, 2));
    caseParameters.setPaymentCycle(new PaymentCycle(ChronoUnit.MONTHS, 3, 0, 0, null));


    return new TestCase("firstMondayQuarterlyPaymentCase")
            .caseParameters(caseParameters)
            .initialDisbursementDate(initialDisbursementDate)
            .expectedResultContents(scheduledRepaymentActions(initialDisbursementDate,
                    LocalDate.of(2017, 4, 3),
                    LocalDate.of(2017, 7, 3),
                    LocalDate.of(2017, 10, 2),
                    LocalDate.of(2018, 1, 1),
                    LocalDate.of(2018, 4, 2),
                    LocalDate.of(2018, 7, 2),
                    LocalDate.of(2018, 10, 1),
                    LocalDate.of(2019, 1, 7)))
            .expectedInterestCount(736)
            .expectedPaymentCount(8)
            .expectedDateRangeOfSchedule(initialDisbursementDate, LocalDate.of(2019, 4, 1));

  }

  private static TestCase lastMondayQuarterlyPaymentCase()
  {
    final LocalDate initialDisbursementDate = LocalDate.of(2017, 1, 1);
    final CaseParameters caseParameters = getTestCaseParameters();
    caseParameters.setTermRange(new TermRange(ChronoUnit.YEARS, 2));
    caseParameters.setPaymentCycle(new PaymentCycle(ChronoUnit.MONTHS, 3, 0, -1, null));

    return new TestCase("lastMondayQuarterlyPaymentCase")
            .caseParameters(caseParameters)
            .initialDisbursementDate(initialDisbursementDate)
            .expectedResultContents(scheduledRepaymentActions(initialDisbursementDate,
                    LocalDate.of(2017, 4, 24),
                    LocalDate.of(2017, 7, 31),
                    LocalDate.of(2017, 10, 30),
                    LocalDate.of(2018, 1, 29),
                    LocalDate.of(2018, 4, 30),
                    LocalDate.of(2018, 7, 30),
                    LocalDate.of(2018, 10, 29),
                    LocalDate.of(2019, 1, 28)))
            .expectedInterestCount(757)
            .expectedPaymentCount(8)
            .expectedDateRangeOfSchedule(initialDisbursementDate, LocalDate.of(2019, 1, 28));
  }

  private static TestCase lastWeekNoDayCase()
  {
    final LocalDate initialDisbursementDate = LocalDate.of(2017, 1, 1);
    final CaseParameters caseParameters = getTestCaseParameters();
    caseParameters.setTermRange(new TermRange(ChronoUnit.YEARS, 2));
    caseParameters.setPaymentCycle(new PaymentCycle(ChronoUnit.MONTHS, 3, null, -1, null));

    return new TestCase("lastWeekNoDayCase")
            .caseParameters(caseParameters)
            .initialDisbursementDate(initialDisbursementDate)
            .expectedResultContents(scheduledRepaymentActions(initialDisbursementDate,
                    LocalDate.of(2017, 4, 30),
                    LocalDate.of(2017, 7, 31),
                    LocalDate.of(2017, 10, 31),
                    LocalDate.of(2018, 1, 31),
                    LocalDate.of(2018, 4, 30),
                    LocalDate.of(2018, 7, 31),
                    LocalDate.of(2018, 10, 31),
                    LocalDate.of(2019, 1, 31)))
            .expectedInterestCount(760)
            .expectedPaymentCount(8)
            .expectedDateRangeOfSchedule(initialDisbursementDate, LocalDate.of(2019, 1, 31));
  }

  private static TestCase yearlyPaymentCase()
  {
    final LocalDate initialDisbursementDate = LocalDate.of(2017, 1, 5);
    final CaseParameters caseParameters = getTestCaseParameters();
    caseParameters.setTermRange(new TermRange(ChronoUnit.YEARS, 3));
    caseParameters.setPaymentCycle(new PaymentCycle(ChronoUnit.YEARS, 1, null, null, null));


    return new TestCase("yearlyPaymentCase")
            .caseParameters(caseParameters)
            .initialDisbursementDate(initialDisbursementDate)
            .expectedResultContents(scheduledRepaymentActions(initialDisbursementDate,
                    LocalDate.of(2018, 1, 5),
                    LocalDate.of(2019, 1, 5),
                    LocalDate.of(2020, 1, 5)))
            .expectedInterestCount(1095)
            .expectedPaymentCount(3)
            .expectedDateRangeOfSchedule(initialDisbursementDate, LocalDate.of(2020, 1, 5));
  }

  private static TestCase yearlyPaymentFirstDayOfSecondMonthCase()
  {
    final LocalDate initialDisbursementDate = LocalDate.of(2017, 1, 5);
    final CaseParameters caseParameters = getTestCaseParameters();
    caseParameters.setTermRange(new TermRange(ChronoUnit.YEARS, 3));
    caseParameters.setPaymentCycle(new PaymentCycle(ChronoUnit.YEARS, 1, 0, null, 1));


    return new TestCase("yearlyPaymentFirstDayOfSecondMonthCase")
            .caseParameters(caseParameters)
            .initialDisbursementDate(initialDisbursementDate)
            .expectedResultContents(scheduledRepaymentActions(initialDisbursementDate,
                    LocalDate.of(2018, 2, 1),
                    LocalDate.of(2019, 2, 1),
                    LocalDate.of(2020, 2, 1)))
            .expectedInterestCount(1122)
            .expectedPaymentCount(3)
            .expectedDateRangeOfSchedule(initialDisbursementDate, LocalDate.of(2020, 2, 1));
  }

  private static TestCase yearlyPaymentThirdMonthCase()
  {
    final LocalDate initialDisbursementDate = LocalDate.of(2017, 1, 5);
    final CaseParameters caseParameters = getTestCaseParameters();
    caseParameters.setTermRange(new TermRange(ChronoUnit.YEARS, 5));
    caseParameters.setPaymentCycle(new PaymentCycle(ChronoUnit.YEARS, 1, null, null, 2));


    return new TestCase("yearlyPaymentThirdMonthCase")
            .caseParameters(caseParameters)
            .initialDisbursementDate(initialDisbursementDate)
            .expectedResultContents(scheduledRepaymentActions(initialDisbursementDate,
                    LocalDate.of(2018, 3, 1),
                    LocalDate.of(2019, 3, 1),
                    LocalDate.of(2020, 3, 1),
                    LocalDate.of(2021, 3, 1),
                    LocalDate.of(2022, 3, 1)))
            .expectedInterestCount(1881)
            .expectedPaymentCount(5)
            .expectedDateRangeOfSchedule(initialDisbursementDate, LocalDate.of(2022, 3, 1));
  }

  private final TestCase testCase;

  public ScheduledActionHelpersTest(final TestCase testCase)
  {
    this.testCase = testCase;
  }

  @Test
  public void getScheduledActions() throws Exception {
    final List<ScheduledAction> result = ScheduledActionHelpers.getHypotheticalScheduledActions(testCase.initialDisbursementDate, testCase.caseParameters);

    final List<ScheduledAction> missingExpectedResults = testCase.expectedResultContents.stream()
        .filter(expectedResult -> !result.contains(expectedResult))
        .collect(Collectors.toList());

    Assert.assertTrue("Case " + testCase.description + " missing these expected results " + missingExpectedResults,
        missingExpectedResults.isEmpty());
    result.forEach(x -> {
      Assert.assertTrue(x.toString(), testCase.earliestActionDate.isBefore(x.getWhen()) || testCase.earliestActionDate.isEqual(x.getWhen()));
      Assert.assertTrue(x.toString(), testCase.latestActionDate.isAfter(x.getWhen()) || testCase.latestActionDate.isEqual(x.getWhen()));
    });
    Assert.assertEquals(testCase.expectedPaymentCount, countActionsByType(result, Action.ACCEPT_PAYMENT));
    Assert.assertEquals(testCase.expectedInterestCount, countActionsByType(result, Action.APPLY_INTEREST));
    Assert.assertEquals(1, countActionsByType(result, Action.APPROVE));
    Assert.assertEquals(1, countActionsByType(result, Action.CLOSE));
    result.stream().filter(scheduledAction -> !ScheduledActionHelpers.actionHasNoActionPeriod(scheduledAction.getAction()))
        .forEach(scheduledAction -> {
          Assert.assertNotNull("The action period of " + scheduledAction.toString() + " should not be null.",
              scheduledAction.getActionPeriod());
          Assert.assertNotNull("The repayment period of " + scheduledAction.toString() + " should not be null.",
              scheduledAction.getRepaymentPeriod());
        });
    Assert.assertTrue(noDuplicatesInResult(result));
    Assert.assertTrue(maximumOneInterestPerDay(result));
  }

  @Test
  public void getNextScheduledPayment() throws Exception {
    final LocalDate roughEndDate = ScheduledActionHelpers.getRoughEndDate(testCase.initialDisbursementDate, testCase.caseParameters);

    testCase.expectedResultContents.stream()
        .filter(x -> x.getAction() == Action.ACCEPT_PAYMENT)
        .forEach(expectedResultContents -> {
      final ScheduledAction nextScheduledPayment = ScheduledActionHelpers.getNextScheduledPayment(
          testCase.initialDisbursementDate,
          expectedResultContents.getWhen().minusDays(1),
          roughEndDate,
          testCase.caseParameters);
      Assert.assertEquals(expectedResultContents, nextScheduledPayment);
    });

    final ScheduledAction afterAction = ScheduledActionHelpers.getNextScheduledPayment(
        testCase.initialDisbursementDate,
        roughEndDate.plusDays(1),
        roughEndDate,
        testCase.caseParameters);

    Assert.assertNotNull(afterAction.getActionPeriod());
    Assert.assertTrue(afterAction.getActionPeriod().isLastPeriod());
  }

  private long countActionsByType(final List<ScheduledAction> scheduledActions, final Action actionToCount) {
    return scheduledActions.stream().filter(x -> x.getAction() == actionToCount).count();
  }

  private boolean maximumOneInterestPerDay(final List<ScheduledAction> result) {
    final List<LocalDate> interestDays = result.stream()
            .filter(x -> x.getAction() == Action.APPLY_INTEREST)
            .map(ScheduledAction::getWhen)
            .collect(Collectors.toList());

    final Set<LocalDate> interestDaysSet = new HashSet<>();
    interestDaysSet.addAll(interestDays);
    return (interestDays.size() == interestDaysSet.size());
  }

  private boolean noDuplicatesInResult(final List<ScheduledAction> result) {
    final Set<ScheduledAction> duplicatesRemoved = new HashSet<>();
    duplicatesRemoved.addAll(result);
    return (duplicatesRemoved.size() == result.size());
  }
}