/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.fineract.cn.teller;

import com.google.common.collect.Lists;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.fineract.cn.accounting.api.v1.domain.Account;
import org.apache.fineract.cn.accounting.api.v1.domain.AccountEntry;
import org.apache.fineract.cn.accounting.api.v1.domain.AccountEntryPage;
import org.apache.fineract.cn.accounting.api.v1.domain.JournalEntry;
import org.apache.fineract.cn.lang.DateRange;
import org.apache.fineract.cn.teller.api.v1.EventConstants;
import org.apache.fineract.cn.teller.api.v1.client.TellerValidationException;
import org.apache.fineract.cn.teller.api.v1.domain.Teller;
import org.apache.fineract.cn.teller.api.v1.domain.TellerDenomination;
import org.apache.fineract.cn.teller.api.v1.domain.TellerManagementCommand;
import org.apache.fineract.cn.teller.api.v1.domain.UnlockDrawerCommand;
import org.apache.fineract.cn.teller.util.TellerGenerator;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mockito;

import java.math.BigDecimal;
import java.time.Clock;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;

public class TestTellerDenomination extends AbstractTellerTest {

  public TestTellerDenomination() {
    super();
  }

  @Test
  public void shouldProcessDenomination() throws Exception {
    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
    final BigDecimal openingAmount = BigDecimal.valueOf(20000.00D);

    final Teller teller = this.prepareTeller(officeIdentifier, openingAmount);

    super.testSubject.post(teller.getCode(), "PAUSE");
    Assert.assertTrue(super.eventRecorder.wait(EventConstants.PAUSE_TELLER, teller.getCode()));

    final AccountEntry openingAmountEntry = new AccountEntry();
    openingAmountEntry.setType(AccountEntry.Type.DEBIT.name());
    openingAmountEntry.setMessage(ServiceConstants.TX_REPAYMENT);
    openingAmountEntry.setAmount(openingAmount.doubleValue());

    final AccountEntryPage accountEntryPage = new AccountEntryPage();
    accountEntryPage.setAccountEntries(Lists.newArrayList(openingAmountEntry));
    accountEntryPage.setTotalPages(1);
    accountEntryPage.setTotalElements(Integer.valueOf(accountEntryPage.getAccountEntries().size()).longValue());

    Mockito
        .doAnswer(invocation -> accountEntryPage)
        .when(super.accountingServiceSpy)
        .fetchAccountEntries(Matchers.eq(teller.getTellerAccountIdentifier()), Matchers.anyString(),
            Matchers.eq(0), Matchers.anyInt());

    final TellerDenomination tellerDenomination = new TellerDenomination();
    tellerDenomination.setCountedTotal(openingAmount);
    tellerDenomination.setNote("Nothing has happened.");

    super.testSubject.saveTellerDenomination(officeIdentifier, teller.getCode(), tellerDenomination);
    Assert.assertTrue(super.eventRecorder.wait(EventConstants.SAVE_DENOMINATION, teller.getCode()));

    Mockito
        .verify(super.accountingServiceSpy, Mockito.atMost(1))
        .postJournalEntry(Matchers.any(JournalEntry.class));

    final LocalDate now = LocalDate.now(Clock.systemUTC());
    final DateRange dateRange = new DateRange(now, now);
    final List<TellerDenomination> tellerDenominations =
        super.testSubject.fetchTellerDenominations(officeIdentifier, teller.getCode(), dateRange.toString());

    Assert.assertEquals(1, tellerDenominations.size());
    Assert.assertNull(tellerDenominations.get(0).getAdjustingJournalEntry());

    this.closeTeller(officeIdentifier, teller.getCode());
  }

  @Test
  public void shouldProcessDenominationOver() throws Exception {
    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
    final BigDecimal openingAmount = BigDecimal.valueOf(20000.00D);

    final Teller teller = this.prepareTeller(officeIdentifier, openingAmount);

    super.testSubject.post(teller.getCode(), "PAUSE");
    Assert.assertTrue(super.eventRecorder.wait(EventConstants.PAUSE_TELLER, teller.getCode()));

    final AccountEntry openingAmountEntry = new AccountEntry();
    openingAmountEntry.setType(AccountEntry.Type.DEBIT.name());
    openingAmountEntry.setMessage(ServiceConstants.TX_REPAYMENT);
    openingAmountEntry.setAmount(openingAmount.doubleValue());

    final AccountEntryPage accountEntryPage = new AccountEntryPage();
    accountEntryPage.setAccountEntries(Lists.newArrayList(openingAmountEntry));
    accountEntryPage.setTotalPages(1);
    accountEntryPage.setTotalElements(Integer.valueOf(accountEntryPage.getAccountEntries().size()).longValue());

    Mockito
        .doAnswer(invocation -> accountEntryPage)
        .when(super.accountingServiceSpy)
        .fetchAccountEntries(Matchers.eq(teller.getTellerAccountIdentifier()), Matchers.anyString(),
            Matchers.eq(0), Matchers.anyInt());

    final TellerDenomination tellerDenomination = new TellerDenomination();
    tellerDenomination.setCountedTotal(openingAmount.add(BigDecimal.valueOf(1000.00D)));
    tellerDenomination.setNote("Teller is over.");

    super.testSubject.saveTellerDenomination(officeIdentifier, teller.getCode(), tellerDenomination);
    Assert.assertTrue(super.eventRecorder.wait(EventConstants.SAVE_DENOMINATION, teller.getCode()));

    Mockito
        .verify(super.accountingServiceSpy, Mockito.atMost(2))
        .postJournalEntry(Matchers.any(JournalEntry.class));

    final LocalDate now = LocalDate.now(Clock.systemUTC());
    final DateRange dateRange = new DateRange(now, now);
    final List<TellerDenomination> tellerDenominations =
        super.testSubject.fetchTellerDenominations(officeIdentifier, teller.getCode(), dateRange.toString());

    Assert.assertEquals(1, tellerDenominations.size());
    Assert.assertNotNull(tellerDenominations.get(0).getAdjustingJournalEntry());

    this.closeTeller(officeIdentifier, teller.getCode());
  }

  @Test
  public void shouldProcessDenominationShort() throws Exception {
    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
    final BigDecimal openingAmount = BigDecimal.valueOf(20000.00D);

    final Teller teller = this.prepareTeller(officeIdentifier, openingAmount);

    super.testSubject.post(teller.getCode(), "PAUSE");
    Assert.assertTrue(super.eventRecorder.wait(EventConstants.PAUSE_TELLER, teller.getCode()));

    final AccountEntry openingAmountEntry = new AccountEntry();
    openingAmountEntry.setType(AccountEntry.Type.DEBIT.name());
    openingAmountEntry.setMessage(ServiceConstants.TX_REPAYMENT);
    openingAmountEntry.setAmount(openingAmount.doubleValue());

    final AccountEntryPage accountEntryPage = new AccountEntryPage();
    accountEntryPage.setAccountEntries(Lists.newArrayList(openingAmountEntry));
    accountEntryPage.setTotalPages(1);
    accountEntryPage.setTotalElements(Integer.valueOf(accountEntryPage.getAccountEntries().size()).longValue());

    Mockito
        .doAnswer(invocation -> accountEntryPage)
        .when(super.accountingServiceSpy)
        .fetchAccountEntries(Matchers.eq(teller.getTellerAccountIdentifier()), Matchers.anyString(),
            Matchers.eq(0), Matchers.anyInt());

    final TellerDenomination tellerDenomination = new TellerDenomination();
    tellerDenomination.setCountedTotal(openingAmount.subtract(BigDecimal.valueOf(1000.00D)));
    tellerDenomination.setNote("Teller is short.");

    super.testSubject.saveTellerDenomination(officeIdentifier, teller.getCode(), tellerDenomination);
    Assert.assertTrue(super.eventRecorder.wait(EventConstants.SAVE_DENOMINATION, teller.getCode()));

    Mockito
        .verify(super.accountingServiceSpy, Mockito.atMost(2))
        .postJournalEntry(Matchers.any(JournalEntry.class));

    final LocalDate now = LocalDate.now(Clock.systemUTC());
    final DateRange dateRange = new DateRange(now, now);
    final List<TellerDenomination> tellerDenominations =
        super.testSubject.fetchTellerDenominations(officeIdentifier, teller.getCode(), dateRange.toString());

    Assert.assertEquals(1, tellerDenominations.size());
    Assert.assertNotNull(tellerDenominations.get(0).getAdjustingJournalEntry());

    this.closeTeller(officeIdentifier, teller.getCode());
  }

  @Test
  public void shouldNotProcessDenominationIsActive() throws Exception {
    final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
    final BigDecimal openingAmount = BigDecimal.valueOf(20000.00D);

    final Teller teller = this.prepareTeller(officeIdentifier, openingAmount);

    final TellerDenomination tellerDenomination = new TellerDenomination();
    tellerDenomination.setCountedTotal(openingAmount.subtract(BigDecimal.valueOf(1000.00D)));

    try {
      super.testSubject.saveTellerDenomination(officeIdentifier, teller.getCode(), tellerDenomination);
      Assert.fail();
    } catch (final TellerValidationException tvex) {
      // do nothing ... expected
    }

    this.closeTeller(officeIdentifier, teller.getCode());
  }

  private Teller prepareTeller(final String officeIdentifier, BigDecimal openingAmount)  throws Exception {
    final Teller teller = TellerGenerator.createRandomTeller();

    Mockito.doAnswer(invocation -> true)
        .when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));

    Mockito.doAnswer(invocation -> Optional.of(new Account()))
        .when(super.accountingServiceSpy).findAccount(Matchers.eq(teller.getTellerAccountIdentifier()));

    Mockito.doAnswer(invocation -> Optional.of(new Account()))
        .when(super.accountingServiceSpy).findAccount(Matchers.eq(teller.getVaultAccountIdentifier()));

    Mockito.doAnswer(invocation -> Optional.of(new Account()))
        .when(super.accountingServiceSpy).findAccount(Matchers.eq(teller.getChequesReceivableAccount()));

    Mockito.doAnswer(invocation -> Optional.of(new Account()))
        .when(super.accountingServiceSpy).findAccount(Matchers.eq(teller.getCashOverShortAccount()));

    super.testSubject.create(officeIdentifier, teller);

    Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode()));

    final TellerManagementCommand command = new TellerManagementCommand();
    command.setAction(TellerManagementCommand.Action.OPEN.name());
    command.setAdjustment(TellerManagementCommand.Adjustment.DEBIT.name());
    command.setAmount(openingAmount);
    command.setAssignedEmployeeIdentifier(AbstractTellerTest.TEST_USER);

    Mockito.doAnswer(invocation -> true)
        .when(super.organizationServiceSpy).employeeExists(Matchers.eq(command.getAssignedEmployeeIdentifier()));

    super.testSubject.post(officeIdentifier, teller.getCode(), command);

    Assert.assertTrue(super.eventRecorder.wait(EventConstants.OPEN_TELLER, teller.getCode()));

    final UnlockDrawerCommand unlockDrawerCommand = new UnlockDrawerCommand();
    unlockDrawerCommand.setEmployeeIdentifier(AbstractTellerTest.TEST_USER);
    unlockDrawerCommand.setPassword(teller.getPassword());

    super.testSubject.unlockDrawer(teller.getCode(), unlockDrawerCommand);

    Assert.assertTrue(super.eventRecorder.wait(EventConstants.AUTHENTICATE_TELLER, teller.getCode()));

    return teller;
  }

  private void closeTeller(final String officeIdentifier, final String tellerCode) throws Exception {
    final TellerManagementCommand closeTellerCommand = new TellerManagementCommand();
    closeTellerCommand.setAction(TellerManagementCommand.Action.CLOSE.name());
    closeTellerCommand.setAmount(BigDecimal.ZERO);
    closeTellerCommand.setAdjustment(TellerManagementCommand.Adjustment.NONE.name());

    super.testSubject.post(officeIdentifier, tellerCode, closeTellerCommand);
    Assert.assertTrue(super.eventRecorder.wait(EventConstants.CLOSE_TELLER, tellerCode));

  }
}
