/*
 * 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;

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 javax.annotation.Nonnull;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author Myrle Krantz
 */
@SuppressWarnings("WeakerAccess")
public class ScheduledActionHelpers {
  public static boolean actionHasNoActionPeriod(final Action action) {
    return preTermActions().anyMatch(x -> action == x) || postTermActions().anyMatch(x -> action == x);
  }

  private static Stream<Action> preTermActions() {
    return Stream.of(Action.OPEN, Action.APPROVE, Action.DISBURSE);
  }

  private static Stream<Action> postTermActions() {
    return Stream.of(Action.CLOSE);
  }

  public static List<ScheduledAction> getHypotheticalScheduledActions(final @Nonnull LocalDate startOfTerm,
                                                        final @Nonnull CaseParameters caseParameters)
  {
    final LocalDate endOfTerm = getRoughEndDate(startOfTerm, caseParameters);
    return Stream.concat( Stream.concat(
          preTermActions().map(action -> new ScheduledAction(action, startOfTerm)),
          getHypotheticalScheduledActionsForDisbursedLoan(startOfTerm, endOfTerm, caseParameters)),
          postTermActions().map(action -> new ScheduledAction(action, endOfTerm)))
        .collect(Collectors.toList());
  }

  public static ScheduledAction getNextScheduledPayment(final @Nonnull LocalDate startOfTerm,
                                                        final @Nonnull LocalDate endOfTerm,
                                                        final @Nonnull CaseParameters caseParameters) {
    final LocalDate now = LocalDate.now(Clock.systemUTC());
    final LocalDate effectiveEndOfTerm = now.isAfter(endOfTerm) ? now : endOfTerm;

    return getHypotheticalScheduledActionsForDisbursedLoan(startOfTerm, effectiveEndOfTerm, caseParameters)
        .filter(x -> x.action.equals(Action.ACCEPT_PAYMENT))
        .filter(x -> x.actionIsOnOrAfter(now))
        .findFirst()
        .orElseGet(() -> new ScheduledAction(Action.ACCEPT_PAYMENT, now));
  }

  private static Stream<ScheduledAction> getHypotheticalScheduledActionsForDisbursedLoan(
      final @Nonnull LocalDate startOfTerm,
      final @Nonnull LocalDate endOfTerm,
      final @Nonnull CaseParameters caseParameters)
  {
    return generateRepaymentPeriods(startOfTerm, endOfTerm, caseParameters)
        .flatMap(ScheduledActionHelpers::generateScheduledActionsForRepaymentPeriod);
  }

  /** 'Rough' end date, because if the repayment period takes the last period after that end date, then the repayment
   period will 'win'.*/

  public static LocalDate getRoughEndDate(final @Nonnull LocalDate startOfTerm,
                                          final @Nonnull CaseParameters caseParameters) {
    final Integer maximumTermSize = caseParameters.getTermRange().getMaximum();
    final ChronoUnit termUnit = caseParameters.getTermRange().getTemporalUnit();

    return startOfTerm.plus(
            maximumTermSize,
            termUnit);
  }

  private static Stream<ScheduledAction> generateScheduledActionsForRepaymentPeriod(final @Nonnull Period repaymentPeriod) {
    return Stream.concat(generateScheduledInterestPaymentsForRepaymentPeriod(repaymentPeriod),
            Stream.of(new ScheduledAction(Action.ACCEPT_PAYMENT, repaymentPeriod.getEndDate(), repaymentPeriod, repaymentPeriod)));
  }

  private static Stream<ScheduledAction> generateScheduledInterestPaymentsForRepaymentPeriod(final @Nonnull Period repaymentPeriod) {
    return getInterestDayInRepaymentPeriod(repaymentPeriod).map(x ->
            new ScheduledAction(Action.APPLY_INTEREST, x, new Period(x.minus(1, ChronoUnit.DAYS), x), repaymentPeriod));
  }

  private static Stream<LocalDate> getInterestDayInRepaymentPeriod(final @Nonnull Period repaymentPeriod) {
    return Stream.iterate(repaymentPeriod.getBeginDate().plusDays(1), date -> date.plusDays(1))
            .limit(ChronoUnit.DAYS.between(repaymentPeriod.getBeginDate(), repaymentPeriod.getEndDate()));
  }

  private static Stream<Period> generateRepaymentPeriods(
          final LocalDate startOfTerm,
          final LocalDate endOfTerm,
          final CaseParameters caseParameters) {

    final List<Period> ret = new ArrayList<>();
    LocalDate lastPaymentDate = startOfTerm;
    LocalDate nextPaymentDate = generateNextPaymentDate(caseParameters, lastPaymentDate);
    while (nextPaymentDate.isBefore(endOfTerm))
    {
      final Period period = new Period(lastPaymentDate, nextPaymentDate);
      ret.add(period);
      lastPaymentDate = nextPaymentDate;
      nextPaymentDate = generateNextPaymentDate(caseParameters, lastPaymentDate);
    }
    ret.add(new Period(lastPaymentDate, nextPaymentDate));

    return ret.stream();
  }

  private static LocalDate generateNextPaymentDate(final CaseParameters caseParameters, final LocalDate lastPaymentDate) {
    final PaymentCycle paymentCycle = caseParameters.getPaymentCycle();

    final ChronoUnit maximumSpecifiedAlignmentChronoUnit =
            paymentCycle.getAlignmentMonth() != null ? ChronoUnit.MONTHS :
            paymentCycle.getAlignmentWeek() != null ? ChronoUnit.WEEKS :
            paymentCycle.getAlignmentDay() != null ? ChronoUnit.DAYS :
            ChronoUnit.HOURS;

    final ChronoUnit maximumPossibleAlignmentChronoUnit =
            paymentCycle.getTemporalUnit().equals(ChronoUnit.YEARS) ? ChronoUnit.MONTHS :
            paymentCycle.getTemporalUnit().equals(ChronoUnit.MONTHS) ? ChronoUnit.WEEKS :
            paymentCycle.getTemporalUnit().equals(ChronoUnit.WEEKS) ? ChronoUnit.DAYS :
            ChronoUnit.HOURS; //Hours as a placeholder.

    final ChronoUnit maximumAlignmentChronoUnit = min(maximumSpecifiedAlignmentChronoUnit, maximumPossibleAlignmentChronoUnit);


    final LocalDate incrementedPaymentDate = incrementPaymentDate(lastPaymentDate, paymentCycle);
    final LocalDate orientedPaymentDate = orientPaymentDate(incrementedPaymentDate, maximumSpecifiedAlignmentChronoUnit, paymentCycle);
    return alignPaymentDate(orientedPaymentDate, maximumAlignmentChronoUnit, paymentCycle);
  }

  private static LocalDate incrementPaymentDate(final LocalDate paymentDate, final PaymentCycle paymentCycle) {
    return paymentDate.plus(
        paymentCycle.getPeriod(),
        paymentCycle.getTemporalUnit());
  }

  private static LocalDate orientPaymentDate(final LocalDate paymentDate, final ChronoUnit maximumSpecifiedAlignmentChronoUnit, PaymentCycle paymentCycle) {
    if (maximumSpecifiedAlignmentChronoUnit == ChronoUnit.HOURS)
      return paymentDate; //No need to orient at all since no alignment is specified.

    switch (paymentCycle.getTemporalUnit())
    {
      case YEARS:
        return orientInYear(paymentDate);
      case MONTHS:
        return orientInMonth(paymentDate);
      case WEEKS:
        return orientInWeek(paymentDate);
      default:
      case DAYS:
        return paymentDate;
    }
  }

  private static @Nonnull ChronoUnit min(@Nonnull final ChronoUnit a, @Nonnull final ChronoUnit b) {
    if (a.getDuration().compareTo(b.getDuration()) < 0)
      return a;
    else
      return b;
  }

  private static LocalDate orientInYear(final LocalDate paymentDate) {
    return LocalDate.of(paymentDate.getYear(), 1, 1);
  }

  private static LocalDate orientInMonth(final LocalDate paymentDate) {
    return LocalDate.of(paymentDate.getYear(), paymentDate.getMonth(), 1);
  }

  private static LocalDate orientInWeek(final LocalDate paymentDate) {
    final DayOfWeek dayOfWeek = paymentDate.getDayOfWeek();
    final int dayOfWeekIndex = dayOfWeek.getValue() - 1;
    return paymentDate.minusDays(dayOfWeekIndex);
  }

  private static LocalDate alignPaymentDate(final LocalDate paymentDate, final ChronoUnit maximumAlignmentChronoUnit, final PaymentCycle paymentCycle) {
    LocalDate ret = paymentDate;
    switch (maximumAlignmentChronoUnit)
    {
      case MONTHS:
        ret = alignInMonths(ret, paymentCycle);
      case WEEKS:
        ret = alignInWeeks(ret, paymentCycle);
      case DAYS:
        ret = alignInDays(ret, paymentCycle);
      default:
      case HOURS:
        return ret;
    }
  }

  private static LocalDate alignInMonths(final LocalDate paymentDate, final PaymentCycle paymentCycle) {
    final Integer alignmentMonth = paymentCycle.getAlignmentMonth();
    if (alignmentMonth == null)
      return paymentDate;

    return paymentDate.plusMonths(alignmentMonth);
  }

  private static LocalDate alignInWeeks(final LocalDate paymentDate, final PaymentCycle paymentCycle) {
    final Integer alignmentWeek = paymentCycle.getAlignmentWeek();
    if (alignmentWeek == null)
      return paymentDate;
    if ((alignmentWeek == 0) || (alignmentWeek == 1) || (alignmentWeek == 2))
      return paymentDate.plusWeeks(alignmentWeek);
    if (alignmentWeek == -1)
    {
      final LocalDate lastDayOfMonth = YearMonth.of(paymentDate.getYear(), paymentDate.getMonth()).atEndOfMonth();
      int dayOfWeek = lastDayOfMonth.getDayOfWeek().getValue() - 1;
      if (paymentCycle.getAlignmentDay() == null || dayOfWeek == paymentCycle.getAlignmentDay()) {
        return lastDayOfMonth;
      }
      else
        return lastDayOfMonth.minus(7, ChronoUnit.DAYS); //Will align days in next step.
    }

    throw new IllegalStateException("PaymentCycle.alignmentWeek should only ever be 0, 1, 2, or -1.");
  }

  static private LocalDate alignInDays(final LocalDate paymentDate, final PaymentCycle paymentCycle) {
    final Integer alignmentDay = paymentCycle.getAlignmentDay();
    if (alignmentDay == null)
      return paymentDate;

    if ((paymentCycle.getAlignmentWeek() != null) || (paymentCycle.getTemporalUnit() == ChronoUnit.WEEKS))
      return alignInDaysOfWeek(paymentDate, alignmentDay);
    else
      return alignInDaysOfMonth(paymentDate, alignmentDay);
  }

  static private LocalDate alignInDaysOfWeek(final LocalDate paymentDate, final Integer alignmentDay) {
    final int dayOfWeek = paymentDate.getDayOfWeek().getValue()-1;

    if (dayOfWeek < alignmentDay)
      return paymentDate.plusDays(alignmentDay - dayOfWeek);
    else if (dayOfWeek > alignmentDay)
      return paymentDate.plusDays(7 - (dayOfWeek - alignmentDay));
    else
      return paymentDate;
  }

  private static LocalDate alignInDaysOfMonth(final LocalDate paymentDate, final Integer alignmentDay) {
    final int maxDay = YearMonth.of(paymentDate.getYear(), paymentDate.getMonth()).lengthOfMonth()-1;
    return paymentDate.plusDays(Math.min(maxDay, alignmentDay));
  }

  public static Optional<Duration> getAccrualPeriodDurationForAction(final Action action) {
    if (action == Action.APPLY_INTEREST)
      return Optional.of(ChronoUnit.DAYS.getDuration());
    else
      return Optional.empty();
  }
}