/*
 * 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.command.handler;


import io.mifos.core.api.util.UserContextHolder;
import io.mifos.core.command.annotation.Aggregate;
import io.mifos.core.command.annotation.CommandHandler;
import io.mifos.core.command.annotation.CommandLogLevel;
import io.mifos.core.command.annotation.EventEmitter;
import io.mifos.core.lang.DateConverter;
import io.mifos.core.lang.ServiceException;
import io.mifos.individuallending.IndividualLendingPatternFactory;
import io.mifos.individuallending.api.v1.domain.product.AccountDesignators;
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.individuallending.internal.command.*;
import io.mifos.individuallending.internal.repository.CaseParametersRepository;
import io.mifos.individuallending.internal.service.DataContextOfAction;
import io.mifos.individuallending.internal.service.DataContextService;
import io.mifos.individuallending.internal.service.DesignatorToAccountIdentifierMapper;
import io.mifos.individuallending.internal.service.costcomponent.*;
import io.mifos.individuallending.internal.service.schedule.ScheduledActionHelpers;
import io.mifos.portfolio.api.v1.domain.AccountAssignment;
import io.mifos.portfolio.api.v1.domain.Case;
import io.mifos.portfolio.api.v1.domain.CostComponent;
import io.mifos.portfolio.api.v1.events.EventConstants;
import io.mifos.portfolio.service.internal.mapper.CaseMapper;
import io.mifos.portfolio.service.internal.repository.*;
import io.mifos.portfolio.service.internal.util.AccountingAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Nullable;
import java.math.BigDecimal;
import java.time.Clock;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author Myrle Krantz
 */
@SuppressWarnings("unused")
@Aggregate
public class IndividualLoanCommandHandler {
  private final CaseRepository caseRepository;
  private final DataContextService dataContextService;
  private final OpenPaymentBuilderService openPaymentBuilderService;
  private final ApprovePaymentBuilderService approvePaymentBuilderService;
  private final DenyPaymentBuilderService denyPaymentBuilderService;
  private final DisbursePaymentBuilderService disbursePaymentBuilderService;
  private final ApplyInterestPaymentBuilderService applyInterestPaymentBuilderService;
  private final AcceptPaymentBuilderService acceptPaymentBuilderService;
  private final ClosePaymentBuilderService closePaymentBuilderService;
  private final MarkLatePaymentBuilderService markLatePaymentBuilderService;
  private final WriteOffPaymentBuilderService writeOffPaymentBuilderService;
  private final RecoverPaymentBuilderService recoverPaymentBuilderService;
  private final AccountingAdapter accountingAdapter;
  private final CaseCommandRepository caseCommandRepository;
  private final TaskInstanceRepository taskInstanceRepository;
  private final CaseParametersRepository caseParametersRepository;

  @Autowired
  public IndividualLoanCommandHandler(
      final CaseRepository caseRepository,
      final DataContextService dataContextService,
      final OpenPaymentBuilderService openPaymentBuilderService,
      final ApprovePaymentBuilderService approvePaymentBuilderService,
      final DenyPaymentBuilderService denyPaymentBuilderService,
      final DisbursePaymentBuilderService disbursePaymentBuilderService,
      final ApplyInterestPaymentBuilderService applyInterestPaymentBuilderService,
      final AcceptPaymentBuilderService acceptPaymentBuilderService,
      final ClosePaymentBuilderService closePaymentBuilderService,
      final MarkLatePaymentBuilderService markLatePaymentBuilderService,
      final WriteOffPaymentBuilderService writeOffPaymentBuilderService,
      final RecoverPaymentBuilderService recoverPaymentBuilderService,
      final AccountingAdapter accountingAdapter,
      CaseCommandRepository caseCommandRepository, final TaskInstanceRepository taskInstanceRepository,
      final CaseParametersRepository caseParametersRepository) {
    this.caseRepository = caseRepository;
    this.dataContextService = dataContextService;
    this.openPaymentBuilderService = openPaymentBuilderService;
    this.approvePaymentBuilderService = approvePaymentBuilderService;
    this.denyPaymentBuilderService = denyPaymentBuilderService;
    this.disbursePaymentBuilderService = disbursePaymentBuilderService;
    this.applyInterestPaymentBuilderService = applyInterestPaymentBuilderService;
    this.acceptPaymentBuilderService = acceptPaymentBuilderService;
    this.closePaymentBuilderService = closePaymentBuilderService;
    this.markLatePaymentBuilderService = markLatePaymentBuilderService;
    this.writeOffPaymentBuilderService = writeOffPaymentBuilderService;
    this.recoverPaymentBuilderService = recoverPaymentBuilderService;
    this.accountingAdapter = accountingAdapter;
    this.caseCommandRepository = caseCommandRepository;
    this.taskInstanceRepository = taskInstanceRepository;
    this.caseParametersRepository = caseParametersRepository;
  }

  @Transactional
  @CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO)
  @EventEmitter(
      selectorName = EventConstants.SELECTOR_NAME,
      selectorValue = IndividualLoanEventConstants.OPEN_INDIVIDUALLOAN_CASE)
  public IndividualLoanCommandEvent process(final OpenCommand command) {
    final String productIdentifier = command.getProductIdentifier();
    final String caseIdentifier = command.getCaseIdentifier();
    final DataContextOfAction dataContextOfAction = dataContextService.checkedGetDataContext(
            productIdentifier, caseIdentifier, command.getCommand().getOneTimeAccountAssignments());
    IndividualLendingPatternFactory.checkActionCanBeExecuted(Case.State.valueOf(dataContextOfAction.getCustomerCaseEntity().getCurrentState()), Action.OPEN);

    checkIfTasksAreOutstanding(dataContextOfAction, Action.OPEN);

    final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
        = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
    final RealRunningBalances runningBalances = new RealRunningBalances(
        accountingAdapter,
        dataContextOfAction);

    final PaymentBuilder paymentBuilder
        = openPaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today(), runningBalances);

    final LocalDateTime today = today();

    final Optional<String> transactionUniqueifier = accountingAdapter.bookCharges(paymentBuilder.getBalanceAdjustments(),
        designatorToAccountIdentifierMapper,
        command.getCommand().getNote(),
        command.getCommand().getCreatedOn(),
        dataContextOfAction.getMessageForCharge(Action.OPEN),
        Action.OPEN.getTransactionType());

    final CaseEntity customerCase = dataContextOfAction.getCustomerCaseEntity();

    recordCommand(
        command.getCommand().getCreatedOn(),
        customerCase.getId(),
        Action.OPEN,
        transactionUniqueifier);

    //Only move to new state if book charges command was accepted.
    customerCase.setCurrentState(Case.State.PENDING.name());
    caseRepository.save(customerCase);

    return new IndividualLoanCommandEvent(productIdentifier, caseIdentifier, DateConverter.toIsoString(today));
  }

  @Transactional
  @CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO)
  @EventEmitter(
      selectorName = EventConstants.SELECTOR_NAME,
      selectorValue = IndividualLoanEventConstants.DENY_INDIVIDUALLOAN_CASE)
  public IndividualLoanCommandEvent process(final DenyCommand command) {
    final String productIdentifier = command.getProductIdentifier();
    final String caseIdentifier = command.getCaseIdentifier();
    final DataContextOfAction dataContextOfAction = dataContextService.checkedGetDataContext(
        productIdentifier, caseIdentifier, command.getCommand().getOneTimeAccountAssignments());
    IndividualLendingPatternFactory.checkActionCanBeExecuted(Case.State.valueOf(dataContextOfAction.getCustomerCaseEntity().getCurrentState()), Action.DENY);

    checkIfTasksAreOutstanding(dataContextOfAction, Action.DENY);

    final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
        = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
    final RealRunningBalances runningBalances = new RealRunningBalances(
        accountingAdapter,
        dataContextOfAction);

    final PaymentBuilder paymentBuilder
        = denyPaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today(), runningBalances);

    final LocalDateTime today = today();

    final Optional<String> transactionUniqueifier = accountingAdapter.bookCharges(paymentBuilder.getBalanceAdjustments(),
        designatorToAccountIdentifierMapper,
        command.getCommand().getNote(),
        command.getCommand().getCreatedOn(),
        dataContextOfAction.getMessageForCharge(Action.DENY),
        Action.DENY.getTransactionType());

    final CaseEntity customerCase = dataContextOfAction.getCustomerCaseEntity();

    recordCommand(
        command.getCommand().getCreatedOn(),
        customerCase.getId(),
        Action.DENY,
        transactionUniqueifier);

    customerCase.setCurrentState(Case.State.CLOSED.name());
    caseRepository.save(customerCase);

    return new IndividualLoanCommandEvent(productIdentifier, caseIdentifier, DateConverter.toIsoString(today));
  }

  static class InterruptedInALambdaException extends RuntimeException {

    private final InterruptedException interruptedException;

    InterruptedInALambdaException(InterruptedException e) {
      interruptedException = e;
    }

    void throwWrappedException() throws InterruptedException {
      throw interruptedException;
    }
  }

  @Transactional
  @CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO)
  @EventEmitter(
      selectorName = EventConstants.SELECTOR_NAME,
      selectorValue = IndividualLoanEventConstants.APPROVE_INDIVIDUALLOAN_CASE)
  public IndividualLoanCommandEvent process(final ApproveCommand command) throws InterruptedException
  {
    final String productIdentifier = command.getProductIdentifier();
    final String caseIdentifier = command.getCaseIdentifier();
    final DataContextOfAction dataContextOfAction = dataContextService.checkedGetDataContext(
        productIdentifier, caseIdentifier, command.getCommand().getOneTimeAccountAssignments());
    IndividualLendingPatternFactory.checkActionCanBeExecuted(Case.State.valueOf(dataContextOfAction.getCustomerCaseEntity().getCurrentState()), Action.APPROVE);

    checkIfTasksAreOutstanding(dataContextOfAction, Action.APPROVE);

    final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
            = new DesignatorToAccountIdentifierMapper(dataContextOfAction);

    //Create the needed account assignments for groups and persist them for the case.
    try {
      designatorToAccountIdentifierMapper.getGroupsNeedingLedgers()
          .map(groupNeedingLedger -> {
            try {
              final String createdLedgerIdentifier = accountingAdapter.createLedger(
                  dataContextOfAction.getCaseParametersEntity().getCustomerIdentifier(),
                  groupNeedingLedger.getGroupName(),
                  groupNeedingLedger.getParentLedger());
              return new AccountAssignment(groupNeedingLedger.getGroupName(), createdLedgerIdentifier);
            } catch (InterruptedException e) {
              throw new InterruptedInALambdaException(e);
            }
          })
          .map(accountAssignment -> CaseMapper.map(accountAssignment, dataContextOfAction.getCustomerCaseEntity()))
          .forEach(caseAccountAssignmentEntity -> dataContextOfAction.getCustomerCaseEntity().getAccountAssignments().add(caseAccountAssignmentEntity));
    }
    catch (final InterruptedInALambdaException e) {
      e.throwWrappedException();
    }

    //Create the needed account assignments and persist them for the case.
    designatorToAccountIdentifierMapper.getLedgersNeedingAccounts()
        .map(ledger ->
            new AccountAssignment(ledger.getDesignator(),
                accountingAdapter.createAccountForLedgerAssignment(
                    dataContextOfAction.getCaseParametersEntity().getCustomerIdentifier(),
                    ledger)))
        .map(accountAssignment -> CaseMapper.map(accountAssignment, dataContextOfAction.getCustomerCaseEntity()))
        .forEach(caseAccountAssignmentEntity ->
            dataContextOfAction.getCustomerCaseEntity().getAccountAssignments().add(caseAccountAssignmentEntity)
        );
    caseRepository.save(dataContextOfAction.getCustomerCaseEntity());

    final RealRunningBalances runningBalances = new RealRunningBalances(
        accountingAdapter,
        dataContextOfAction);

    final PaymentBuilder paymentBuilder =
        approvePaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today(), runningBalances);

    final LocalDateTime today = today();

    final Optional<String> transactionUniqueifier = accountingAdapter.bookCharges(paymentBuilder.getBalanceAdjustments(),
        designatorToAccountIdentifierMapper,
        command.getCommand().getNote(),
        command.getCommand().getCreatedOn(),
        dataContextOfAction.getMessageForCharge(Action.APPROVE),
        Action.APPROVE.getTransactionType());

    final CaseEntity customerCase = dataContextOfAction.getCustomerCaseEntity();

    recordCommand(
        command.getCommand().getCreatedOn(),
        customerCase.getId(),
        Action.APPROVE,
        transactionUniqueifier);

    //Only move to new state if book charges command was accepted.
    customerCase.setCurrentState(Case.State.APPROVED.name());
    caseRepository.save(customerCase);

    return new IndividualLoanCommandEvent(productIdentifier, caseIdentifier, DateConverter.toIsoString(today));
  }

  @Transactional
  @CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO)
  @EventEmitter(selectorName = EventConstants.SELECTOR_NAME, selectorValue = IndividualLoanEventConstants.DISBURSE_INDIVIDUALLOAN_CASE)
  public IndividualLoanCommandEvent process(final DisburseCommand command) {
    final String productIdentifier = command.getProductIdentifier();
    final String caseIdentifier = command.getCaseIdentifier();
    final DataContextOfAction dataContextOfAction = dataContextService.checkedGetDataContext(
        productIdentifier, caseIdentifier, command.getCommand().getOneTimeAccountAssignments());
    IndividualLendingPatternFactory.checkActionCanBeExecuted(Case.State.valueOf(dataContextOfAction.getCustomerCaseEntity().getCurrentState()), Action.DISBURSE);

    checkIfTasksAreOutstanding(dataContextOfAction, Action.DISBURSE);

    final BigDecimal disbursalAmount = Optional.ofNullable(command.getCommand().getPaymentSize()).orElse(BigDecimal.ZERO);

    final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
        = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
    final RealRunningBalances runningBalances = new RealRunningBalances(
        accountingAdapter,
        dataContextOfAction);

    final PaymentBuilder paymentBuilder =
        disbursePaymentBuilderService.getPaymentBuilder(dataContextOfAction, disbursalAmount, CostComponentService.today(), runningBalances);

    final LocalDateTime today = today();

    final Optional<String> transactionUniqueifier = accountingAdapter.bookCharges(paymentBuilder.getBalanceAdjustments(),
        designatorToAccountIdentifierMapper,
        command.getCommand().getNote(),
        command.getCommand().getCreatedOn(),
        dataContextOfAction.getMessageForCharge(Action.DISBURSE),
        Action.DISBURSE.getTransactionType());

    final CaseEntity customerCase = dataContextOfAction.getCustomerCaseEntity();

    recordCommand(
        command.getCommand().getCreatedOn(),
        customerCase.getId(),
        Action.DISBURSE,
        transactionUniqueifier);

    //Only move to new state if book charges command was accepted.
    if (Case.State.valueOf(dataContextOfAction.getCustomerCaseEntity().getCurrentState()) != Case.State.ACTIVE) {
      final LocalDateTime endOfTerm
          = ScheduledActionHelpers.getRoughEndDate(today.toLocalDate(), dataContextOfAction.getCaseParameters())
          .atTime(LocalTime.MIDNIGHT);
      customerCase.setEndOfTerm(endOfTerm);
      customerCase.setCurrentState(Case.State.ACTIVE.name());
      caseRepository.save(customerCase);
    }
    final BigDecimal currentBalance = runningBalances.getBalance(AccountDesignators.CUSTOMER_LOAN_GROUP);

    final BigDecimal newLoanPaymentSize = disbursePaymentBuilderService.getLoanPaymentSizeForSingleDisbursement(
        currentBalance.add(paymentBuilder.getBalanceAdjustment(AccountDesignators.ENTRY)),
        dataContextOfAction);

    dataContextOfAction.getCaseParametersEntity().setPaymentSize(newLoanPaymentSize);
    caseParametersRepository.save(dataContextOfAction.getCaseParametersEntity());

    return new IndividualLoanCommandEvent(productIdentifier, caseIdentifier, DateConverter.toIsoString(today));
  }

  @Transactional
  @CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO)
  @EventEmitter(
      selectorName = EventConstants.SELECTOR_NAME,
      selectorValue = IndividualLoanEventConstants.APPLY_INTEREST_INDIVIDUALLOAN_CASE)
  public IndividualLoanCommandEvent process(final ApplyInterestCommand command) {
    final String productIdentifier = command.getProductIdentifier();
    final String caseIdentifier = command.getCaseIdentifier();
    final DataContextOfAction dataContextOfAction = dataContextService.checkedGetDataContext(
        productIdentifier, caseIdentifier, null);
    IndividualLendingPatternFactory.checkActionCanBeExecuted(Case.State.valueOf(dataContextOfAction.getCustomerCaseEntity().getCurrentState()), Action.APPLY_INTEREST);

    if (dataContextOfAction.getCustomerCaseEntity().getEndOfTerm() == null)
      throw ServiceException.internalError(
          "End of term not set for active case ''{0}.{1}.''", productIdentifier, caseIdentifier);

    final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
        = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
    final RealRunningBalances runningBalances = new RealRunningBalances(
        accountingAdapter,
        dataContextOfAction);

    final PaymentBuilder paymentBuilder =
        applyInterestPaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today(), runningBalances);

    final Optional<String> transactionUniqueifier = accountingAdapter.bookCharges(paymentBuilder.getBalanceAdjustments(),
        designatorToAccountIdentifierMapper,
        "Applied interest on " + command.getForTime(),
        command.getForTime(),
        dataContextOfAction.getMessageForCharge(Action.APPLY_INTEREST),
        Action.APPLY_INTEREST.getTransactionType());

    final CaseEntity customerCase = dataContextOfAction.getCustomerCaseEntity();

    recordCommand(
        command.getForTime(),
        customerCase.getId(),
        Action.APPLY_INTEREST,
        transactionUniqueifier);

    return new IndividualLoanCommandEvent(productIdentifier, caseIdentifier, command.getForTime());
  }

  @Transactional
  @CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO)
  @EventEmitter(
      selectorName = EventConstants.SELECTOR_NAME,
      selectorValue = IndividualLoanEventConstants.ACCEPT_PAYMENT_INDIVIDUALLOAN_CASE)
  public IndividualLoanCommandEvent process(final AcceptPaymentCommand command) {
    final String productIdentifier = command.getProductIdentifier();
    final String caseIdentifier = command.getCaseIdentifier();
    final DataContextOfAction dataContextOfAction = dataContextService.checkedGetDataContext(
        productIdentifier, caseIdentifier, command.getCommand().getOneTimeAccountAssignments());
    IndividualLendingPatternFactory.checkActionCanBeExecuted(Case.State.valueOf(dataContextOfAction.getCustomerCaseEntity().getCurrentState()), Action.ACCEPT_PAYMENT);

    checkIfTasksAreOutstanding(dataContextOfAction, Action.ACCEPT_PAYMENT);

    if (dataContextOfAction.getCustomerCaseEntity().getEndOfTerm() == null)
      throw ServiceException.internalError(
          "End of term not set for active case ''{0}.{1}.''", productIdentifier, caseIdentifier);


    final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
        = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
    final RealRunningBalances runningBalances = new RealRunningBalances(
        accountingAdapter,
        dataContextOfAction);

    final PaymentBuilder paymentBuilder =
        acceptPaymentBuilderService.getPaymentBuilder(
            dataContextOfAction,
            command.getCommand().getPaymentSize(),
            DateConverter.fromIsoString(command.getCommand().getCreatedOn()).toLocalDate(), runningBalances);

    final LocalDateTime today = today();

    final Optional<String> transactionUniqueifier = accountingAdapter.bookCharges(paymentBuilder.getBalanceAdjustments(),
        designatorToAccountIdentifierMapper,
        command.getCommand().getNote(),
        command.getCommand().getCreatedOn(),
        dataContextOfAction.getMessageForCharge(Action.ACCEPT_PAYMENT),
        Action.ACCEPT_PAYMENT.getTransactionType());

    final CaseEntity customerCase = dataContextOfAction.getCustomerCaseEntity();

    recordCommand(
        command.getCommand().getCreatedOn(),
        customerCase.getId(),
        Action.ACCEPT_PAYMENT,
        transactionUniqueifier);

    return new IndividualLoanCommandEvent(productIdentifier, caseIdentifier, DateConverter.toIsoString(today));
  }

  @Transactional
  @CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO)
  @EventEmitter(
      selectorName = EventConstants.SELECTOR_NAME,
      selectorValue = IndividualLoanEventConstants.MARK_LATE_INDIVIDUALLOAN_CASE)
  public IndividualLoanCommandEvent process(final MarkLateCommand command) {
    final String productIdentifier = command.getProductIdentifier();
    final String caseIdentifier = command.getCaseIdentifier();
    final DataContextOfAction dataContextOfAction = dataContextService.checkedGetDataContext(
        productIdentifier, caseIdentifier, Collections.emptyList());
    IndividualLendingPatternFactory.checkActionCanBeExecuted(Case.State.valueOf(dataContextOfAction.getCustomerCaseEntity().getCurrentState()), Action.MARK_LATE);

    checkIfTasksAreOutstanding(dataContextOfAction, Action.MARK_LATE);

    if (dataContextOfAction.getCustomerCaseEntity().getEndOfTerm() == null)
      throw ServiceException.internalError(
          "End of term not set for active case ''{0}.{1}.''", productIdentifier, caseIdentifier);

    final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
        = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
    final RealRunningBalances runningBalances = new RealRunningBalances(
        accountingAdapter,
        dataContextOfAction);

    final PaymentBuilder paymentBuilder =
        markLatePaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, DateConverter.fromIsoString(command.getForTime()).toLocalDate(),
            runningBalances);

    final LocalDateTime today = today();

    final Optional<String> transactionUniqueifier = accountingAdapter.bookCharges(paymentBuilder.getBalanceAdjustments(),
        designatorToAccountIdentifierMapper,
        "Marked late on " + command.getForTime(),
        command.getForTime(),
        dataContextOfAction.getMessageForCharge(Action.MARK_LATE),
        Action.MARK_LATE.getTransactionType());

    final CaseEntity customerCase = dataContextOfAction.getCustomerCaseEntity();

    recordCommand(
        command.getForTime(),
        customerCase.getId(),
        Action.MARK_LATE,
        transactionUniqueifier);

    return new IndividualLoanCommandEvent(productIdentifier, caseIdentifier, DateConverter.toIsoString(today));
  }

  @Transactional
  @CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO)
  @EventEmitter(selectorName = EventConstants.SELECTOR_NAME, selectorValue = IndividualLoanEventConstants.WRITE_OFF_INDIVIDUALLOAN_CASE)
  public IndividualLoanCommandEvent process(final WriteOffCommand command) {
    final String productIdentifier = command.getProductIdentifier();
    final String caseIdentifier = command.getCaseIdentifier();
    final DataContextOfAction dataContextOfAction = dataContextService.checkedGetDataContext(
        productIdentifier, caseIdentifier, command.getCommand().getOneTimeAccountAssignments());
    IndividualLendingPatternFactory.checkActionCanBeExecuted(Case.State.valueOf(dataContextOfAction.getCustomerCaseEntity().getCurrentState()), Action.WRITE_OFF);

    checkIfTasksAreOutstanding(dataContextOfAction, Action.WRITE_OFF);
    final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
        = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
    final RealRunningBalances runningBalances = new RealRunningBalances(
        accountingAdapter,
        dataContextOfAction);

    final PaymentBuilder paymentBuilder =
        writeOffPaymentBuilderService.getPaymentBuilder(
            dataContextOfAction,
            command.getCommand().getPaymentSize(),
            DateConverter.fromIsoString(command.getCommand().getCreatedOn()).toLocalDate(), runningBalances);

    final LocalDateTime today = today();

    final Optional<String> transactionUniqueifier = accountingAdapter.bookCharges(paymentBuilder.getBalanceAdjustments(),
        designatorToAccountIdentifierMapper,
        command.getCommand().getNote(),
        command.getCommand().getCreatedOn(),
        dataContextOfAction.getMessageForCharge(Action.WRITE_OFF),
        Action.WRITE_OFF.getTransactionType());

    final CaseEntity customerCase = dataContextOfAction.getCustomerCaseEntity();

    recordCommand(
        command.getCommand().getCreatedOn(),
        customerCase.getId(),
        Action.WRITE_OFF,
        transactionUniqueifier);

    customerCase.setCurrentState(Case.State.CLOSED.name());
    caseRepository.save(customerCase);

    return new IndividualLoanCommandEvent(productIdentifier, caseIdentifier, DateConverter.toIsoString(today));
  }

  @Transactional
  @CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO)
  @EventEmitter(selectorName = EventConstants.SELECTOR_NAME, selectorValue = IndividualLoanEventConstants.CLOSE_INDIVIDUALLOAN_CASE)
  public IndividualLoanCommandEvent process(final CloseCommand command) {
    final String productIdentifier = command.getProductIdentifier();
    final String caseIdentifier = command.getCaseIdentifier();
    final DataContextOfAction dataContextOfAction = dataContextService.checkedGetDataContext(
        productIdentifier, caseIdentifier, command.getCommand().getOneTimeAccountAssignments());
    IndividualLendingPatternFactory.checkActionCanBeExecuted(Case.State.valueOf(dataContextOfAction.getCustomerCaseEntity().getCurrentState()), Action.CLOSE);

    checkIfTasksAreOutstanding(dataContextOfAction, Action.CLOSE);

    final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
        = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
    final RealRunningBalances runningBalances = new RealRunningBalances(
        accountingAdapter,
        dataContextOfAction);

    final PaymentBuilder paymentBuilder =
        closePaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today(), runningBalances);

    final LocalDateTime today = today();

    final Optional<String> transactionIdentifier = accountingAdapter.bookCharges(paymentBuilder.getBalanceAdjustments(),
        designatorToAccountIdentifierMapper,
        command.getCommand().getNote(),
        command.getCommand().getCreatedOn(),
        dataContextOfAction.getMessageForCharge(Action.CLOSE),
        Action.CLOSE.getTransactionType());

    final CaseEntity customerCase = dataContextOfAction.getCustomerCaseEntity();
    customerCase.setCurrentState(Case.State.CLOSED.name());
    caseRepository.save(customerCase);

    return new IndividualLoanCommandEvent(productIdentifier, caseIdentifier, DateConverter.toIsoString(today));
  }

  @Transactional
  @CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO)
  @EventEmitter(selectorName = EventConstants.SELECTOR_NAME, selectorValue = IndividualLoanEventConstants.RECOVER_INDIVIDUALLOAN_CASE)
  public IndividualLoanCommandEvent process(final RecoverCommand command) {
    final String productIdentifier = command.getProductIdentifier();
    final String caseIdentifier = command.getCaseIdentifier();
    final DataContextOfAction dataContextOfAction = dataContextService.checkedGetDataContext(
        productIdentifier, caseIdentifier, command.getCommand().getOneTimeAccountAssignments());
    IndividualLendingPatternFactory.checkActionCanBeExecuted(Case.State.valueOf(dataContextOfAction.getCustomerCaseEntity().getCurrentState()), Action.RECOVER);

    checkIfTasksAreOutstanding(dataContextOfAction, Action.RECOVER);

    final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
        = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
    final RealRunningBalances runningBalances = new RealRunningBalances(
        accountingAdapter,
        dataContextOfAction);

    final PaymentBuilder paymentBuilder =
        recoverPaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today(), runningBalances);

    final LocalDateTime today = today();

    final Optional<String> transactionUniqueifier = accountingAdapter.bookCharges(paymentBuilder.getBalanceAdjustments(),
        designatorToAccountIdentifierMapper,
        command.getCommand().getNote(),
        command.getCommand().getCreatedOn(),
        dataContextOfAction.getMessageForCharge(Action.RECOVER),
        Action.CLOSE.getTransactionType());

    final CaseEntity customerCase = dataContextOfAction.getCustomerCaseEntity();

    recordCommand(
        command.getCommand().getCreatedOn(),
        customerCase.getId(),
        Action.RECOVER,
        transactionUniqueifier);

    customerCase.setCurrentState(Case.State.CLOSED.name());
    caseRepository.save(customerCase);

    return new IndividualLoanCommandEvent(productIdentifier, caseIdentifier, DateConverter.toIsoString(today));
  }

  private Map<String, BigDecimal> getRequestedChargeAmounts(final @Nullable List<CostComponent> costComponents) {
    if (costComponents == null)
      return Collections.emptyMap();
    else
      return costComponents.stream()
          .collect(Collectors.groupingBy(
              CostComponent::getChargeIdentifier,
              Collectors.reducing(BigDecimal.ZERO,
                  CostComponent::getAmount,
                  BigDecimal::add)));
  }

  private void checkIfTasksAreOutstanding(final DataContextOfAction dataContextOfAction, final Action action) {
    final String productIdentifier = dataContextOfAction.getProductEntity().getIdentifier();
    final String caseIdentifier = dataContextOfAction.getCustomerCaseEntity().getIdentifier();
    final boolean tasksOutstanding = taskInstanceRepository.areTasksOutstanding(
        productIdentifier, caseIdentifier, action.name());
    if (tasksOutstanding)
      throw ServiceException.conflict("Cannot execute action ''{0}'' for case ''{1}.{2}'' because tasks are incomplete.",
          action.name(), productIdentifier, caseIdentifier);
  }

  private void recordCommand(
      final String when,
      final Long caseId,
      final Action action,
      @SuppressWarnings("OptionalUsedAsFieldOrParameterType") final Optional<String> transactionUniqueifier) {
    final CaseCommandEntity caseCommandEntity = new CaseCommandEntity();
    caseCommandEntity.setCaseId(caseId);
    caseCommandEntity.setActionName(action.name());
    caseCommandEntity.setCreatedBy(UserContextHolder.checkedGetUser());
    caseCommandEntity.setCreatedOn(DateConverter.fromIsoString(when));
    caseCommandEntity.setTransactionUniqueifier(transactionUniqueifier.orElse(""));
    caseCommandRepository.save(caseCommandEntity);
  }

  private static LocalDateTime today() {
    return LocalDate.now(Clock.systemUTC()).atStartOfDay();
  }
}