/*
 * 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 io.mifos.accounting.api.v1.client.LedgerManager;
import io.mifos.accounting.api.v1.domain.*;
import io.mifos.core.api.util.NotFoundException;
import io.mifos.core.lang.DateConverter;
import io.mifos.individuallending.api.v1.domain.workflow.Action;
import org.hamcrest.Description;
import org.mockito.AdditionalMatchers;
import org.mockito.ArgumentMatcher;
import org.mockito.Matchers;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import javax.validation.Validation;
import javax.validation.Validator;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static org.mockito.Matchers.argThat;

/**
 * @author Myrle Krantz
 */
@SuppressWarnings("Duplicates")
class AccountingFixture {
  private static final LocalDateTime universalCreationDate = LocalDateTime.of(2017, 7, 18, 15, 16, 43, 10);
  private static final String INCOME_LEDGER_IDENTIFIER = "1000";
  private static final String LOAN_INCOME_LEDGER_IDENTIFIER = "1100";
  private static final String FEES_AND_CHARGES_LEDGER_IDENTIFIER = "1300";
  private static final String ASSET_LEDGER_IDENTIFIER = "7000";
  private static final String CASH_LEDGER_IDENTIFIER = "7300";
  static final String PENDING_DISBURSAL_LEDGER_IDENTIFIER = "7320";
  static final String CUSTOMER_LOAN_LEDGER_IDENTIFIER = "7353";
  private static final String ACCRUED_INCOME_LEDGER_IDENTIFIER = "7800";

  static final String LOAN_FUNDS_SOURCE_ACCOUNT_IDENTIFIER = "7310";
  static final String LOAN_ORIGINATION_FEES_ACCOUNT_IDENTIFIER = "1310";
  static final String PROCESSING_FEE_INCOME_ACCOUNT_IDENTIFIER = "1312";
  static final String DISBURSEMENT_FEE_INCOME_ACCOUNT_IDENTIFIER = "1313";
  static final String TELLER_ONE_ACCOUNT_IDENTIFIER = "7352";
  static final String LOAN_INTEREST_ACCRUAL_ACCOUNT_IDENTIFIER = "7810";
  static final String CONSUMER_LOAN_INTEREST_ACCOUNT_IDENTIFIER = "1103";
  static final String LOANS_PAYABLE_ACCOUNT_IDENTIFIER ="8690";
  static final String LATE_FEE_INCOME_ACCOUNT_IDENTIFIER = "1311";
  static final String LATE_FEE_ACCRUAL_ACCOUNT_IDENTIFIER = "7840";
  static final String ARREARS_ALLOWANCE_ACCOUNT_IDENTIFIER = "3010";

  static final Map<String, AccountData> accountMap = new HashMap<>();

  private static class AccountData {
    final Account account;
    final List<AccountEntry> accountEntries = new ArrayList<>();

    AccountData(final Account account) {
      this.account = account;
    }

    void setBalance(final double balance) {
      this.account.setBalance(balance);
    }

    synchronized void addAccountEntry(final String message, final String date, final double amount) {
      final AccountEntry accountEntry = new AccountEntry();
      accountEntry.setAmount(amount);
      accountEntry.setMessage(message);
      accountEntry.setTransactionDate(date);
      accountEntries.add(accountEntry);
    }

    synchronized List<AccountEntry> copyAccountEntries() {
      return new ArrayList<>(accountEntries);
    }
  }

  private static void makeAccountResponsive(final Account account, final LocalDateTime creationDate, final LedgerManager ledgerManagerMock) {
    account.setCreatedOn(DateConverter.toIsoString(creationDate));
    final AccountData accountData = new AccountData(account);
    accountMap.put(account.getIdentifier(), accountData);
    Mockito.doAnswer(new AccountEntriesStreamAnswer(accountData))
        .when(ledgerManagerMock)
        .fetchAccountEntriesStream(Mockito.eq(account.getIdentifier()), Matchers.anyString(), Matchers.anyString(), AdditionalMatchers.or(Matchers.eq("DESC"), Matchers.eq("ASC")));
  }


  private static Ledger cashLedger() {
    final Ledger ret = new Ledger();
    ret.setIdentifier(CASH_LEDGER_IDENTIFIER);
    ret.setParentLedgerIdentifier(ASSET_LEDGER_IDENTIFIER);
    ret.setType(AccountType.ASSET.name());
    ret.setCreatedOn(DateConverter.toIsoString(universalCreationDate));
    return ret;
  }

  private static Ledger incomeLedger() {
    final Ledger ret = new Ledger();
    ret.setIdentifier(INCOME_LEDGER_IDENTIFIER);
    ret.setType(AccountType.REVENUE.name());
    ret.setCreatedOn(DateConverter.toIsoString(universalCreationDate));
    return ret;
  }

  private static Ledger feesAndChargesLedger() {
    final Ledger ret = new Ledger();
    ret.setIdentifier(FEES_AND_CHARGES_LEDGER_IDENTIFIER);
    ret.setParentLedgerIdentifier(INCOME_LEDGER_IDENTIFIER);
    ret.setType(AccountType.REVENUE.name());
    ret.setCreatedOn(DateConverter.toIsoString(universalCreationDate));
    return ret;
  }

  private static Ledger pendingDisbursalLedger() {
    final Ledger ret = new Ledger();
    ret.setIdentifier(PENDING_DISBURSAL_LEDGER_IDENTIFIER);
    ret.setParentLedgerIdentifier(CASH_LEDGER_IDENTIFIER);
    ret.setType(AccountType.ASSET.name());
    ret.setCreatedOn(DateConverter.toIsoString(universalCreationDate));
    return ret;
  }

  private static Ledger customerLoanLedger() {
    final Ledger ret = new Ledger();
    ret.setIdentifier(CUSTOMER_LOAN_LEDGER_IDENTIFIER);
    ret.setParentLedgerIdentifier(CASH_LEDGER_IDENTIFIER);
    ret.setType(AccountType.ASSET.name());
    ret.setCreatedOn(DateConverter.toIsoString(universalCreationDate));
    return ret;
  }

  private static Ledger loanIncomeLedger() {
    final Ledger ret = new Ledger();
    ret.setIdentifier(LOAN_INCOME_LEDGER_IDENTIFIER);
    ret.setParentLedgerIdentifier(INCOME_LEDGER_IDENTIFIER);
    ret.setType(AccountType.REVENUE.name());
    ret.setCreatedOn(DateConverter.toIsoString(universalCreationDate));
    return ret;

  }

  private static Ledger accruedIncomeLedger() {
    final Ledger ret = new Ledger();
    ret.setIdentifier(ACCRUED_INCOME_LEDGER_IDENTIFIER);
    ret.setParentLedgerIdentifier(ASSET_LEDGER_IDENTIFIER);
    ret.setType(AccountType.ASSET.name());
    ret.setCreatedOn(DateConverter.toIsoString(universalCreationDate));
    return ret;

  }

  private static Account loanFundsSourceAccount() {
    final Account ret = new Account();
    ret.setIdentifier(LOAN_FUNDS_SOURCE_ACCOUNT_IDENTIFIER);
    ret.setLedger(CASH_LEDGER_IDENTIFIER);
    ret.setType(AccountType.ASSET.name());
    return ret;
  }

  private static Account processingFeeIncomeAccount() {
    final Account ret = new Account();
    ret.setIdentifier(PROCESSING_FEE_INCOME_ACCOUNT_IDENTIFIER);
    ret.setLedger(FEES_AND_CHARGES_LEDGER_IDENTIFIER);
    ret.setType(AccountType.REVENUE.name());
    return ret;
  }

  private static Account loanOriginationFeesIncomeAccount() {
    final Account ret = new Account();
    ret.setIdentifier(LOAN_ORIGINATION_FEES_ACCOUNT_IDENTIFIER);
    ret.setLedger(FEES_AND_CHARGES_LEDGER_IDENTIFIER);
    ret.setType(AccountType.REVENUE.name());
    return ret;
  }

  private static Account disbursementFeeIncomeAccount() {
    final Account ret = new Account();
    ret.setIdentifier(DISBURSEMENT_FEE_INCOME_ACCOUNT_IDENTIFIER);
    ret.setLedger(FEES_AND_CHARGES_LEDGER_IDENTIFIER);
    ret.setType(AccountType.REVENUE.name());
    return ret;
  }

  private static Account tellerOneAccount() {
    final Account ret = new Account();
    ret.setIdentifier(TELLER_ONE_ACCOUNT_IDENTIFIER);
    ret.setLedger(CASH_LEDGER_IDENTIFIER);
    ret.setType(AccountType.ASSET.name());
    return ret;
  }

  private static Account loanInterestAccrualAccount() {
    final Account ret = new Account();
    ret.setIdentifier(LOAN_INTEREST_ACCRUAL_ACCOUNT_IDENTIFIER);
    ret.setLedger(ACCRUED_INCOME_LEDGER_IDENTIFIER);
    ret.setType(AccountType.ASSET.name());
    return ret;
  }

  private static Account consumerLoanInterestAccount() {
    final Account ret = new Account();
    ret.setIdentifier(CONSUMER_LOAN_INTEREST_ACCOUNT_IDENTIFIER);
    ret.setLedger(LOAN_INCOME_LEDGER_IDENTIFIER);
    ret.setType(AccountType.REVENUE.name());
    return ret;
  }

  private static Account loansPayableAccount() {
    final Account ret = new Account();
    ret.setIdentifier(LOANS_PAYABLE_ACCOUNT_IDENTIFIER);
    //ret.setLedger(LOAN_INCOME_LEDGER_IDENTIFIER);
    ret.setType(AccountType.LIABILITY.name());
    return ret;
  }

  private static Account lateFeeIncomeAccount() {
    final Account ret = new Account();
    ret.setIdentifier(LATE_FEE_INCOME_ACCOUNT_IDENTIFIER);
    ret.setLedger(FEES_AND_CHARGES_LEDGER_IDENTIFIER);
    ret.setType(AccountType.LIABILITY.name()); //TODO: ??
    return ret;
  }

  private static Account lateFeeAccrualAccount() {
    final Account ret = new Account();
    ret.setIdentifier(LATE_FEE_ACCRUAL_ACCOUNT_IDENTIFIER);
    ret.setLedger(ACCRUED_INCOME_LEDGER_IDENTIFIER);
    ret.setType(AccountType.LIABILITY.name()); //TODO: ??
    return ret;
  }

  private static Account arrearsAllowanceAccount() {
    final Account ret = new Account();
    ret.setIdentifier(ARREARS_ALLOWANCE_ACCOUNT_IDENTIFIER);
    //ret.setLedger(LOAN_INCOME_LEDGER_IDENTIFIER); //TODO: ??
    ret.setType(AccountType.LIABILITY.name()); //TODO: ??
    return ret;
  }

  private static AccountPage customerLoanAccountsPage() {
    final Account customerLoanAccount1 = new Account();
    customerLoanAccount1.setIdentifier("customerLoanAccount1");
    final Account customerLoanAccount2 = new Account();
    customerLoanAccount2.setIdentifier("customerLoanAccount2");
    final Account customerLoanAccount3 = new Account();
    customerLoanAccount3.setIdentifier("customerLoanAccount3");

    final AccountPage ret = new AccountPage();
    ret.setTotalElements(3L);
    ret.setTotalPages(1);
    ret.setAccounts(Arrays.asList(customerLoanAccount1, customerLoanAccount2, customerLoanAccount3));
    return ret;
  }

  private static Object pendingDisbursalAccountsPage() {
    final Account pendingDisbursalAccount1 = new Account();
    pendingDisbursalAccount1.setIdentifier("pendingDisbursalAccount1");

    final Account pendingDisbursalAccount2 = new Account();
    pendingDisbursalAccount2.setIdentifier("pendingDisbursalAccount2");

    final Account pendingDisbursalAccount3 = new Account();
    pendingDisbursalAccount3.setIdentifier("pendingDisbursalAccount3");

    final AccountPage ret = new AccountPage();
    ret.setTotalElements(3L);
    ret.setTotalPages(1);
    ret.setAccounts(Arrays.asList(pendingDisbursalAccount1, pendingDisbursalAccount2, pendingDisbursalAccount3));
    return ret;
  }

  private static <T> Valid<T> isValid() {
    return new Valid<>();
  }

  private static class Valid<T> extends ArgumentMatcher<T> {
    @Override
    public boolean matches(final Object argument) {
      if (argument == null)
        return false;
      final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
      final Set errors = validator.validate(argument);

      return errors.size() == 0;
    }
  }

  private static class AccountMatcher extends ArgumentMatcher<Account> {
    private final String ledgerIdentifer;
    private final AccountType type;
    private Account matchedArgument;

    private AccountMatcher(final String ledgerIdentifier, final AccountType type) {
      this.ledgerIdentifer = ledgerIdentifier;
      this.type = type;
      this.matchedArgument = null; //Set when matches called and returns true.
    }

    @Override
    public boolean matches(final Object argument) {
      if (argument == null)
        return false;
      if (! (argument instanceof Account))
        return false;

      final Account checkedArgument = (Account) argument;

      final boolean ret = checkedArgument.getLedger().equals(ledgerIdentifer) &&
          checkedArgument.getType().equals(type.name()) &&
          checkedArgument.getBalance() == 0.0;

      if (ret)
        matchedArgument = checkedArgument;

      return ret;
    }

    Account getMatchedArgument() {
      return matchedArgument;
    }
  }

  private static class JournalEntryMatcher extends ArgumentMatcher<JournalEntry> {
    private final Set<Debtor> debtors;
    private final Set<Creditor> creditors;
    private final String transactionPrefix;
    private JournalEntry checkedArgument;

    private JournalEntryMatcher(final Set<Debtor> debtors,
                                final Set<Creditor> creditors,
                                final String productIdentifier,
                                final String caseIdentifier,
                                final Action action) {
      this.debtors = debtors;
      this.creditors = creditors;
      this.checkedArgument = null; //Set when matches called.
      this.transactionPrefix = "portfolio." + productIdentifier + "." + caseIdentifier + "." + action.name();
    }

    @Override
    public boolean matches(final Object argument) {
      if (argument == null)
        return false;
      if (! (argument instanceof JournalEntry))
        return false;

      checkedArgument = (JournalEntry) argument;

      return this.debtors.equals(checkedArgument.getDebtors()) &&
          this.creditors.equals(checkedArgument.getCreditors()) &&
          checkedArgument.getTransactionIdentifier().startsWith(transactionPrefix);
    }

    @Override
    public void describeTo(final Description description) {
      description.appendText(this.toString());
    }

    @Override
    public String toString() {
      return "JournalEntryMatcher{" +
              "debtors=" + debtors +
              ", creditors=" + creditors +
              '}';
    }
  }

  private static class CreateJournalEntryAnswer implements Answer {
    @Override
    public Void answer(final InvocationOnMock invocation) throws Throwable {
      final JournalEntry journalEntry = invocation.getArgumentAt(0, JournalEntry.class);
      journalEntry.getCreditors().forEach(creditor ->
          accountMap.get(creditor.getAccountNumber()).addAccountEntry(
              journalEntry.getMessage(),
              journalEntry.getTransactionDate(),
              Double.valueOf(creditor.getAmount())));
      journalEntry.getDebtors().forEach(debtor ->
          accountMap.get(debtor.getAccountNumber()).addAccountEntry(
              journalEntry.getMessage(),
              journalEntry.getTransactionDate(),
              Double.valueOf(debtor.getAmount())));
      return null;
    }
  }

  private static class FindAccountAnswer implements Answer {
    @Override
    public Account answer(final InvocationOnMock invocation) throws Throwable {
      final String identifier = invocation.getArgumentAt(0, String.class);
      final AccountData ret = accountMap.get(identifier);
      if (ret != null)
        return ret.account;
      else
        throw new NotFoundException("Account '" + identifier + "' not found.");
    }
  }

  private static class CreateAccountAnswer implements Answer {
    @Override
    public Void answer(final InvocationOnMock invocation) throws Throwable {
      final Account account = invocation.getArgumentAt(0, Account.class);
      makeAccountResponsive(account, LocalDateTime.now(), (LedgerManager) invocation.getMock());
      return null;
    }
  }

  static class AccountEntriesStreamAnswer implements Answer {
    private final AccountData accountData;

    AccountEntriesStreamAnswer(final AccountData accountData) {
      this.accountData = accountData;
    }

    @Override
    public Stream<AccountEntry> answer(final InvocationOnMock invocation) throws Throwable {
      final String message = invocation.getArgumentAt(2, String.class);
      final String direction = invocation.getArgumentAt(3, String.class);
      final boolean asc = direction == null || direction.equals("ASC");
      final List<AccountEntry> accountEntries = accountData.copyAccountEntries();
      final int entryCount = accountEntries.size();
      final Stream<AccountEntry> orderedCorrectly = asc ?
          IntStream.rangeClosed(1, entryCount).mapToObj(i -> accountEntries.get(entryCount - i)) :
          accountEntries.stream();

      if (message != null) {
        return orderedCorrectly.filter(x -> x.getMessage().equals(message));
      }
      else {
        return orderedCorrectly;
      }
    }
  }

  static void mockAccountingPrereqs(final LedgerManager ledgerManagerMock) {
    makeAccountResponsive(loanFundsSourceAccount(), universalCreationDate, ledgerManagerMock);
    makeAccountResponsive(loanOriginationFeesIncomeAccount(), universalCreationDate, ledgerManagerMock);
    makeAccountResponsive(processingFeeIncomeAccount(), universalCreationDate, ledgerManagerMock);
    makeAccountResponsive(disbursementFeeIncomeAccount(), universalCreationDate, ledgerManagerMock);
    makeAccountResponsive(tellerOneAccount(), universalCreationDate, ledgerManagerMock);
    makeAccountResponsive(loanInterestAccrualAccount(), universalCreationDate, ledgerManagerMock);
    makeAccountResponsive(consumerLoanInterestAccount(), universalCreationDate, ledgerManagerMock);
    makeAccountResponsive(loansPayableAccount(), universalCreationDate, ledgerManagerMock);
    makeAccountResponsive(lateFeeIncomeAccount(), universalCreationDate, ledgerManagerMock);
    makeAccountResponsive(lateFeeAccrualAccount(), universalCreationDate, ledgerManagerMock);
    makeAccountResponsive(arrearsAllowanceAccount(), universalCreationDate, ledgerManagerMock);

    Mockito.doReturn(incomeLedger()).when(ledgerManagerMock).findLedger(INCOME_LEDGER_IDENTIFIER);
    Mockito.doReturn(feesAndChargesLedger()).when(ledgerManagerMock).findLedger(FEES_AND_CHARGES_LEDGER_IDENTIFIER);
    Mockito.doReturn(cashLedger()).when(ledgerManagerMock).findLedger(CASH_LEDGER_IDENTIFIER);
    Mockito.doReturn(pendingDisbursalLedger()).when(ledgerManagerMock).findLedger(PENDING_DISBURSAL_LEDGER_IDENTIFIER);
    Mockito.doReturn(customerLoanLedger()).when(ledgerManagerMock).findLedger(CUSTOMER_LOAN_LEDGER_IDENTIFIER);
    Mockito.doReturn(loanIncomeLedger()).when(ledgerManagerMock).findLedger(LOAN_INCOME_LEDGER_IDENTIFIER);
    Mockito.doReturn(accruedIncomeLedger()).when(ledgerManagerMock).findLedger(ACCRUED_INCOME_LEDGER_IDENTIFIER);
    Mockito.doReturn(customerLoanAccountsPage()).when(ledgerManagerMock).fetchAccountsOfLedger(Mockito.eq(CUSTOMER_LOAN_LEDGER_IDENTIFIER),
            Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
    Mockito.doReturn(pendingDisbursalAccountsPage()).when(ledgerManagerMock).fetchAccountsOfLedger(Mockito.eq(PENDING_DISBURSAL_LEDGER_IDENTIFIER),
            Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());

    Mockito.doAnswer(new FindAccountAnswer()).when(ledgerManagerMock).findAccount(Matchers.anyString());
    Mockito.doAnswer(new CreateAccountAnswer()).when(ledgerManagerMock).createAccount(Matchers.any());
    Mockito.doAnswer(new CreateJournalEntryAnswer()).when(ledgerManagerMock).createJournalEntry(Matchers.any(JournalEntry.class));
  }

  static void mockBalance(final String accountIdentifier, final BigDecimal balance) {
    accountMap.get(accountIdentifier).setBalance(balance.doubleValue());
  }

  static String verifyAccountCreation(final LedgerManager ledgerManager,
                                      final String ledgerIdentifier,
                                      final AccountType type) {
    final AccountMatcher specifiesCorrectAccount = new AccountMatcher(ledgerIdentifier, type);
    Mockito.verify(ledgerManager).createAccount(AdditionalMatchers.and(argThat(isValid()), argThat(specifiesCorrectAccount)));
    return specifiesCorrectAccount.getMatchedArgument().getIdentifier();
  }

  static void verifyTransfer(final LedgerManager ledgerManager,
                             final String fromAccountIdentifier,
                             final String toAccountIdentifier,
                             final BigDecimal amount,
                             final String productIdentifier,
                             final String caseIdentifier,
                             final Action action) {
    final JournalEntryMatcher specifiesCorrectJournalEntry = new JournalEntryMatcher(
        Collections.singleton(new Debtor(fromAccountIdentifier, amount.toPlainString())),
        Collections.singleton(new Creditor(toAccountIdentifier, amount.toPlainString())),
        productIdentifier, caseIdentifier, action);
    Mockito.verify(ledgerManager).createJournalEntry(AdditionalMatchers.and(argThat(isValid()), argThat(specifiesCorrectJournalEntry)));
  }

  static void verifyTransfer(final LedgerManager ledgerManager,
                             final Set<Debtor> debtors,
                             final Set<Creditor> creditors,
                             final String productIdentifier,
                             final String caseIdentifier,
                             final Action action) {
    final Set<Debtor> filteredDebtors = debtors.stream().filter(x -> BigDecimal.valueOf(Double.valueOf(x.getAmount())).compareTo(BigDecimal.ZERO) != 0).collect(Collectors.toSet());
    final Set<Creditor> filteredCreditors = creditors.stream().filter(x -> BigDecimal.valueOf(Double.valueOf(x.getAmount())).compareTo(BigDecimal.ZERO) != 0).collect(Collectors.toSet());
    final JournalEntryMatcher specifiesCorrectJournalEntry = new JournalEntryMatcher(filteredDebtors, filteredCreditors, productIdentifier, caseIdentifier, action);
    Mockito.verify(ledgerManager, Mockito.atLeastOnce()).createJournalEntry(AdditionalMatchers.and(argThat(isValid()), argThat(specifiesCorrectJournalEntry)));

  }
}