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

import io.mifos.accounting.api.v1.client.AccountAlreadyExistsException;
import io.mifos.accounting.api.v1.client.AccountNotFoundException;
import io.mifos.accounting.api.v1.client.LedgerManager;
import io.mifos.accounting.api.v1.client.LedgerNotFoundException;
import io.mifos.accounting.api.v1.domain.*;
import io.mifos.core.api.util.UserContextHolder;
import io.mifos.core.lang.DateConverter;
import io.mifos.core.lang.DateRange;
import io.mifos.core.lang.ServiceException;
import io.mifos.core.lang.listening.EventExpectation;
import io.mifos.individuallending.internal.service.DesignatorToAccountIdentifierMapper;
import io.mifos.portfolio.api.v1.domain.AccountAssignment;
import io.mifos.portfolio.api.v1.domain.ChargeDefinition;
import io.mifos.portfolio.service.ServiceConstants;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static io.mifos.individuallending.api.v1.domain.product.AccountDesignators.ENTRY;

/**
 * @author Myrle Krantz
 */
@Component
public class AccountingAdapter {


  public enum IdentifierType {LEDGER, ACCOUNT}

  private final LedgerManager ledgerManager;
  private final AccountingListener accountingListener;
  private final Logger logger;

  @Autowired
  public AccountingAdapter(@SuppressWarnings("SpringJavaAutowiringInspection") final LedgerManager ledgerManager,
                           final AccountingListener accountingListener,
                           @Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) {
    this.ledgerManager = ledgerManager;
    this.accountingListener = accountingListener;
    this.logger = logger;
  }

  public Optional<String> bookCharges(
      final Map<String, BigDecimal> balanceAdjustments,
      final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper,
      final String note,
      final String transactionDate,
      final String message,
      final String transactionType) {
    final JournalEntry journalEntry = new JournalEntry();
    final Set<Creditor> creditors = new HashSet<>();
    journalEntry.setCreditors(creditors);
    final Set<Debtor> debtors = new HashSet<>();
    journalEntry.setDebtors(debtors);
    balanceAdjustments.forEach((accountDesignator, balanceAdjustment) -> {
      final int sign = balanceAdjustment.compareTo(BigDecimal.ZERO);
      if (sign == 0)
        return;

      final String accountIdentifier = designatorToAccountIdentifierMapper.mapOrThrow(accountDesignator);

      if (sign < 0) {
        final Debtor debtor = new Debtor();
        debtor.setAccountNumber(accountIdentifier);
        debtor.setAmount(balanceAdjustment.negate().toPlainString());
        debtors.add(debtor);
      } else {
        final Creditor creditor = new Creditor();
        creditor.setAccountNumber(accountIdentifier);
        creditor.setAmount(balanceAdjustment.toPlainString());
        creditors.add(creditor);
      }
    });

    if (creditors.isEmpty() && !debtors.isEmpty() ||
        debtors.isEmpty() && !creditors.isEmpty())
      throw ServiceException.internalError("either only creditors or only debtors were provided.");

    //noinspection ConstantConditions
    if (creditors.isEmpty() && debtors.isEmpty())
      return Optional.empty();

    final String transactionUniqueifier = RandomStringUtils.random(26, true, true);
    final String transactionIdentifier = "portfolio." + message + "." + transactionUniqueifier;
    journalEntry.setCreditors(creditors);
    journalEntry.setDebtors(debtors);
    journalEntry.setClerk(UserContextHolder.checkedGetUser());
    journalEntry.setTransactionDate(transactionDate);
    journalEntry.setMessage(message);
    journalEntry.setTransactionType(transactionType);
    journalEntry.setNote(note);
    journalEntry.setTransactionIdentifier(transactionIdentifier);

    ledgerManager.createJournalEntry(journalEntry);
    return Optional.of(transactionUniqueifier);
  }

  public Optional<LocalDateTime> getDateOfOldestEntryContainingMessage(final String accountIdentifier,
                                                                       final String message) {
    final Account account = ledgerManager.findAccount(accountIdentifier);
    final LocalDateTime accountCreatedOn = DateConverter.fromIsoString(account.getCreatedOn());
    final DateRange fromAccountCreationUntilNow = oneSidedDateRange(accountCreatedOn.toLocalDate());

    return ledgerManager.fetchAccountEntriesStream(accountIdentifier, fromAccountCreationUntilNow.toString(), message, "ASC")
        .findFirst()
        .map(AccountEntry::getTransactionDate)
        .map(DateConverter::fromIsoString);
  }

  public Optional<LocalDateTime> getDateOfMostRecentEntryContainingMessage(
      final String accountIdentifier,
      final String message) {

    final Account account = ledgerManager.findAccount(accountIdentifier);
    final LocalDateTime accountCreatedOn = DateConverter.fromIsoString(account.getCreatedOn());
    final DateRange fromAccountCreationUntilNow = oneSidedDateRange(accountCreatedOn.toLocalDate());

    return ledgerManager.fetchAccountEntriesStream(accountIdentifier, fromAccountCreationUntilNow.toString(), message, "DESC")
        .findFirst()
        .map(AccountEntry::getTransactionDate)
        .map(DateConverter::fromIsoString);
  }

  public BigDecimal sumMatchingEntriesSinceDate(final String accountIdentifier, final LocalDate startDate, final String message)
  {
    final DateRange fromLastPaymentUntilNow = oneSidedDateRange(startDate);
    final Stream<AccountEntry> accountEntriesStream = ledgerManager.fetchAccountEntriesStream(accountIdentifier, fromLastPaymentUntilNow.toString(), message, "ASC");
    return accountEntriesStream
        .map(AccountEntry::getAmount)
        .map(BigDecimal::valueOf).reduce(BigDecimal.ZERO, BigDecimal::add);
  }

  public BigDecimal getCurrentAccountBalance(final String accountIdentifier) {
    try {
      final Account account = ledgerManager.findAccount(accountIdentifier);
      if (account == null || account.getBalance() == null)
        throw ServiceException.internalError("Could not find the account with identifier ''{0}''", accountIdentifier);
      return BigDecimal.valueOf(account.getBalance());
    }
    catch (final AccountNotFoundException e) {
     throw ServiceException.internalError("Could not find the account with identifier ''{0}''", accountIdentifier);
    }
  }

  public String createLedger(
      final String customerIdentifier,
      final String groupName,
      final String parentLedger) throws InterruptedException
  {
    final Ledger ledger = ledgerManager.findLedger(parentLedger);
    final List<Ledger> subLedgers = ledger.getSubLedgers() == null ? Collections.emptyList() : ledger.getSubLedgers();

    final Ledger generatedLedger = new Ledger();
    generatedLedger.setShowAccountsInChart(true);
    generatedLedger.setParentLedgerIdentifier(parentLedger);
    generatedLedger.setType(ledger.getType());
    final String ledgerIdentifer = createLedgerIdentifier(customerIdentifier, groupName, subLedgers);
    generatedLedger.setIdentifier(ledgerIdentifer);
    generatedLedger.setDescription("Individual loan case specific ledger");
    generatedLedger.setName(ledgerIdentifer);

    logger.info("Creating ledger with identifier '{}'", ledgerIdentifer);

    final EventExpectation expectation = accountingListener.expectLedgerCreation(generatedLedger.getIdentifier());
    ledgerManager.createLedger(generatedLedger);
    final boolean ledgerCreationDetected = expectation.waitForOccurrence(5, TimeUnit.SECONDS);
    if (!ledgerCreationDetected)
      logger.warn("Waited 5 seconds for creation of ledger '{}', but it was not detected. This could cause subsequent " +
              "account creations to fail. Is there something wrong with the accounting service? Is ActiveMQ setup properly?",
          generatedLedger.getIdentifier());
    return ledgerIdentifer;
  }

  public String createAccountForLedgerAssignment(final String customerIdentifier, final AccountAssignment ledgerAssignment) {
    final Ledger ledger = ledgerManager.findLedger(ledgerAssignment.getLedgerIdentifier());
    final AccountPage accountsOfLedger = ledgerManager.fetchAccountsOfLedger(ledger.getIdentifier(), null, null, null, null);

    final Account generatedAccount = new Account();
    generatedAccount.setBalance(0.0);
    generatedAccount.setType(ledger.getType());
    generatedAccount.setState(Account.State.OPEN.name());
    long guestimatedAccountIndex = accountsOfLedger.getTotalElements() + 1;
    generatedAccount.setLedger(ledger.getIdentifier());
    final Optional<String> createdAccountNumber =
        Stream.iterate(guestimatedAccountIndex, i -> i + 1).limit(99999 - guestimatedAccountIndex)
        .map(i -> {
          final String accountNumber = createAccountNumber(customerIdentifier, ledgerAssignment.getDesignator(), i);
          generatedAccount.setIdentifier(accountNumber);
          generatedAccount.setName(accountNumber);
          try {
            ledgerManager.createAccount(generatedAccount);
            return Optional.of(accountNumber);
          } catch (final AccountAlreadyExistsException e) {
            logger.error("Account '{}' could not be created because it already exists.", accountNumber);
            return Optional.<String>empty();
          }
        })
        .filter(Optional::isPresent).map(Optional::get)
        .findFirst();

    return createdAccountNumber.orElseThrow(() ->
        ServiceException.conflict("Failed to create an account for customer ''{0}'' and ''{1}'', in ledger ''{2}''.",
            customerIdentifier, ledgerAssignment.getDesignator(), ledgerAssignment.getLedgerIdentifier()));
  }

  private String createLedgerIdentifier(
      final String customerIdentifier,
      final String groupName,
      final List<Ledger> subLedgers) {
    final String partialCustomerIdentifer = StringUtils.left(customerIdentifier, 22);
    final String partialGroupName = StringUtils.left(groupName, 3);
    final Set<String> subLedgerIdentifiers = subLedgers.stream().map(Ledger::getIdentifier).collect(Collectors.toSet());
    long index = 0;
    while (true) {
      index++;
      final String generatedIdentifier = partialCustomerIdentifer + "." + partialGroupName + "." + String.format("%05d", index);
      if (!subLedgerIdentifiers.contains(generatedIdentifier))
        return generatedIdentifier;
    }
  }

  private String createAccountNumber(final String customerIdentifier, final String designator, final long accountIndex) {
    return StringUtils.left(customerIdentifier, 22) + "." + StringUtils.left(designator, 3)
            + "." + String.format("%05d", accountIndex);
  }


  public static Set<String> accountAssignmentsRequiredButNotProvided(
          final Set<AccountAssignment> accountAssignments,
          final Stream<ChargeDefinition> chargeDefinitionEntities) {
    final Set<String> allAccountDesignatorsRequired = getRequiredAccountDesignators(chargeDefinitionEntities);
    final Set<String> allAccountDesignatorsDefined = accountAssignments.stream().map(AccountAssignment::getDesignator)
            .collect(Collectors.toSet());
    if (allAccountDesignatorsDefined.containsAll(allAccountDesignatorsRequired))
      return Collections.emptySet();
    else {
      allAccountDesignatorsRequired.removeAll(allAccountDesignatorsDefined);
      return allAccountDesignatorsRequired;
    }
  }

  public static Set<String> getRequiredAccountDesignators(final Stream<ChargeDefinition> chargeDefinitionEntities) {
    return chargeDefinitionEntities
            .flatMap(AccountingAdapter::getAutomaticActionAccountDesignators)
            .filter(Objects::nonNull)
            .collect(Collectors.toSet());
  }

  private static Stream<String> getAutomaticActionAccountDesignators(final ChargeDefinition chargeDefinition) {
    final Stream.Builder<String> retBuilder = Stream.builder();

    checkAddDesignator(chargeDefinition.getFromAccountDesignator(), retBuilder);
    checkAddDesignator(chargeDefinition.getAccrualAccountDesignator(), retBuilder);
    checkAddDesignator(chargeDefinition.getToAccountDesignator(), retBuilder);

    return retBuilder.build();
  }

  private static void checkAddDesignator(final String accountDesignator, final Stream.Builder<String> retBuilder) {
    if (accountDesignator != null && !accountDesignator.equals(ENTRY))
      retBuilder.add(accountDesignator);
  }

  public Set<String> accountAssignmentsMappedToNonexistentAccounts(final Set<AccountAssignment> accountAssignments)
  {
    return accountAssignments.stream()
        .filter(x -> !accountAssignmentRepresentsRealAccount(x))
        .map(AccountAssignment::getDesignator)
        .collect(Collectors.toSet());
  }

  public boolean accountAssignmentRepresentsRealAccount(final AccountAssignment accountAssignment) {
    if (accountAssignment.getAccountIdentifier() != null) {
      try {
        ledgerManager.findAccount(accountAssignment.getAccountIdentifier());
        return true;
      }
      catch (final AccountNotFoundException e){
        return false;
      }
    }
    else if (accountAssignment.getLedgerIdentifier() != null) {
      try {
        ledgerManager.findLedger(accountAssignment.getLedgerIdentifier());
        return true;
      }
      catch (final LedgerNotFoundException e){
        return false;
      }
    }
    else
      return false;
  }

  private static DateRange oneSidedDateRange(final LocalDate start) {
    return new DateRange(start, LocalDate.now(ZoneId.of("UTC")));
  }
}
