/*
 * 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.Clock;
import java.time.LocalDateTime;
import java.util.*;
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 ="8530";
  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);
    }

    void addAccountEntry(final String message, final double amount) {
      final AccountEntry accountEntry = new AccountEntry();
      accountEntry.setAmount(amount);
      accountEntry.setMessage(message);
      accountEntry.setTransactionDate(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
      accountEntries.add(accountEntry);
    }
  }

  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(), 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(),
              Double.valueOf(creditor.getAmount())));
      journalEntry.getDebtors().forEach(debtor ->
          accountMap.get(debtor.getAccountNumber()).addAccountEntry(
              journalEntry.getMessage(),
              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);
      if (message != null)
        return accountData.accountEntries.stream().filter(x -> x.getMessage().equals(message));
      else
        return accountData.accountEntries.stream();
    }
  }

  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 JournalEntryMatcher specifiesCorrectJournalEntry = new JournalEntryMatcher(debtors, creditors, productIdentifier, caseIdentifier, action);
    Mockito.verify(ledgerManager).createJournalEntry(AdditionalMatchers.and(argThat(isValid()), argThat(specifiesCorrectJournalEntry)));

  }
}