/**
 * 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.test.stepdef.loan;

import static org.apache.fineract.test.data.TransactionProcessingStrategyCode.ADVANCED_PAYMENT_ALLOCATION;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;

import com.google.gson.Gson;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.cucumber.datatable.DataTable;
import io.cucumber.java.en.And;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.avro.loan.v1.LoanAccountDataV1;
import org.apache.fineract.avro.loan.v1.LoanChargePaidByDataV1;
import org.apache.fineract.avro.loan.v1.LoanStatusEnumDataV1;
import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1;
import org.apache.fineract.client.models.AdvancedPaymentData;
import org.apache.fineract.client.models.DeleteLoansLoanIdResponse;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdDelinquencySummary;
import org.apache.fineract.client.models.GetLoansLoanIdLoanChargeData;
import org.apache.fineract.client.models.GetLoansLoanIdLoanChargePaidByData;
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule;
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdTimeline;
import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse;
import org.apache.fineract.client.models.IsCatchUpRunningResponse;
import org.apache.fineract.client.models.PostClientsResponse;
import org.apache.fineract.client.models.PostLoansLoanIdRequest;
import org.apache.fineract.client.models.PostLoansLoanIdResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
import org.apache.fineract.client.models.PostLoansRequest;
import org.apache.fineract.client.models.PostLoansResponse;
import org.apache.fineract.client.models.PutLoanProductsProductIdRequest;
import org.apache.fineract.client.models.PutLoanProductsProductIdResponse;
import org.apache.fineract.client.models.PutLoansLoanIdRequest;
import org.apache.fineract.client.models.PutLoansLoanIdResponse;
import org.apache.fineract.client.services.LoanCobCatchUpApi;
import org.apache.fineract.client.services.LoanProductsApi;
import org.apache.fineract.client.services.LoanTransactionsApi;
import org.apache.fineract.client.services.LoansApi;
import org.apache.fineract.client.util.JSON;
import org.apache.fineract.test.data.AmortizationType;
import org.apache.fineract.test.data.InterestCalculationPeriodTime;
import org.apache.fineract.test.data.InterestType;
import org.apache.fineract.test.data.LoanStatus;
import org.apache.fineract.test.data.LoanTermFrequencyType;
import org.apache.fineract.test.data.RepaymentFrequencyType;
import org.apache.fineract.test.data.TransactionProcessingStrategyCode;
import org.apache.fineract.test.data.TransactionType;
import org.apache.fineract.test.data.loanproduct.DefaultLoanProduct;
import org.apache.fineract.test.data.loanproduct.LoanProductResolver;
import org.apache.fineract.test.data.paymenttype.DefaultPaymentType;
import org.apache.fineract.test.data.paymenttype.PaymentTypeResolver;
import org.apache.fineract.test.factory.LoanRequestFactory;
import org.apache.fineract.test.helper.ErrorHelper;
import org.apache.fineract.test.helper.ErrorMessageHelper;
import org.apache.fineract.test.helper.ErrorResponse;
import org.apache.fineract.test.helper.Utils;
import org.apache.fineract.test.initializer.global.LoanProductGlobalInitializerStep;
import org.apache.fineract.test.messaging.EventAssertion;
import org.apache.fineract.test.messaging.event.EventCheckHelper;
import org.apache.fineract.test.messaging.event.loan.LoanStatusChangedEvent;
import org.apache.fineract.test.messaging.event.loan.transaction.LoanAccrualTransactionCreatedBusinessEvent;
import org.apache.fineract.test.messaging.event.loan.transaction.LoanChargeOffEvent;
import org.apache.fineract.test.messaging.event.loan.transaction.LoanChargeOffUndoEvent;
import org.apache.fineract.test.stepdef.AbstractStepDef;
import org.apache.fineract.test.support.TestContextKey;
import org.springframework.beans.factory.annotation.Autowired;
import retrofit2.Response;

@Slf4j
public class LoanStepDef extends AbstractStepDef {

    public static final String DATE_FORMAT = "dd MMMM yyyy";
    public static final String DATE_FORMAT_EVENTS = "yyyy-MM-dd";
    public static final String DEFAULT_LOCALE = "en";
    public static final String LOAN_STATE_SUBMITTED_AND_PENDING = "Submitted and pending approval";
    public static final String LOAN_STATE_APPROVED = "Approved";
    public static final String LOAN_STATE_ACTIVE = "Active";
    private static final Gson GSON = new JSON().getGson();
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT);
    private static final DateTimeFormatter FORMATTER_EVENTS = DateTimeFormatter.ofPattern(DATE_FORMAT_EVENTS);

    @Autowired
    private LoansApi loansApi;

    @Autowired
    private LoanCobCatchUpApi loanCobCatchUpApi;

    @Autowired
    private LoanTransactionsApi loanTransactionsApi;

    @Autowired
    private EventAssertion eventAssertion;

    @Autowired
    private PaymentTypeResolver paymentTypeResolver;

    @Autowired
    private LoanProductResolver loanProductResolver;

    @Autowired
    private LoanRequestFactory loanRequestFactory;

    @Autowired
    private EventCheckHelper eventCheckHelper;

    @Autowired
    private LoanProductsApi loanProductsApi;

    @When("Admin creates a new Loan")
    public void createLoan() throws IOException {
        Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
        Long clientId = clientResponse.body().getClientId();
        PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId);

        Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
        testContext().set(TestContextKey.LOAN_CREATE_RESPONSE, response);
        ErrorHelper.checkSuccessfulApiCall(response);

        eventCheckHelper.createLoanEventCheck(response);
    }

    @When("Admin creates a new default Loan with date: {string}")
    public void createLoanWithDate(String date) throws IOException {
        Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
        Long clientId = clientResponse.body().getClientId();
        PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId).submittedOnDate(date)
                .expectedDisbursementDate(date);

        Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
        testContext().set(TestContextKey.LOAN_CREATE_RESPONSE, response);
        ErrorHelper.checkSuccessfulApiCall(response);

        eventCheckHelper.createLoanEventCheck(response);
    }

    @When("Admin crates a second default loan with date: {string}")
    public void createSecondLoanWithDate(String date) throws IOException {
        Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
        Long clientId = clientResponse.body().getClientId();
        PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId).submittedOnDate(date)
                .expectedDisbursementDate(date);

        Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
        testContext().set(TestContextKey.LOAN_CREATE_SECOND_LOAN_RESPONSE, response);
        ErrorHelper.checkSuccessfulApiCall(response);

        eventCheckHelper.createLoanEventCheck(response);
    }

    @When("Admin crates a second default loan for the second client with date: {string}")
    public void createSecondLoanForSecondClientWithDate(String date) throws IOException {
        Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_SECOND_CLIENT_RESPONSE);
        Long clientId = clientResponse.body().getClientId();
        PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId).submittedOnDate(date)
                .expectedDisbursementDate(date);

        Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
        testContext().set(TestContextKey.LOAN_CREATE_SECOND_LOAN_RESPONSE, response);
        ErrorHelper.checkSuccessfulApiCall(response);

        eventCheckHelper.createLoanEventCheck(response);
    }

    /**
     * Use this where inline COB run needed - this way we don't have to run inline COB for all 30 days of loan term, but
     * only 1 day
     */
    @When("Admin creates a new Loan with date: {string} and with 1 day loan term and repayment")
    public void createLoanWithDateShortTerm(String date) throws IOException {
        Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
        Long clientId = clientResponse.body().getClientId();
        PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId)//
                .submittedOnDate(date)//
                .expectedDisbursementDate(date)//
                .loanTermFrequency(1)//
                .repaymentEvery(1);//

        Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
        testContext().set(TestContextKey.LOAN_CREATE_RESPONSE, response);
        ErrorHelper.checkSuccessfulApiCall(response);
    }

    @When("Customer makes {string} transaction with {string} payment type on {string} with {double} EUR transaction amount and self-generated Idempotency key")
    public void createTransactionWithIdempotencyKey(String transactionTypeInput, String transactionPaymentType, String transactionDate,
            double transactionAmount) throws IOException {
        createTransactionWithIdempotencyKeyAndExternalOwnerCheck(transactionTypeInput, transactionPaymentType, transactionDate,
                transactionAmount, null);
    }

    @When("Customer makes {string} transaction with {string} payment type on {string} with {double} EUR transaction amount and self-generated Idempotency key and check external owner")
    public void createTransactionWithIdempotencyKeyAndWithExternalOwner(String transactionTypeInput, String transactionPaymentType,
            String transactionDate, double transactionAmount) throws IOException {
        String transferExternalOwnerId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID);
        createTransactionWithIdempotencyKeyAndExternalOwnerCheck(transactionTypeInput, transactionPaymentType, transactionDate,
                transactionAmount, transferExternalOwnerId);
    }

    private void createTransactionWithIdempotencyKeyAndExternalOwnerCheck(String transactionTypeInput, String transactionPaymentType,
            String transactionDate, double transactionAmount, String externalOwnerId) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        TransactionType transactionType = TransactionType.valueOf(transactionTypeInput);
        String transactionTypeValue = transactionType.getValue();
        DefaultPaymentType paymentType = DefaultPaymentType.valueOf(transactionPaymentType);
        Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);

        PostLoansLoanIdTransactionsRequest paymentTransactionRequest = LoanRequestFactory.defaultPaymentTransactionRequest()
                .transactionDate(transactionDate).transactionAmount(transactionAmount).paymentTypeId(paymentTypeValue);

        Map<String, String> headerMap = new HashMap<>();
        String idempotencyKey = UUID.randomUUID().toString();
        testContext().set(TestContextKey.TRANSACTION_IDEMPOTENCY_KEY, idempotencyKey);
        headerMap.put("Idempotency-Key", idempotencyKey);

        Response<PostLoansLoanIdTransactionsResponse> paymentTransactionResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, paymentTransactionRequest, transactionTypeValue, headerMap).execute();
        testContext().set(TestContextKey.LOAN_PAYMENT_TRANSACTION_RESPONSE, paymentTransactionResponse);
        ErrorHelper.checkSuccessfulApiCall(paymentTransactionResponse);

        eventCheckHelper.transactionEventCheck(paymentTransactionResponse, transactionType, externalOwnerId);
    }

    @When("Admin makes {string} transaction with {string} payment type on {string} with {double} EUR transaction amount")
    public void createTransactionForRefund(String transactionTypeInput, String transactionPaymentType, String transactionDate,
            double transactionAmount) throws IOException, InterruptedException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        TransactionType transactionType = TransactionType.valueOf(transactionTypeInput);
        String transactionTypeValue = transactionType.getValue();
        DefaultPaymentType paymentType = DefaultPaymentType.valueOf(transactionPaymentType);
        Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);

        PostLoansLoanIdTransactionsRequest paymentTransactionRequest = LoanRequestFactory.defaultPaymentTransactionRequest()
                .transactionDate(transactionDate).transactionAmount(transactionAmount).paymentTypeId(paymentTypeValue);

        Response<PostLoansLoanIdTransactionsResponse> paymentTransactionResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, paymentTransactionRequest, transactionTypeValue).execute();
        testContext().set(TestContextKey.LOAN_PAYMENT_TRANSACTION_RESPONSE, paymentTransactionResponse);
        ErrorHelper.checkSuccessfulApiCall(paymentTransactionResponse);

        eventCheckHelper.transactionEventCheck(paymentTransactionResponse, transactionType, null);
    }

    @When("Customer makes {string} transaction with {string} payment type on {string} with {double} EUR transaction amount and system-generated Idempotency key")
    public void createTransactionWithAutoIdempotencyKey(String transactionTypeInput, String transactionPaymentType, String transactionDate,
            double transactionAmount) throws IOException {
        createTransactionWithAutoIdempotencyKeyAndWithExternalOwner(transactionTypeInput, transactionPaymentType, transactionDate,
                transactionAmount, null);
    }

    @When("Customer makes {string} transaction with {string} payment type on {string} with {double} EUR transaction amount and system-generated Idempotency key and check external owner")
    public void createTransactionWithAutoIdempotencyKeyWithExternalOwner(String transactionTypeInput, String transactionPaymentType,
            String transactionDate, double transactionAmount) throws IOException {
        String transferExternalOwnerId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_OWNER_EXTERNAL_ID);
        createTransactionWithAutoIdempotencyKeyAndWithExternalOwner(transactionTypeInput, transactionPaymentType, transactionDate,
                transactionAmount, transferExternalOwnerId);
    }

    private void createTransactionWithAutoIdempotencyKeyAndWithExternalOwner(String transactionTypeInput, String transactionPaymentType,
            String transactionDate, double transactionAmount, String externalOwnerId) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        TransactionType transactionType = TransactionType.valueOf(transactionTypeInput);
        String transactionTypeValue = transactionType.getValue();
        DefaultPaymentType paymentType = DefaultPaymentType.valueOf(transactionPaymentType);
        Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);

        PostLoansLoanIdTransactionsRequest paymentTransactionRequest = LoanRequestFactory.defaultPaymentTransactionRequest()
                .transactionDate(transactionDate).transactionAmount(transactionAmount).paymentTypeId(paymentTypeValue);

        Response<PostLoansLoanIdTransactionsResponse> paymentTransactionResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, paymentTransactionRequest, transactionTypeValue).execute();
        testContext().set(TestContextKey.LOAN_PAYMENT_TRANSACTION_RESPONSE, paymentTransactionResponse);
        testContext().set(TestContextKey.LOAN_REPAYMENT_RESPONSE, paymentTransactionResponse);
        ErrorHelper.checkSuccessfulApiCall(paymentTransactionResponse);

        eventCheckHelper.transactionEventCheck(paymentTransactionResponse, transactionType, externalOwnerId);
    }

    @When("Admin makes Credit Balance Refund transaction on {string} with {double} EUR transaction amount")
    public void createCBR(String transactionDate, double transactionAmount) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        String transactionTypeValue = "creditBalanceRefund";

        PostLoansLoanIdTransactionsRequest paymentTransactionRequest = LoanRequestFactory.defaultPaymentTransactionRequest()
                .transactionDate(transactionDate).transactionAmount(transactionAmount);

        Response<PostLoansLoanIdTransactionsResponse> paymentTransactionResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, paymentTransactionRequest, transactionTypeValue).execute();
        testContext().set(TestContextKey.LOAN_PAYMENT_TRANSACTION_RESPONSE, paymentTransactionResponse);
        ErrorHelper.checkSuccessfulApiCall(paymentTransactionResponse);
    }

    @Then("Credit Balance Refund transaction on future date {string} with {double} EUR transaction amount will result an error")
    public void futureDateCBRError(String transactionDate, double transactionAmount) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        int errorCodeExpected = 403;
        String errorMessageExpected = String.format("Loan: %s, Credit Balance Refund transaction cannot be created for the future.",
                loanId);

        String transactionTypeValue = "creditBalanceRefund";

        PostLoansLoanIdTransactionsRequest paymentTransactionRequest = LoanRequestFactory.defaultPaymentTransactionRequest()
                .transactionDate(transactionDate).transactionAmount(transactionAmount);

        Response<PostLoansLoanIdTransactionsResponse> paymentTransactionResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, paymentTransactionRequest, transactionTypeValue).execute();
        testContext().set(TestContextKey.LOAN_PAYMENT_TRANSACTION_RESPONSE, paymentTransactionResponse);

        int errorCodeActual = paymentTransactionResponse.code();
        String errorBody = paymentTransactionResponse.errorBody().string();
        ErrorResponse errorResponse = GSON.fromJson(errorBody, ErrorResponse.class);
        String errorMessageActual = errorResponse.getErrors().get(0).getDeveloperMessage();

        assertThat(errorCodeActual).as(ErrorMessageHelper.wrongErrorCode(errorCodeActual, errorCodeExpected)).isEqualTo(errorCodeExpected);
        assertThat(errorMessageActual).as(ErrorMessageHelper.wrongErrorMessage(errorMessageActual, errorMessageExpected))
                .isEqualTo(errorMessageExpected);

        log.info("ERROR CODE: {}", errorCodeActual);
        log.info("ERROR MESSAGE: {}", errorMessageActual);
    }

    @When("Admin creates a fully customized loan with the following data:")
    public void createFullyCustomizedLoan(DataTable table) throws IOException {
        List<List<String>> data = table.asLists();
        List<String> loanData = data.get(1);
        String loanProduct = loanData.get(0);
        String submitDate = loanData.get(1);
        String principal = loanData.get(2);
        BigDecimal interestRate = new BigDecimal(loanData.get(3));
        String interestType = loanData.get(4);
        String interestCalculationPeriod = loanData.get(5);
        String amortizationType = loanData.get(6);
        Integer loanTermFrequency = Integer.valueOf(loanData.get(7));
        String loanTermFrequencyType = loanData.get(8);
        Integer repaymentFrequency = Integer.valueOf(loanData.get(9));
        String repaymentFrequencyType = loanData.get(10);
        Integer numberOfRepayments = Integer.valueOf(loanData.get(11));
        Integer graceOnPrincipalPayment = Integer.valueOf(loanData.get(12));
        Integer graceOnInterestPayment = Integer.valueOf(loanData.get(13));
        Integer graceOnInterestCharged = Integer.valueOf(loanData.get(14));
        String transactionProcessingStrategyCode = loanData.get(15);

        Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
        Long clientId = clientResponse.body().getClientId();

        DefaultLoanProduct product = DefaultLoanProduct.valueOf(loanProduct);
        Long loanProductId = loanProductResolver.resolve(product);

        LoanTermFrequencyType termFrequencyType = LoanTermFrequencyType.valueOf(loanTermFrequencyType);
        Integer loanTermFrequencyTypeValue = termFrequencyType.getValue();

        RepaymentFrequencyType repaymentFrequencyType1 = RepaymentFrequencyType.valueOf(repaymentFrequencyType);
        Integer repaymentFrequencyTypeValue = repaymentFrequencyType1.getValue();

        InterestType interestType1 = InterestType.valueOf(interestType);
        Integer interestTypeValue = interestType1.getValue();

        InterestCalculationPeriodTime interestCalculationPeriod1 = InterestCalculationPeriodTime.valueOf(interestCalculationPeriod);
        Integer interestCalculationPeriodValue = interestCalculationPeriod1.getValue();

        AmortizationType amortizationType1 = AmortizationType.valueOf(amortizationType);
        Integer amortizationTypeValue = amortizationType1.getValue();

        TransactionProcessingStrategyCode processingStrategyCode = TransactionProcessingStrategyCode
                .valueOf(transactionProcessingStrategyCode);
        String transactionProcessingStrategyCodeValue = processingStrategyCode.getValue();

        PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId)//
                .productId(loanProductId)//
                .principal(new BigDecimal(principal))//
                .interestRatePerPeriod(interestRate)//
                .interestType(interestTypeValue)//
                .interestCalculationPeriodType(interestCalculationPeriodValue)//
                .amortizationType(amortizationTypeValue)//
                .loanTermFrequency(loanTermFrequency)//
                .loanTermFrequencyType(loanTermFrequencyTypeValue)//
                .numberOfRepayments(numberOfRepayments)//
                .repaymentEvery(repaymentFrequency)//
                .repaymentFrequencyType(repaymentFrequencyTypeValue)//
                .submittedOnDate(submitDate)//
                .expectedDisbursementDate(submitDate)//
                .graceOnPrincipalPayment(graceOnPrincipalPayment)//
                .graceOnInterestPayment(graceOnInterestPayment)//
                .graceOnInterestPayment(graceOnInterestCharged).transactionProcessingStrategyCode(transactionProcessingStrategyCodeValue);//

        Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
        testContext().set(TestContextKey.LOAN_CREATE_RESPONSE, response);
        ErrorHelper.checkSuccessfulApiCall(response);

        eventCheckHelper.createLoanEventCheck(response);
    }

    @When("Admin creates a fully customized loan with fixed length {int} and with the following data:")
    public void createFullyCustomizedLoanFixedLength(int fixedLength, DataTable table) throws IOException {
        List<List<String>> data = table.asLists();
        List<String> loanData = data.get(1);
        String loanProduct = loanData.get(0);
        String submitDate = loanData.get(1);
        String principal = loanData.get(2);
        BigDecimal interestRate = new BigDecimal(loanData.get(3));
        String interestType = loanData.get(4);
        String interestCalculationPeriod = loanData.get(5);
        String amortizationType = loanData.get(6);
        Integer loanTermFrequency = Integer.valueOf(loanData.get(7));
        String loanTermFrequencyType = loanData.get(8);
        Integer repaymentFrequency = Integer.valueOf(loanData.get(9));
        String repaymentFrequencyType = loanData.get(10);
        Integer numberOfRepayments = Integer.valueOf(loanData.get(11));
        Integer graceOnPrincipalPayment = Integer.valueOf(loanData.get(12));
        Integer graceOnInterestPayment = Integer.valueOf(loanData.get(13));
        Integer graceOnInterestCharged = Integer.valueOf(loanData.get(14));
        String transactionProcessingStrategyCode = loanData.get(15);

        Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
        Long clientId = clientResponse.body().getClientId();

        DefaultLoanProduct product = DefaultLoanProduct.valueOf(loanProduct);
        Long loanProductId = loanProductResolver.resolve(product);

        LoanTermFrequencyType termFrequencyType = LoanTermFrequencyType.valueOf(loanTermFrequencyType);
        Integer loanTermFrequencyTypeValue = termFrequencyType.getValue();

        RepaymentFrequencyType repaymentFrequencyType1 = RepaymentFrequencyType.valueOf(repaymentFrequencyType);
        Integer repaymentFrequencyTypeValue = repaymentFrequencyType1.getValue();

        InterestType interestType1 = InterestType.valueOf(interestType);
        Integer interestTypeValue = interestType1.getValue();

        InterestCalculationPeriodTime interestCalculationPeriod1 = InterestCalculationPeriodTime.valueOf(interestCalculationPeriod);
        Integer interestCalculationPeriodValue = interestCalculationPeriod1.getValue();

        AmortizationType amortizationType1 = AmortizationType.valueOf(amortizationType);
        Integer amortizationTypeValue = amortizationType1.getValue();

        TransactionProcessingStrategyCode processingStrategyCode = TransactionProcessingStrategyCode
                .valueOf(transactionProcessingStrategyCode);
        String transactionProcessingStrategyCodeValue = processingStrategyCode.getValue();

        PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId)//
                .productId(loanProductId)//
                .principal(new BigDecimal(principal))//
                .interestRatePerPeriod(interestRate)//
                .interestType(interestTypeValue)//
                .interestCalculationPeriodType(interestCalculationPeriodValue)//
                .amortizationType(amortizationTypeValue)//
                .loanTermFrequency(loanTermFrequency)//
                .loanTermFrequencyType(loanTermFrequencyTypeValue)//
                .numberOfRepayments(numberOfRepayments)//
                .repaymentEvery(repaymentFrequency)//
                .repaymentFrequencyType(repaymentFrequencyTypeValue)//
                .submittedOnDate(submitDate)//
                .expectedDisbursementDate(submitDate)//
                .graceOnPrincipalPayment(graceOnPrincipalPayment)//
                .graceOnInterestPayment(graceOnInterestPayment)//
                .graceOnInterestPayment(graceOnInterestCharged).transactionProcessingStrategyCode(transactionProcessingStrategyCodeValue)//
                .fixedLength(fixedLength);//

        Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
        testContext().set(TestContextKey.LOAN_CREATE_RESPONSE, response);
        ErrorHelper.checkSuccessfulApiCall(response);

        eventCheckHelper.createLoanEventCheck(response);
    }

    @When("Admin creates a fully customized loan with Advanced payment allocation and with product no Advanced payment allocation set results an error:")
    public void createFullyCustomizedLoanNoAdvancedPaymentError(DataTable table) throws IOException {
        int errorCodeExpected = 400;
        String errorMessageExpected = "Failed data validation due to: strategy.cannot.be.advanced.payment.allocation.if.not.configured.";

        List<List<String>> data = table.asLists();
        List<String> loanData = data.get(1);
        String loanProduct = loanData.get(0);
        String submitDate = loanData.get(1);
        String principal = loanData.get(2);
        BigDecimal interestRate = new BigDecimal(loanData.get(3));
        String interestType = loanData.get(4);
        String interestCalculationPeriod = loanData.get(5);
        String amortizationType = loanData.get(6);
        Integer loanTermFrequency = Integer.valueOf(loanData.get(7));
        String loanTermFrequencyType = loanData.get(8);
        Integer repaymentFrequency = Integer.valueOf(loanData.get(9));
        String repaymentFrequencyType = loanData.get(10);
        Integer numberOfRepayments = Integer.valueOf(loanData.get(11));
        Integer graceOnPrincipalPayment = Integer.valueOf(loanData.get(12));
        Integer graceOnInterestPayment = Integer.valueOf(loanData.get(13));
        Integer graceOnInterestCharged = Integer.valueOf(loanData.get(14));
        String transactionProcessingStrategyCode = loanData.get(15);

        Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
        Long clientId = clientResponse.body().getClientId();

        DefaultLoanProduct product = DefaultLoanProduct.valueOf(loanProduct);
        Long loanProductId = loanProductResolver.resolve(product);

        LoanTermFrequencyType termFrequencyType = LoanTermFrequencyType.valueOf(loanTermFrequencyType);
        Integer loanTermFrequencyTypeValue = termFrequencyType.getValue();

        RepaymentFrequencyType repaymentFrequencyType1 = RepaymentFrequencyType.valueOf(repaymentFrequencyType);
        Integer repaymentFrequencyTypeValue = repaymentFrequencyType1.getValue();

        InterestType interestType1 = InterestType.valueOf(interestType);
        Integer interestTypeValue = interestType1.getValue();

        InterestCalculationPeriodTime interestCalculationPeriod1 = InterestCalculationPeriodTime.valueOf(interestCalculationPeriod);
        Integer interestCalculationPeriodValue = interestCalculationPeriod1.getValue();

        AmortizationType amortizationType1 = AmortizationType.valueOf(amortizationType);
        Integer amortizationTypeValue = amortizationType1.getValue();

        TransactionProcessingStrategyCode processingStrategyCode = TransactionProcessingStrategyCode
                .valueOf(transactionProcessingStrategyCode);
        String transactionProcessingStrategyCodeValue = processingStrategyCode.getValue();

        PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId)//
                .productId(loanProductId)//
                .principal(new BigDecimal(principal))//
                .interestRatePerPeriod(interestRate)//
                .interestType(interestTypeValue)//
                .interestCalculationPeriodType(interestCalculationPeriodValue)//
                .amortizationType(amortizationTypeValue)//
                .loanTermFrequency(loanTermFrequency)//
                .loanTermFrequencyType(loanTermFrequencyTypeValue)//
                .numberOfRepayments(numberOfRepayments)//
                .repaymentEvery(repaymentFrequency)//
                .repaymentFrequencyType(repaymentFrequencyTypeValue)//
                .submittedOnDate(submitDate)//
                .expectedDisbursementDate(submitDate)//
                .graceOnPrincipalPayment(graceOnPrincipalPayment)//
                .graceOnInterestPayment(graceOnInterestPayment)//
                .graceOnInterestPayment(graceOnInterestCharged).transactionProcessingStrategyCode(transactionProcessingStrategyCodeValue);//

        Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
        int errorCodeActual = response.code();
        String errorBody = response.errorBody().string();
        ErrorResponse errorResponse = GSON.fromJson(errorBody, ErrorResponse.class);
        String errorMessageActual = errorResponse.getErrors().get(0).getDeveloperMessage();

        assertThat(errorCodeActual).as(ErrorMessageHelper.wrongErrorCode(errorCodeActual, errorCodeExpected)).isEqualTo(errorCodeExpected);
        assertThat(errorMessageActual).as(ErrorMessageHelper.wrongErrorMessage(errorMessageActual, errorMessageExpected))
                .isEqualTo(errorMessageExpected);

        log.info("ERROR CODE: {}", errorCodeActual);
        log.info("ERROR MESSAGE: {}", errorMessageActual);
    }

    @Then("Loan details has the following last payment related data:")
    public void checkLastPaymentData(DataTable table) throws IOException {
        List<List<String>> data = table.asLists();
        List<String> expectedValues = data.get(1);
        String lastPaymentAmountExpected = expectedValues.get(0);
        String lastPaymentDateExpected = expectedValues.get(1);
        String lastRepaymentAmountExpected = expectedValues.get(2);
        String lastRepaymentDateExpected = expectedValues.get(3);

        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();
        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "collection", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);

        GetLoansLoanIdDelinquencySummary delinquent = loanDetailsResponse.body().getDelinquent();
        String lastPaymentAmountActual = String.valueOf(delinquent.getLastPaymentAmount());
        String lastPaymentDateActual = FORMATTER.format(delinquent.getLastPaymentDate());
        String lastRepaymentAmountActual = String.valueOf(delinquent.getLastRepaymentAmount());
        String lastRepaymentDateActual = FORMATTER.format(delinquent.getLastRepaymentDate());

        assertThat(lastPaymentAmountActual)
                .as(ErrorMessageHelper.wrongDataInLastPaymentAmount(lastPaymentAmountActual, lastPaymentAmountExpected))
                .isEqualTo(lastPaymentAmountExpected);
        assertThat(lastPaymentDateActual).as(ErrorMessageHelper.wrongDataInLastPaymentDate(lastPaymentDateActual, lastPaymentDateExpected))
                .isEqualTo(lastPaymentDateExpected);
        assertThat(lastRepaymentAmountActual)
                .as(ErrorMessageHelper.wrongDataInLastRepaymentAmount(lastRepaymentAmountActual, lastRepaymentAmountExpected))
                .isEqualTo(lastRepaymentAmountExpected);
        assertThat(lastRepaymentDateActual)
                .as(ErrorMessageHelper.wrongDataInLastRepaymentDate(lastRepaymentDateActual, lastRepaymentDateExpected))
                .isEqualTo(lastRepaymentDateExpected);
    }

    @Then("Loan details and LoanTransactionMakeRepaymentPostBusinessEvent has the following data in loanChargePaidByList section:")
    public void checkLoanDetailsAndEventLoanChargePaidByListSection(DataTable table) throws IOException {
        List<List<String>> data = table.asLists();

        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);

        List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
        GetLoansLoanIdTransactions lastRepaymentData = transactions.stream()
                .filter(t -> "loanTransactionType.repayment".equals(t.getType().getCode())).reduce((first, second) -> second).orElse(null);
        List<GetLoansLoanIdLoanChargePaidByData> loanChargePaidByList = lastRepaymentData.getLoanChargePaidByList();
        loanChargePaidByList.sort(Comparator.comparing(GetLoansLoanIdLoanChargePaidByData::getChargeId));

        EventAssertion.EventAssertionBuilder<LoanTransactionDataV1> transactionEvent = testContext().get(TestContextKey.TRANSACTION_EVENT);
        transactionEvent.extractingData(loanTransactionDataV1 -> {
            for (int i = 0; i < loanChargePaidByList.size(); i++) {
                List<LoanChargePaidByDataV1> loanChargePaidByListEvent = loanTransactionDataV1.getLoanChargePaidByList();
                loanChargePaidByListEvent.sort(Comparator.comparing(LoanChargePaidByDataV1::getChargeId));
                String amountEventActual = loanChargePaidByListEvent.get(i).getAmount().setScale(1, RoundingMode.HALF_DOWN).toString();
                String nameEventActual = loanChargePaidByListEvent.get(i).getName();

                String amountActual = String.valueOf(loanChargePaidByList.get(i).getAmount());
                String nameActual = loanChargePaidByList.get(i).getName();

                String amountExpected = data.get(i + 1).get(0);
                String nameExpected = data.get(i + 1).get(1);

                assertThat(amountActual)
                        .as(ErrorMessageHelper.wrongDataInLoanDetailsLoanChargePaidByListAmount(amountActual, amountExpected))
                        .isEqualTo(amountExpected);
                assertThat(nameActual).as(ErrorMessageHelper.wrongDataInLoanDetailsLoanChargePaidByListName(nameActual, nameExpected))
                        .isEqualTo(nameExpected);

                assertThat(amountEventActual).as(ErrorMessageHelper
                        .wrongDataInLoanTransactionMakeRepaymentPostEventLoanChargePaidByListAmount(amountEventActual, amountExpected))
                        .isEqualTo(amountExpected);
                assertThat(nameEventActual).as(ErrorMessageHelper
                        .wrongDataInLoanTransactionMakeRepaymentPostEventLoanChargePaidByListName(nameEventActual, nameExpected))
                        .isEqualTo(nameExpected);
            }
            return null;
        });
    }

    @And("Admin successfully creates a new customised Loan submitted on date: {string}, with Principal: {string}, a loanTermFrequency: {int} months, and numberOfRepayments: {int}")
    public void createCustomizedLoan(String submitDate, String principal, Integer loanTermFrequency, Integer numberOfRepayments)
            throws IOException {
        Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
        Long clientId = clientResponse.body().getClientId();
        Integer repaymentFrequency = loanTermFrequency / numberOfRepayments;

        PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId).principal(new BigDecimal(principal))
                .loanTermFrequency(loanTermFrequency).loanTermFrequencyType(LoanTermFrequencyType.MONTHS.value)
                .numberOfRepayments(numberOfRepayments).repaymentEvery(repaymentFrequency)
                .repaymentFrequencyType(RepaymentFrequencyType.MONTHS.value).submittedOnDate(submitDate)
                .expectedDisbursementDate(submitDate);

        Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
        testContext().set(TestContextKey.LOAN_CREATE_RESPONSE, response);
        ErrorHelper.checkSuccessfulApiCall(response);
    }

    @And("Customer makes {string} transaction with {string} payment type on {string} with {double} EUR transaction amount with the same Idempotency key as previous transaction")
    public void createTransactionWithIdempotencyKeyOfPreviousTransaction(String transactionTypeInput, String transactionPaymentType,
            String transactionDate, double transactionAmount) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        TransactionType transactionType = TransactionType.valueOf(transactionTypeInput);
        String transactionTypeValue = transactionType.getValue();
        DefaultPaymentType paymentType = DefaultPaymentType.valueOf(transactionPaymentType);
        Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);

        PostLoansLoanIdTransactionsRequest paymentTransactionRequest = LoanRequestFactory.defaultPaymentTransactionRequest()
                .transactionDate(transactionDate).transactionAmount(transactionAmount).paymentTypeId(paymentTypeValue);

        Map<String, String> headerMap = new HashMap<>();
        String idempotencyKey = testContext().get(TestContextKey.TRANSACTION_IDEMPOTENCY_KEY);
        headerMap.put("Idempotency-Key", idempotencyKey);

        Response<PostLoansLoanIdTransactionsResponse> paymentTransactionResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, paymentTransactionRequest, transactionTypeValue, headerMap).execute();
        testContext().set(TestContextKey.LOAN_PAYMENT_TRANSACTION_RESPONSE, paymentTransactionResponse);
        ErrorHelper.checkSuccessfulApiCall(paymentTransactionResponse);
    }

    @And("Customer makes {string} transaction on the second loan with {string} payment type on {string} with {double} EUR transaction amount with the same Idempotency key as previous transaction")
    public void createTransactionOnSecondLoanWithIdempotencyKeyOfPreviousTransaction(String transactionTypeInput,
            String transactionPaymentType, String transactionDate, double transactionAmount) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_SECOND_LOAN_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        TransactionType transactionType = TransactionType.valueOf(transactionTypeInput);
        String transactionTypeValue = transactionType.getValue();
        DefaultPaymentType paymentType = DefaultPaymentType.valueOf(transactionPaymentType);
        Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);

        PostLoansLoanIdTransactionsRequest paymentTransactionRequest = LoanRequestFactory.defaultPaymentTransactionRequest()
                .transactionDate(transactionDate).transactionAmount(transactionAmount).paymentTypeId(paymentTypeValue);

        Map<String, String> headerMap = new HashMap<>();
        String idempotencyKey = testContext().get(TestContextKey.TRANSACTION_IDEMPOTENCY_KEY);
        headerMap.put("Idempotency-Key", idempotencyKey);

        Response<PostLoansLoanIdTransactionsResponse> paymentTransactionResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, paymentTransactionRequest, transactionTypeValue, headerMap).execute();
        testContext().set(TestContextKey.LOAN_PAYMENT_TRANSACTION_RESPONSE, paymentTransactionResponse);
        ErrorHelper.checkSuccessfulApiCall(paymentTransactionResponse);
    }

    @Then("Admin can successfully modify the loan and changes the submitted on date to {string}")
    public void modifyLoanSubmittedOnDate(String newSubmittedOnDate) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        Long loanId2 = loanResponse.body().getResourceId();
        Long clientId2 = loanResponse.body().getClientId();

        PutLoansLoanIdRequest putLoansLoanIdRequest = loanRequestFactory.modifySubmittedOnDateOnLoan(clientId2, newSubmittedOnDate);

        Response<PutLoansLoanIdResponse> responseMod = loansApi.modifyLoanApplication(loanId2, putLoansLoanIdRequest, "").execute();
        testContext().set(TestContextKey.LOAN_MODIFY_RESPONSE, responseMod);
        ErrorHelper.checkSuccessfulApiCall(responseMod);
    }

    @Then("Admin fails to create a new customised Loan submitted on date: {string}, with Principal: {string}, a loanTermFrequency: {int} months, and numberOfRepayments: {int}")
    public void createCustomizedLoanFailure(String submitDate, String principal, Integer loanTermFrequency, Integer numberOfRepayments)
            throws IOException {
        Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
        Long clientId = clientResponse.body().getClientId();
        Integer repaymentFrequency = loanTermFrequency / numberOfRepayments;

        PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId).principal(new BigDecimal(principal))
                .loanTermFrequency(loanTermFrequency).loanTermFrequencyType(LoanTermFrequencyType.MONTHS.value)
                .numberOfRepayments(numberOfRepayments).repaymentEvery(repaymentFrequency)
                .repaymentFrequencyType(RepaymentFrequencyType.MONTHS.value).submittedOnDate(submitDate)
                .expectedDisbursementDate(submitDate);

        Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
        testContext().set(TestContextKey.LOAN_CREATE_RESPONSE, response);
        ErrorResponse errorDetails = ErrorResponse.from(response);
        assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.dateFailureErrorCodeMsg()).isEqualTo(403);
        assertThat(errorDetails.getSingleError().getDeveloperMessage()).isEqualTo(ErrorMessageHelper.loanSubmitDateInFutureFailureMsg());
    }

    @And("Admin successfully approves the loan on {string} with {string} amount and expected disbursement date on {string}")
    public void approveLoan(String approveDate, String approvedAmount, String expectedDisbursementDate) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();
        PostLoansLoanIdRequest approveRequest = LoanRequestFactory.defaultLoanApproveRequest().approvedOnDate(approveDate)
                .approvedLoanAmount(new BigDecimal(approvedAmount)).expectedDisbursementDate(expectedDisbursementDate);

        Response<PostLoansLoanIdResponse> loanApproveResponse = loansApi.stateTransitions(loanId, approveRequest, "approve").execute();
        testContext().set(TestContextKey.LOAN_APPROVAL_RESPONSE, loanApproveResponse);
        ErrorHelper.checkSuccessfulApiCall(loanApproveResponse);
        assertThat(loanApproveResponse.body().getChanges().getStatus().getValue()).isEqualTo(LOAN_STATE_APPROVED);
        assertThat(loanApproveResponse.body().getChanges().getStatus().getValue()).isEqualTo(LOAN_STATE_APPROVED);

        eventCheckHelper.approveLoanEventCheck(loanApproveResponse);
    }

    @And("Admin successfully approves the second loan on {string} with {string} amount and expected disbursement date on {string}")
    public void approveSecondLoan(String approveDate, String approvedAmount, String expectedDisbursementDate) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_SECOND_LOAN_RESPONSE);
        long loanId = loanResponse.body().getLoanId();
        PostLoansLoanIdRequest approveRequest = LoanRequestFactory.defaultLoanApproveRequest().approvedOnDate(approveDate)
                .approvedLoanAmount(new BigDecimal(approvedAmount)).expectedDisbursementDate(expectedDisbursementDate);

        Response<PostLoansLoanIdResponse> loanApproveResponse = loansApi.stateTransitions(loanId, approveRequest, "approve").execute();
        testContext().set(TestContextKey.LOAN_APPROVAL_SECOND_LOAN_RESPONSE, loanApproveResponse);
        ErrorHelper.checkSuccessfulApiCall(loanApproveResponse);
        assertThat(loanApproveResponse.body().getChanges().getStatus().getValue()).isEqualTo(LOAN_STATE_APPROVED);
        assertThat(loanApproveResponse.body().getChanges().getStatus().getValue()).isEqualTo(LOAN_STATE_APPROVED);
    }

    @Then("Admin can successfully undone the loan approval")
    public void undoLoanApproval() throws IOException {
        Response<PostLoansLoanIdResponse> loanApproveResponse = testContext().get(TestContextKey.LOAN_APPROVAL_RESPONSE);
        long loanId = loanApproveResponse.body().getLoanId();
        PostLoansLoanIdRequest undoApprovalRequest = new PostLoansLoanIdRequest().note("");

        Response<PostLoansLoanIdResponse> undoApprovalResponse = loansApi.stateTransitions(loanId, undoApprovalRequest, "undoapproval")
                .execute();
        testContext().set(TestContextKey.LOAN_UNDO_APPROVAL_RESPONSE, loanApproveResponse);
        ErrorHelper.checkSuccessfulApiCall(undoApprovalResponse);
        assertThat(undoApprovalResponse.body().getChanges().getStatus().getValue()).isEqualTo(LOAN_STATE_SUBMITTED_AND_PENDING);
    }

    @Then("Admin fails to approve the loan on {string} with {string} amount and expected disbursement date on {string} because of wrong date")
    public void failedLoanApproveWithDate(String approveDate, String approvedAmount, String expectedDisbursementDate) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();
        PostLoansLoanIdRequest approveRequest = LoanRequestFactory.defaultLoanApproveRequest().approvedOnDate(approveDate)
                .approvedLoanAmount(new BigDecimal(approvedAmount)).expectedDisbursementDate(expectedDisbursementDate);

        Response<PostLoansLoanIdResponse> loanApproveResponse = loansApi.stateTransitions(loanId, approveRequest, "approve").execute();
        ErrorResponse errorDetails = ErrorResponse.from(loanApproveResponse);
        assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.dateFailureErrorCodeMsg()).isEqualTo(403);
        assertThat(errorDetails.getSingleError().getDeveloperMessage()).isEqualTo(ErrorMessageHelper.loanApproveDateInFutureFailureMsg());
    }

    @Then("Admin fails to approve the loan on {string} with {string} amount and expected disbursement date on {string} because of wrong amount")
    public void failedLoanApproveWithAmount(String approveDate, String approvedAmount, String expectedDisbursementDate) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();
        PostLoansLoanIdRequest approveRequest = LoanRequestFactory.defaultLoanApproveRequest().approvedOnDate(approveDate)
                .approvedLoanAmount(new BigDecimal(approvedAmount)).expectedDisbursementDate(expectedDisbursementDate);

        Response<PostLoansLoanIdResponse> loanApproveResponse = loansApi.stateTransitions(loanId, approveRequest, "approve").execute();
        ErrorResponse errorDetails = ErrorResponse.from(loanApproveResponse);
        assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.dateFailureErrorCodeMsg()).isEqualTo(403);
        assertThat(errorDetails.getSingleError().getDeveloperMessage()).isEqualTo(ErrorMessageHelper.loanApproveMaxAmountFailureMsg());
    }

    @And("Admin successfully disburse the loan on {string} with {string} EUR transaction amount")
    public void disburseLoan(String actualDisbursementDate, String transactionAmount) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();
        PostLoansLoanIdRequest disburseRequest = LoanRequestFactory.defaultLoanDisburseRequest()
                .actualDisbursementDate(actualDisbursementDate).transactionAmount(new BigDecimal(transactionAmount));

        Response<PostLoansLoanIdResponse> loanDisburseResponse = loansApi.stateTransitions(loanId, disburseRequest, "disburse").execute();
        testContext().set(TestContextKey.LOAN_DISBURSE_RESPONSE, loanDisburseResponse);
        ErrorHelper.checkSuccessfulApiCall(loanDisburseResponse);
        Long statusActual = loanDisburseResponse.body().getChanges().getStatus().getId();

        Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
        Long statusExpected = Long.valueOf(loanDetails.body().getStatus().getId());

        assertThat(statusActual)//
                .as(ErrorMessageHelper.wrongLoanStatus(Math.toIntExact(statusActual), Math.toIntExact(statusExpected)))//
                .isEqualTo(statusExpected);//
        eventCheckHelper.disburseLoanEventCheck(loanDisburseResponse);
        eventCheckHelper.loanDisbursalTransactionEventCheck(loanDisburseResponse);
    }

    @And("Admin successfully disburse the second loan on {string} with {string} EUR transaction amount")
    public void disburseSecondLoan(String actualDisbursementDate, String transactionAmount) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_SECOND_LOAN_RESPONSE);
        long loanId = loanResponse.body().getLoanId();
        PostLoansLoanIdRequest disburseRequest = LoanRequestFactory.defaultLoanDisburseRequest()
                .actualDisbursementDate(actualDisbursementDate).transactionAmount(new BigDecimal(transactionAmount));

        Response<PostLoansLoanIdResponse> loanDisburseResponse = loansApi.stateTransitions(loanId, disburseRequest, "disburse").execute();
        testContext().set(TestContextKey.LOAN_DISBURSE_SECOND_LOAN_RESPONSE, loanDisburseResponse);
        ErrorHelper.checkSuccessfulApiCall(loanDisburseResponse);
        assertThat(loanDisburseResponse.body().getChanges().getStatus().getValue()).isEqualTo(LOAN_STATE_ACTIVE);

        eventCheckHelper.disburseLoanEventCheck(loanDisburseResponse);
        eventCheckHelper.loanDisbursalTransactionEventCheck(loanDisburseResponse);
    }

    @And("Admin does charge-off the loan on {string}")
    public void chargeOffLoan(String transactionDate) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        PostLoansLoanIdTransactionsRequest chargeOffRequest = LoanRequestFactory.defaultChargeOffRequest().transactionDate(transactionDate)
                .dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);

        Response<PostLoansLoanIdTransactionsResponse> chargeOffResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, chargeOffRequest, "charge-off").execute();
        testContext().set(TestContextKey.LOAN_CHARGE_OFF_RESPONSE, chargeOffResponse);
        ErrorHelper.checkSuccessfulApiCall(chargeOffResponse);

        Long transactionId = chargeOffResponse.body().getResourceId();
        eventAssertion.assertEvent(LoanChargeOffEvent.class, transactionId).extractingData(LoanTransactionDataV1::getLoanId)
                .isEqualTo(loanId).extractingData(LoanTransactionDataV1::getId).isEqualTo(chargeOffResponse.body().getResourceId());
    }

    @Then("Charge-off attempt on {string} results an error")
    public void chargeOffOnLoanWithInterestFails(String transactionDate) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        PostLoansLoanIdTransactionsRequest chargeOffRequest = LoanRequestFactory.defaultChargeOffRequest().transactionDate(transactionDate)
                .dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);

        Response<PostLoansLoanIdTransactionsResponse> chargeOffResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, chargeOffRequest, "charge-off").execute();
        testContext().set(TestContextKey.LOAN_CHARGE_OFF_RESPONSE, chargeOffResponse);

        assertThat(chargeOffResponse.isSuccessful()).isFalse();

        String string = chargeOffResponse.errorBody().string();
        ErrorResponse errorResponse = GSON.fromJson(string, ErrorResponse.class);
        String developerMessage = errorResponse.getErrors().get(0).getDeveloperMessage();
        assertThat(developerMessage)
                .isEqualTo(String.format("Loan: %s Charge-off is not allowed. Loan Account is interest bearing", loanId));
    }

    @Then("Second Charge-off is not possible on {string}")
    public void secondChargeOffLoan(String transactionDate) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        PostLoansLoanIdTransactionsRequest chargeOffRequest = LoanRequestFactory.defaultChargeOffRequest().transactionDate(transactionDate)
                .dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);

        Response<PostLoansLoanIdTransactionsResponse> secondChargeOffResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, chargeOffRequest, "charge-off").execute();
        testContext().set(TestContextKey.LOAN_CHARGE_OFF_RESPONSE, secondChargeOffResponse);
        ErrorResponse errorDetails = ErrorResponse.from(secondChargeOffResponse);
        assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.chargeOffUndoFailureCodeMsg()).isEqualTo(403);
        assertThat(errorDetails.getSingleError().getDeveloperMessage()).isEqualTo(ErrorMessageHelper.secondChargeOffFailure(loanId));
    }

    @And("Admin does a charge-off undo the loan")
    public void chargeOffUndo() throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        PostLoansLoanIdTransactionsRequest chargeOffUndoRequest = LoanRequestFactory.defaultUndoChargeOffRequest();

        Response<PostLoansLoanIdTransactionsResponse> chargeOffUndoResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, chargeOffUndoRequest, "undo-charge-off").execute();
        testContext().set(TestContextKey.LOAN_CHARGE_OFF_UNDO_RESPONSE, chargeOffUndoResponse);
        ErrorHelper.checkSuccessfulApiCall(chargeOffUndoResponse);

        Long transactionId = chargeOffUndoResponse.body().getResourceId();
        eventAssertion.assertEventRaised(LoanChargeOffUndoEvent.class, transactionId);
    }

    @Then("Charge-off undo is not possible on {string}")
    public void chargeOffUndoFailure(String transactionDate) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        Long loanId = loanResponse.body().getLoanId();

        PostLoansLoanIdTransactionsRequest chargeOffRequest = LoanRequestFactory.defaultChargeOffRequest().transactionDate(transactionDate)
                .dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);

        Response<PostLoansLoanIdTransactionsResponse> chargeOffResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, chargeOffRequest, "charge-off").execute();
        testContext().set(TestContextKey.LOAN_CHARGE_OFF_RESPONSE, chargeOffResponse);
        ErrorResponse errorDetails = ErrorResponse.from(chargeOffResponse);
        assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.chargeOffUndoFailureCodeMsg()).isEqualTo(403);
        assertThat(errorDetails.getSingleError().getDeveloperMessage()).isEqualTo(ErrorMessageHelper.chargeOffUndoFailure(loanId));
    }

    @Then("Charge-off undo is not possible as the loan is not charged-off")
    public void chargeOffNotPossibleFailure() throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        Long loanId = loanResponse.body().getLoanId();

        PostLoansLoanIdTransactionsRequest chargeOffRequest = LoanRequestFactory.defaultUndoChargeOffRequest();

        Response<PostLoansLoanIdTransactionsResponse> undoChargeOffResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, chargeOffRequest, "undo-charge-off").execute();
        testContext().set(TestContextKey.LOAN_CHARGE_OFF_RESPONSE, undoChargeOffResponse);
        ErrorResponse errorDetails = ErrorResponse.from(undoChargeOffResponse);
        assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.chargeOffUndoFailureCodeMsg()).isEqualTo(403);
        assertThat(errorDetails.getSingleError().getDeveloperMessage()).isEqualTo(ErrorMessageHelper.notChargedOffFailure(loanId));
    }

    @When("Admin successfully undo disbursal")
    public void undoDisbursal() throws IOException {
        Response<PostLoansLoanIdResponse> loanApproveResponse = testContext().get(TestContextKey.LOAN_APPROVAL_RESPONSE);
        long loanId = loanApproveResponse.body().getLoanId();

        PostLoansLoanIdRequest undoDisbursalRequest = new PostLoansLoanIdRequest().note("");
        Response<PostLoansLoanIdResponse> undoLastDisbursalResponse = loansApi
                .stateTransitions(loanId, undoDisbursalRequest, "undodisbursal").execute();
        ErrorHelper.checkSuccessfulApiCall(undoLastDisbursalResponse);
    }

    @When("Admin successfully undo last disbursal")
    public void undoLastDisbursal() throws IOException {
        Response<PostLoansLoanIdResponse> loanApproveResponse = testContext().get(TestContextKey.LOAN_APPROVAL_RESPONSE);
        long loanId = loanApproveResponse.body().getLoanId();

        PostLoansLoanIdRequest undoDisbursalRequest = new PostLoansLoanIdRequest().note("");
        Response<PostLoansLoanIdResponse> undoLastDisbursalResponse = loansApi
                .stateTransitions(loanId, undoDisbursalRequest, "undolastdisbursal").execute();
        ErrorHelper.checkSuccessfulApiCall(undoLastDisbursalResponse);
    }

    @Then("Admin can successfully undone the loan disbursal")
    public void checkUndoLoanDisbursal() throws IOException {
        Response<PostLoansLoanIdResponse> loanApproveResponse = testContext().get(TestContextKey.LOAN_APPROVAL_RESPONSE);
        long loanId = loanApproveResponse.body().getLoanId();
        PostLoansLoanIdRequest undoDisbursalRequest = new PostLoansLoanIdRequest().note("");

        Response<PostLoansLoanIdResponse> undoDisbursalResponse = loansApi.stateTransitions(loanId, undoDisbursalRequest, "undodisbursal")
                .execute();
        testContext().set(TestContextKey.LOAN_UNDO_DISBURSE_RESPONSE, undoDisbursalResponse);
        ErrorHelper.checkSuccessfulApiCall(undoDisbursalResponse);
        assertThat(undoDisbursalResponse.body().getChanges().getStatus().getValue()).isEqualTo(LOAN_STATE_APPROVED);
    }

    @Then("Admin fails to disburse the loan on {string} with {string} EUR transaction amount because of wrong date")
    public void disburseLoanFailureWithDate(String actualDisbursementDate, String transactionAmount) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();
        PostLoansLoanIdRequest disburseRequest = LoanRequestFactory.defaultLoanDisburseRequest()
                .actualDisbursementDate(actualDisbursementDate).transactionAmount(new BigDecimal(transactionAmount));

        Response<PostLoansLoanIdResponse> loanDisburseResponse = loansApi.stateTransitions(loanId, disburseRequest, "disburse").execute();
        testContext().set(TestContextKey.LOAN_DISBURSE_RESPONSE, loanDisburseResponse);
        ErrorResponse errorDetails = ErrorResponse.from(loanDisburseResponse);
        assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.dateFailureErrorCodeMsg()).isEqualTo(403);
        assertThat(errorDetails.getSingleError().getDeveloperMessage()).isEqualTo(ErrorMessageHelper.disburseDateFailure((int) loanId));
    }

    @Then("Admin fails to disburse the loan on {string} with {string} EUR transaction amount because of wrong amount")
    public void disburseLoanFailureWithAmount(String actualDisbursementDate, String transactionAmount) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();
        PostLoansLoanIdRequest disburseRequest = LoanRequestFactory.defaultLoanDisburseRequest()
                .actualDisbursementDate(actualDisbursementDate).transactionAmount(new BigDecimal(transactionAmount));

        Response<PostLoansLoanIdResponse> loanDisburseResponse = loansApi.stateTransitions(loanId, disburseRequest, "disburse").execute();
        testContext().set(TestContextKey.LOAN_DISBURSE_RESPONSE, loanDisburseResponse);
        ErrorResponse errorDetails = ErrorResponse.from(loanDisburseResponse);
        String developerMessage = errorDetails.getSingleError().getDeveloperMessage();

        assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.dateFailureErrorCodeMsg()).isEqualTo(403);
        assertThat(developerMessage).matches(ErrorMessageHelper.disburseMaxAmountFailure());
        log.info("Error message: {}", developerMessage);
    }

    @Then("Loan has {double} outstanding amount")
    public void loanOutstanding(double totalOutstandingExpected) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
        testContext().set(TestContextKey.LOAN_RESPONSE, loanDetailsResponse);

        Double totalOutstandingActual = loanDetailsResponse.body().getSummary().getTotalOutstanding();
        assertThat(totalOutstandingActual)
                .as(ErrorMessageHelper.wrongAmountInTotalOutstanding(totalOutstandingActual, totalOutstandingExpected))
                .isEqualTo(totalOutstandingExpected);
    }

    @Then("Loan has {double} overpaid amount")
    public void loanOverpaid(double totalOverpaidExpected) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
        testContext().set(TestContextKey.LOAN_RESPONSE, loanDetailsResponse);

        Double totalOverpaidActual = loanDetailsResponse.body().getTotalOverpaid();
        Double totalOutstandingActual = loanDetailsResponse.body().getSummary().getTotalOutstanding();
        double totalOutstandingExpected = 0.0;
        assertThat(totalOutstandingActual)
                .as(ErrorMessageHelper.wrongAmountInTotalOutstanding(totalOutstandingActual, totalOutstandingExpected))
                .isEqualTo(totalOutstandingExpected);
        assertThat(totalOverpaidActual)
                .as(ErrorMessageHelper.wrongAmountInTransactionsOverpayment(totalOverpaidActual, totalOverpaidExpected))
                .isEqualTo(totalOverpaidExpected);
    }

    @Then("Loan has {double} total overdue amount")
    public void loanOverdue(double totalOverdueExpected) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
        testContext().set(TestContextKey.LOAN_RESPONSE, loanDetailsResponse);

        Double totalOverdueActual = loanDetailsResponse.body().getSummary().getTotalOverdue();
        assertThat(totalOverdueActual).as(ErrorMessageHelper.wrongAmountInTotalOverdue(totalOverdueActual, totalOverdueExpected))
                .isEqualTo(totalOverdueExpected);
    }

    @Then("Loan has {double} last payment amount")
    public void loanLastPaymentAmount(double lastPaymentAmountExpected) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
        testContext().set(TestContextKey.LOAN_RESPONSE, loanDetailsResponse);

        Double lastPaymentAmountActual = loanDetailsResponse.body().getDelinquent().getLastPaymentAmount();
        assertThat(lastPaymentAmountActual)
                .as(ErrorMessageHelper.wrongLastPaymentAmount(lastPaymentAmountActual, lastPaymentAmountExpected))
                .isEqualTo(lastPaymentAmountExpected);
    }

    @Then("Loan Repayment schedule has {int} periods, with the following data for periods:")
    public void loanRepaymentSchedulePeriodsCheck(int linesExpected, DataTable table) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "repaymentSchedule", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);

        List<GetLoansLoanIdRepaymentPeriod> repaymentPeriods = loanDetailsResponse.body().getRepaymentSchedule().getPeriods();

        List<List<String>> data = table.asLists();
        int nrLines = data.size();
        int linesActual = (int) repaymentPeriods.stream().filter(r -> r.getPeriod() != null).count();
        for (int i = 1; i < nrLines; i++) {
            List<String> expectedValues = data.get(i);
            String dueDateExpected = expectedValues.get(2);

            List<List<String>> actualValuesList = repaymentPeriods.stream()
                    .filter(r -> dueDateExpected.equals(FORMATTER.format(r.getDueDate())))
                    .map(r -> fetchValuesOfRepaymentSchedule(data.get(0), r)).collect(Collectors.toList());

            boolean containsExpectedValues = actualValuesList.stream().anyMatch(actualValues -> actualValues.equals(expectedValues));
            assertThat(containsExpectedValues)
                    .as(ErrorMessageHelper.wrongValueInLineInRepaymentSchedule(i, actualValuesList, expectedValues)).isTrue();

            assertThat(linesActual).as(ErrorMessageHelper.wrongNumberOfLinesInRepaymentSchedule(linesActual, linesExpected))
                    .isEqualTo(linesExpected);
        }
    }

    @Then("Loan Repayment schedule has the following data in Total row:")
    public void loanRepaymentScheduleAmountCheck(DataTable table) throws IOException {
        List<List<String>> data = table.asLists();
        List<String> header = data.get(0);
        List<String> expectedValues = data.get(1);
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "repaymentSchedule", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);

        GetLoansLoanIdRepaymentSchedule repaymentSchedule = loanDetailsResponse.body().getRepaymentSchedule();
        validateRepaymentScheduleTotal(header, repaymentSchedule, expectedValues);
    }

    @Then("Loan Transactions tab has a transaction with date: {string}, and with the following data:")
    public void loanTransactionsTransactionWithGivenDateDataCheck(String date, DataTable table) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);

        List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();

        List<List<String>> data = table.asLists();
        List<String> expectedValues = data.get(1);

        List<List<String>> actualValuesList = transactions.stream().filter(t -> date.equals(FORMATTER.format(t.getDate())))
                .map(t -> fetchValuesOfTransaction(data.get(0), t)).collect(Collectors.toList());
        boolean containsExpectedValues = actualValuesList.stream().anyMatch(actualValues -> actualValues.equals(expectedValues));

        assertThat(containsExpectedValues).as(ErrorMessageHelper.wrongValueInLineInTransactionsTab(1, actualValuesList, expectedValues))
                .isTrue();
    }

    @Then("Loan Transactions tab has the following data:")
    public void loanTransactionsTabCheck(DataTable table) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();
        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
        List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
        List<List<String>> data = table.asLists();
        for (int i = 1; i < data.size(); i++) {
            List<String> expectedValues = data.get(i);
            String transactionDateExpected = expectedValues.get(0);
            List<List<String>> actualValuesList = transactions.stream()//
                    .filter(t -> transactionDateExpected.equals(FORMATTER.format(t.getDate())))//
                    .map(t -> fetchValuesOfTransaction(table.row(0), t))//
                    .collect(Collectors.toList());//
            boolean containsExpectedValues = actualValuesList.stream()//
                    .anyMatch(actualValues -> actualValues.equals(expectedValues));//
            assertThat(containsExpectedValues).as(ErrorMessageHelper.wrongValueInLineInTransactionsTab(i, actualValuesList, expectedValues))
                    .isTrue();
        }
        assertThat(transactions.size()).as(ErrorMessageHelper.nrOfLinesWrongInTransactionsTab(transactions.size(), data.size() - 1))
                .isEqualTo(data.size() - 1);
    }

    @Then("In Loan Transactions the latest Transaction has Transaction type={string} and is reverted")
    public void loanTransactionsLatestTransactionReverted(String transactionType) throws IOException {
        loanTransactionsLatestTransactionReverted(null, transactionType);
    }

    @Then("In Loan Transactions the {string}th Transaction has Transaction type={string} and is reverted")
    public void loanTransactionsLatestTransactionReverted(String nthTransactionStr, String transactionType) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);

        List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
        int nthTransaction = nthTransactionStr == null ? transactions.size() - 1 : Integer.parseInt(nthTransactionStr) - 1;
        GetLoansLoanIdTransactions latestTransaction = transactions.get(nthTransaction);

        String transactionTypeActual = latestTransaction.getType().getValue();
        Boolean isReversedActual = latestTransaction.getManuallyReversed();

        assertThat(transactionTypeActual)
                .as(ErrorMessageHelper.wrongDataInTransactionsTransactionType(transactionTypeActual, transactionType))
                .isEqualTo(transactionType);
        assertThat(isReversedActual).as(ErrorMessageHelper.transactionIsNotReversedError(isReversedActual, true)).isEqualTo(true);
    }

    @Then("On Loan Transactions tab the {string} Transaction with date {string} is reverted")
    public void loanTransactionsGivenTransactionReverted(String transactionType, String transactionDate) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);

        List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
        List<GetLoansLoanIdTransactions> transactionsMatch = transactions//
                .stream()//
                .filter(t -> transactionDate.equals(FORMATTER.format(t.getDate())) && transactionType.equals(t.getType().getValue()))//
                .collect(Collectors.toList());//
        boolean isReverted = transactionsMatch.stream().anyMatch(t -> t.getManuallyReversed());

        assertThat(isReverted).as(ErrorMessageHelper.transactionIsNotReversedError(isReverted, true)).isEqualTo(true);
    }

    @Then("On Loan Transactions tab the {string} Transaction with date {string} is NOT reverted")
    public void loanTransactionsGivenTransactionNotReverted(String transactionType, String transactionDate) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);

        List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
        List<GetLoansLoanIdTransactions> transactionsMatch = transactions//
                .stream()//
                .filter(t -> transactionDate.equals(FORMATTER.format(t.getDate())) && transactionType.equals(t.getType().getValue()))//
                .collect(Collectors.toList());//
        boolean isReverted = transactionsMatch.stream().anyMatch(t -> t.getManuallyReversed());

        assertThat(isReverted).as(ErrorMessageHelper.transactionIsNotReversedError(isReverted, false)).isEqualTo(false);
    }

    @Then("Loan Charges tab has a given charge with the following data:")
    public void loanChargesGivenChargeDataCheck(DataTable table) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "charges", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
        List<GetLoansLoanIdLoanChargeData> charges = loanDetailsResponse.body().getCharges();

        List<List<String>> data = table.asLists();
        List<String> expectedValues = data.get(1);
        String paymentDueAtExpected = expectedValues.get(2);
        String dueAsOfExpected = expectedValues.get(3);
        List<List<String>> actualValuesList = getActualValuesList(charges, paymentDueAtExpected, dueAsOfExpected);

        boolean containsExpectedValues = actualValuesList.stream().anyMatch(actualValues -> actualValues.equals(expectedValues));

        assertThat(containsExpectedValues).as(ErrorMessageHelper.wrongValueInLineInChargesTab(1, actualValuesList, expectedValues))
                .isTrue();
    }

    @Then("Loan Charges tab has the following data:")
    public void loanChargesTabCheck(DataTable table) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "charges", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
        List<GetLoansLoanIdLoanChargeData> charges = loanDetailsResponse.body().getCharges();

        List<List<String>> data = table.asLists();
        for (int i = 1; i < data.size(); i++) {
            List<String> expectedValues = data.get(i);
            String paymentDueAtExpected = expectedValues.get(2);
            String dueAsOfExpected = expectedValues.get(3);
            List<List<String>> actualValuesList = getActualValuesList(charges, paymentDueAtExpected, dueAsOfExpected);

            boolean containsExpectedValues = actualValuesList.stream().anyMatch(actualValues -> actualValues.equals(expectedValues));

            assertThat(containsExpectedValues).as(ErrorMessageHelper.wrongValueInLineInChargesTab(i, actualValuesList, expectedValues))
                    .isTrue();
        }
    }

    private List<List<String>> getActualValuesList(List<GetLoansLoanIdLoanChargeData> charges, String paymentDueAtExpected,
            String dueAsOfExpected) {
        List<GetLoansLoanIdLoanChargeData> result;

        if (dueAsOfExpected != null) {
            result = charges.stream().filter(t -> {
                LocalDate dueDate = t.getDueDate();
                return dueDate != null && dueAsOfExpected.equals(FORMATTER.format(dueDate));
            }).collect(Collectors.toList());
        } else {
            result = charges.stream().filter(t -> paymentDueAtExpected.equals(t.getChargeTimeType().getValue()))
                    .collect(Collectors.toList());
        }

        return result.stream().map(t -> {
            List<String> actualValues = new ArrayList<>();
            actualValues.add(t.getName() == null ? null : t.getName());
            actualValues.add(String.valueOf(t.getPenalty() == null ? null : t.getPenalty()));
            actualValues.add(t.getChargeTimeType().getValue() == null ? null : t.getChargeTimeType().getValue());
            actualValues.add(t.getDueDate() == null ? null : FORMATTER.format(t.getDueDate()));
            actualValues.add(t.getChargeCalculationType().getValue() == null ? null : t.getChargeCalculationType().getValue());
            actualValues.add(t.getAmount() == null ? null : String.valueOf(t.getAmount()));
            actualValues.add(t.getAmountPaid() == null ? null : String.valueOf(t.getAmountPaid()));
            actualValues.add(t.getAmountWaived() == null ? null : String.valueOf(t.getAmountWaived()));
            actualValues.add(t.getAmountOutstanding() == null ? null : String.valueOf(t.getAmountOutstanding()));
            return actualValues;
        }).collect(Collectors.toList());
    }

    @Then("Loan status will be {string}")
    public void loanStatus(String statusExpected) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
        testContext().set(TestContextKey.LOAN_RESPONSE, loanDetailsResponse);
        Integer loanStatusActualValue = loanDetailsResponse.body().getStatus().getId();

        LoanStatus loanStatusExpected = LoanStatus.valueOf(statusExpected);
        Integer loanStatusExpectedValue = loanStatusExpected.getValue();

        assertThat(loanStatusActualValue).as(ErrorMessageHelper.wrongLoanStatus(loanStatusActualValue, loanStatusExpectedValue))
                .isEqualTo(loanStatusExpectedValue);
    }

    @Then("Admin can successfully set Fraud flag to the loan")
    public void setFraud() throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        Long loanId = loanResponse.body().getResourceId();

        PutLoansLoanIdRequest putLoansLoanIdRequest = LoanRequestFactory.enableFraudFlag();

        Response<PutLoansLoanIdResponse> responseMod = loansApi.modifyLoanApplication(loanId, putLoansLoanIdRequest, "markAsFraud")
                .execute();
        testContext().set(TestContextKey.LOAN_FRAUD_MODIFY_RESPONSE, responseMod);

        ErrorHelper.checkSuccessfulApiCall(responseMod);

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
        testContext().set(TestContextKey.LOAN_RESPONSE, loanDetailsResponse);

        Boolean fraudFlagActual = loanDetailsResponse.body().getFraud();
        assertThat(fraudFlagActual).as(ErrorMessageHelper.wrongFraudFlag(fraudFlagActual, true)).isEqualTo(true);
    }

    @Then("Admin can successfully unset Fraud flag to the loan")
    public void unsetFraud() throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        Long loanId = loanResponse.body().getResourceId();

        PutLoansLoanIdRequest putLoansLoanIdRequest = LoanRequestFactory.disableFraudFlag();

        Response<PutLoansLoanIdResponse> responseMod = loansApi.modifyLoanApplication(loanId, putLoansLoanIdRequest, "markAsFraud")
                .execute();
        testContext().set(TestContextKey.LOAN_FRAUD_MODIFY_RESPONSE, responseMod);
        ErrorHelper.checkSuccessfulApiCall(responseMod);

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
        testContext().set(TestContextKey.LOAN_RESPONSE, loanDetailsResponse);

        Boolean fraudFlagActual = loanDetailsResponse.body().getFraud();
        assertThat(fraudFlagActual).as(ErrorMessageHelper.wrongFraudFlag(fraudFlagActual, false)).isEqualTo(false);
    }

    @Then("Fraud flag modification fails")
    public void failedFraudModification() throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        Long loanId = loanResponse.body().getResourceId();

        PutLoansLoanIdRequest putLoansLoanIdRequest = LoanRequestFactory.disableFraudFlag();

        Response<PutLoansLoanIdResponse> responseMod = loansApi.modifyLoanApplication(loanId, putLoansLoanIdRequest, "markAsFraud")
                .execute();
        testContext().set(TestContextKey.LOAN_FRAUD_MODIFY_RESPONSE, responseMod);

        ErrorResponse errorDetails = ErrorResponse.from(responseMod);
        assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.dateFailureErrorCodeMsg()).isEqualTo(403);
        assertThat(errorDetails.getSingleError().getDeveloperMessage())
                .isEqualTo(ErrorMessageHelper.loanFraudFlagModificationMsg(loanId.toString()));
    }

    @Then("Transaction response has boolean value in header {string}: {string}")
    public void transactionHeaderCheckBoolean(String headerKey, String headerValue) {
        Response<PostLoansLoanIdTransactionsResponse> paymentTransactionResponse = testContext()
                .get(TestContextKey.LOAN_PAYMENT_TRANSACTION_RESPONSE);
        String headerValueActual = paymentTransactionResponse.headers().get(headerKey);
        assertThat(headerValueActual).as(ErrorMessageHelper.wrongValueInResponseHeader(headerKey, headerValueActual, headerValue))
                .isEqualTo(headerValue);
    }

    @Then("Transaction response has {double} EUR value for transaction amount")
    public void transactionAmountCheck(double amountExpected) {
        Response<PostLoansLoanIdTransactionsResponse> paymentTransactionResponse = testContext()
                .get(TestContextKey.LOAN_PAYMENT_TRANSACTION_RESPONSE);
        Double amountActual = Double.valueOf(paymentTransactionResponse.body().getChanges().getTransactionAmount());
        assertThat(amountActual).as(ErrorMessageHelper.wrongAmountInTransactionsResponse(amountActual, amountExpected))
                .isEqualTo(amountExpected);
    }

    @Then("Transaction response has the correct clientId and the loanId of the first transaction")
    public void transactionClientIdAndLoanIdCheck() {
        Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
        Long clientIdExpected = clientResponse.body().getClientId();

        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        Long loanIdExpected = Long.valueOf(loanResponse.body().getLoanId());

        Response<PostLoansLoanIdTransactionsResponse> paymentTransactionResponse = testContext()
                .get(TestContextKey.LOAN_PAYMENT_TRANSACTION_RESPONSE);
        Long clientIdActual = paymentTransactionResponse.body().getClientId();
        Long loanIdActual = paymentTransactionResponse.body().getLoanId();

        assertThat(clientIdActual).as(ErrorMessageHelper.wrongClientIdInTransactionResponse(clientIdActual, clientIdExpected))
                .isEqualTo(clientIdExpected);
        assertThat(loanIdActual).as(ErrorMessageHelper.wrongLoanIdInTransactionResponse(loanIdActual, loanIdExpected))
                .isEqualTo(loanIdExpected);
    }

    @Then("Transaction response has the clientId for the second client and the loanId of the second transaction")
    public void transactionSecondClientIdAndSecondLoanIdCheck() {
        Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_SECOND_CLIENT_RESPONSE);
        Long clientIdExpected = clientResponse.body().getClientId();

        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_SECOND_LOAN_RESPONSE);
        Long loanIdExpected = Long.valueOf(loanResponse.body().getLoanId());

        Response<PostLoansLoanIdTransactionsResponse> paymentTransactionResponse = testContext()
                .get(TestContextKey.LOAN_PAYMENT_TRANSACTION_RESPONSE);
        Long clientIdActual = paymentTransactionResponse.body().getClientId();
        Long loanIdActual = paymentTransactionResponse.body().getLoanId();

        assertThat(clientIdActual).as(ErrorMessageHelper.wrongClientIdInTransactionResponse(clientIdActual, clientIdExpected))
                .isEqualTo(clientIdExpected);
        assertThat(loanIdActual).as(ErrorMessageHelper.wrongLoanIdInTransactionResponse(loanIdActual, loanIdExpected))
                .isEqualTo(loanIdExpected);
    }

    @Then("Loan has {int} {string} transactions on Transactions tab")
    public void checkNrOfTransactions(int nrOfTransactionsExpected, String transactionTypeInput) throws IOException {
        TransactionType transactionType = TransactionType.valueOf(transactionTypeInput);
        String transactionTypeValue = transactionType.getValue();

        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();
        Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();

        List<GetLoansLoanIdTransactions> transactions = loanDetails.body().getTransactions();
        List<String> transactionsMatched = new ArrayList<>();

        transactions.forEach(t -> {
            String transactionTypeValueActual = t.getType().getCode();
            String transactionTypeValueExpected = "loanTransactionType." + transactionTypeValue;

            if (transactionTypeValueActual.equals(transactionTypeValueExpected)) {
                transactionsMatched.add(transactionTypeValueActual);
            }
        });

        int nrOfTransactionsActual = transactionsMatched.size();
        assertThat(nrOfTransactionsActual)
                .as(ErrorMessageHelper.wrongNrOfTransactions(transactionTypeInput, nrOfTransactionsActual, nrOfTransactionsExpected))
                .isEqualTo(nrOfTransactionsExpected);
    }

    @Then("Second loan has {int} {string} transactions on Transactions tab")
    public void checkNrOfTransactionsOnSecondLoan(int nrOfTransactionsExpected, String transactionTypeInput) throws IOException {
        TransactionType transactionType = TransactionType.valueOf(transactionTypeInput);
        String transactionTypeValue = transactionType.getValue();

        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_SECOND_LOAN_RESPONSE);
        long loanId = loanResponse.body().getLoanId();
        Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();

        List<GetLoansLoanIdTransactions> transactions = loanDetails.body().getTransactions();
        List<String> transactionsMatched = new ArrayList<>();

        transactions.forEach(t -> {
            String transactionTypeValueActual = t.getType().getCode();
            String transactionTypeValueExpected = "loanTransactionType." + transactionTypeValue;

            if (transactionTypeValueActual.equals(transactionTypeValueExpected)) {
                transactionsMatched.add(transactionTypeValueActual);
            }
        });

        int nrOfTransactionsActual = transactionsMatched.size();
        assertThat(nrOfTransactionsActual)
                .as(ErrorMessageHelper.wrongNrOfTransactions(transactionTypeInput, nrOfTransactionsActual, nrOfTransactionsExpected))
                .isEqualTo(nrOfTransactionsExpected);
    }

    @Then("Loan status has changed to {string}")
    public void loanStatusHasChangedTo(String loanStatus) {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        LoanStatusEnumDataV1 expectedStatus = getExpectedStatus(loanStatus);
        eventAssertion.assertEvent(LoanStatusChangedEvent.class, loanId).extractingData(LoanAccountDataV1::getStatus)
                .isEqualTo(expectedStatus);
    }

    @Then("Loan marked as charged-off on {string}")
    public void isLoanChargedOff(String chargeOffDate) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
        testContext().set(TestContextKey.LOAN_RESPONSE, loanDetailsResponse);

        LocalDate expectedChargeOffDate = LocalDate.parse(chargeOffDate, FORMATTER);

        assertThat(loanDetailsResponse.body().getChargedOff()).isEqualTo(true);
        assertThat(loanDetailsResponse.body().getTimeline().getChargedOffOnDate()).isEqualTo(expectedChargeOffDate);
    }

    @And("Admin checks that last closed business date of loan is {string}")
    public void getLoanLastCOBDate(String date) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetails);
        if ("null".equals(date)) {
            assertThat(loanDetails.body().getLastClosedBusinessDate()).isNull();
        } else {
            assertThat(FORMATTER.format(Objects.requireNonNull(loanDetails.body().getLastClosedBusinessDate()))).isEqualTo(date);
        }
    }

    @When("Admin runs COB catch up")
    public void runLoanCOBCatchUp() throws IOException {
        Response<Void> catchUpResponse = loanCobCatchUpApi.executeLoanCOBCatchUp().execute();
        ErrorHelper.checkSuccessfulApiCall(catchUpResponse);
    }

    @When("Admin checks that Loan COB is running until the current business date")
    public void checkLoanCOBCatchUpRunningUntilCOBBusinessDate() {
        await().pollInterval(2, TimeUnit.SECONDS).atMost(Duration.ofSeconds(20)).until(() -> {
            Response<IsCatchUpRunningResponse> isCatchUpRunningResponse = loanCobCatchUpApi.isCatchUpRunning().execute();
            ErrorHelper.checkSuccessfulApiCall(isCatchUpRunningResponse);
            IsCatchUpRunningResponse isCatchUpRunning = isCatchUpRunningResponse.body();
            return isCatchUpRunning.getIsCatchUpRunning();
        });
        await().pollInterval(2, TimeUnit.SECONDS).atMost(Duration.ofSeconds(240)).until(() -> {
            Response<IsCatchUpRunningResponse> isCatchUpRunningResponse = loanCobCatchUpApi.isCatchUpRunning().execute();
            ErrorHelper.checkSuccessfulApiCall(isCatchUpRunningResponse);
            IsCatchUpRunningResponse isCatchUpRunning = isCatchUpRunningResponse.body();
            return !isCatchUpRunning.getIsCatchUpRunning();
        });
    }

    @Then("Loan's actualMaturityDate is {string}")
    public void checkActualMaturityDate(String actualMaturityDateExpected) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);

        LocalDate actualMaturityDate = loanDetailsResponse.body().getTimeline().getActualMaturityDate();
        String actualMaturityDateActual = FORMATTER.format(actualMaturityDate);

        assertThat(actualMaturityDateActual)
                .as(ErrorMessageHelper.wrongDataInActualMaturityDate(actualMaturityDateActual, actualMaturityDateExpected))
                .isEqualTo(actualMaturityDateExpected);
    }

    @Then("LoanAccrualTransactionCreatedBusinessEvent is raised on {string}")
    public void checkLoanAccrualTransactionCreatedBusinessEvent(String date) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);

        List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
        GetLoansLoanIdTransactions accrualTransaction = transactions.stream()
                .filter(t -> date.equals(FORMATTER.format(t.getDate())) && "Accrual".equals(t.getType().getValue())).findFirst()
                .orElseThrow(() -> new IllegalStateException(String.format("No Accrual transaction found on %s", date)));
        Long accrualTransactionId = accrualTransaction.getId();

        eventAssertion.assertEventRaised(LoanAccrualTransactionCreatedBusinessEvent.class, accrualTransactionId);
    }

    @Then("Loan details and event has the following last repayment related data:")
    public void checkLastRepaymentData(DataTable table) throws IOException {
        List<List<String>> data = table.asLists();
        List<String> expectedValues = data.get(1);
        String lastPaymentAmountExpected = expectedValues.get(0);
        String lastPaymentDateExpected = expectedValues.get(1);
        String lastRepaymentAmountExpected = expectedValues.get(2);
        String lastRepaymentDateExpected = expectedValues.get(3);

        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();
        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "collection", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);

        GetLoansLoanIdDelinquencySummary delinquent = loanDetailsResponse.body().getDelinquent();
        String lastPaymentAmountActual = String.valueOf(delinquent.getLastPaymentAmount());
        String lastPaymentDateActual = FORMATTER.format(delinquent.getLastPaymentDate());
        String lastRepaymentAmountActual = String.valueOf(delinquent.getLastRepaymentAmount());
        String lastRepaymentDateActual = FORMATTER.format(delinquent.getLastRepaymentDate());

        assertThat(lastPaymentAmountActual)
                .as(ErrorMessageHelper.wrongDataInLastPaymentAmount(lastPaymentAmountActual, lastPaymentAmountExpected))
                .isEqualTo(lastPaymentAmountExpected);
        assertThat(lastPaymentDateActual).as(ErrorMessageHelper.wrongDataInLastPaymentDate(lastPaymentDateActual, lastPaymentDateExpected))
                .isEqualTo(lastPaymentDateExpected);
        assertThat(lastRepaymentAmountActual)
                .as(ErrorMessageHelper.wrongDataInLastRepaymentAmount(lastRepaymentAmountActual, lastRepaymentAmountExpected))
                .isEqualTo(lastRepaymentAmountExpected);
        assertThat(lastRepaymentDateActual)
                .as(ErrorMessageHelper.wrongDataInLastRepaymentDate(lastRepaymentDateActual, lastRepaymentDateExpected))
                .isEqualTo(lastRepaymentDateExpected);

        eventAssertion.assertEvent(LoanStatusChangedEvent.class, loanId).extractingData(loanAccountDataV1 -> {
            String lastPaymentAmountEvent = String.valueOf(loanAccountDataV1.getDelinquent().getLastPaymentAmount().doubleValue());
            String lastPaymentDateEvent = FORMATTER.format(LocalDate.parse(loanAccountDataV1.getDelinquent().getLastPaymentDate()));
            String lastRepaymentAmountEvent = String.valueOf(loanAccountDataV1.getDelinquent().getLastRepaymentAmount().doubleValue());
            String lastRepaymentDateEvent = FORMATTER.format(LocalDate.parse(loanAccountDataV1.getDelinquent().getLastRepaymentDate()));

            assertThat(lastPaymentAmountEvent)
                    .as(ErrorMessageHelper.wrongDataInLastPaymentAmount(lastPaymentAmountEvent, lastPaymentAmountExpected))
                    .isEqualTo(lastPaymentAmountExpected);
            assertThat(lastPaymentDateEvent)
                    .as(ErrorMessageHelper.wrongDataInLastPaymentDate(lastPaymentDateEvent, lastPaymentDateExpected))
                    .isEqualTo(lastPaymentDateExpected);
            assertThat(lastRepaymentAmountEvent)
                    .as(ErrorMessageHelper.wrongDataInLastRepaymentAmount(lastRepaymentAmountEvent, lastRepaymentAmountExpected))
                    .isEqualTo(lastRepaymentAmountExpected);
            assertThat(lastRepaymentDateEvent)
                    .as(ErrorMessageHelper.wrongDataInLastRepaymentDate(lastRepaymentDateEvent, lastRepaymentDateExpected))
                    .isEqualTo(lastRepaymentDateExpected);

            return null;
        });

    }

    @And("Admin does a charge-off undo the loan with reversal external Id")
    public void chargeOffUndoWithReversalExternalId() throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        String reversalExternalId = Utils.randomNameGenerator("reversalExtId_", 3);
        PostLoansLoanIdTransactionsRequest chargeOffUndoRequest = LoanRequestFactory.defaultUndoChargeOffRequest()
                .reversalExternalId(reversalExternalId);

        Response<PostLoansLoanIdTransactionsResponse> chargeOffUndoResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, chargeOffUndoRequest, "undo-charge-off").execute();
        testContext().set(TestContextKey.LOAN_CHARGE_OFF_UNDO_RESPONSE, chargeOffUndoResponse);
        ErrorHelper.checkSuccessfulApiCall(chargeOffUndoResponse);

        Long transactionId = chargeOffUndoResponse.body().getResourceId();

        Response<GetLoansLoanIdTransactionsTransactionIdResponse> transactionResponse = loanTransactionsApi
                .retrieveTransaction(loanId, transactionId, "").execute();
        ErrorHelper.checkSuccessfulApiCall(transactionResponse);
        assertThat(transactionResponse.body().getReversalExternalId()).isEqualTo(reversalExternalId);
    }

    @Then("Loan Charge-off undo event has reversed on date {string} for charge-off undo")
    public void reversedOnDateIsNotNullForEvent(String reversedDate) throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanCreateResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);

        List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
        GetLoansLoanIdTransactions chargeOffTransaction = transactions.stream().filter(t -> "Charge-off".equals(t.getType().getValue()))
                .findFirst().orElseThrow(() -> new IllegalStateException(String.format("No transaction found")));
        Long chargeOffTransactionId = chargeOffTransaction.getId();

        eventAssertion.assertEvent(LoanChargeOffUndoEvent.class, chargeOffTransactionId).extractingData(loanTransactionDataV1 -> {
            String reversedOnDate = FORMATTER.format(LocalDate.parse(loanTransactionDataV1.getReversedOnDate()));
            assertThat(reversedOnDate).isEqualTo(reversedDate);
            return null;
        });
    }

    @Then("Loan has the following maturity data:")
    public void checkMaturity(DataTable table) throws IOException {
        List<List<String>> data = table.asLists();
        List<String> expectedValues = data.get(1);
        String actualMaturityDateExpected = expectedValues.get(0);
        String expectedMaturityDateExpected = expectedValues.get(1);

        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();
        Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
        GetLoansLoanIdTimeline timeline = loanDetailsResponse.body().getTimeline();
        String actualMaturityDateActual = FORMATTER.format(timeline.getActualMaturityDate());
        String expectedMaturityDateActual = FORMATTER.format(timeline.getExpectedMaturityDate());

        assertThat(actualMaturityDateActual)
                .as(ErrorMessageHelper.wrongDataInActualMaturityDate(actualMaturityDateActual, actualMaturityDateExpected))
                .isEqualTo(actualMaturityDateExpected);
        assertThat(expectedMaturityDateActual)
                .as(ErrorMessageHelper.wrongDataInExpectedMaturityDate(expectedMaturityDateActual, expectedMaturityDateExpected))
                .isEqualTo(expectedMaturityDateExpected);
    }

    @Then("Admin successfully deletes the loan with external id")
    public void deleteLoanWithExternalId() throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        Long loanId = loanCreateResponse.body().getLoanId();
        String loanExternalId = loanCreateResponse.body().getResourceExternalId();
        Response<DeleteLoansLoanIdResponse> deleteLoanResponse = loansApi.deleteLoanApplication1(loanExternalId).execute();
        assertThat(deleteLoanResponse.body().getLoanId()).isEqualTo(loanId);
        assertThat(deleteLoanResponse.body().getResourceExternalId()).isEqualTo(loanExternalId);
    }

    @Then("Admin fails to delete the loan with incorrect external id")
    public void failedDeleteLoanWithExternalId() throws IOException {
        Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        String loanExternalId = loanCreateResponse.body().getResourceExternalId();
        Response<DeleteLoansLoanIdResponse> deleteLoanResponse = loansApi.deleteLoanApplication1(loanExternalId.substring(5)).execute();
        ErrorResponse errorDetails = ErrorResponse.from(deleteLoanResponse);
        assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.dateFailureErrorCodeMsg()).isEqualTo(404);
    }

    @When("Admin set {string} loan product {string} transaction type to {string} future installment allocation rule")
    public void editFutureInstallmentAllocationTypeForLoanProduct(String loanProductName, String transactionTypeToChange,
            String futureInstallmentAllocationRuleNew) throws IOException {
        DefaultLoanProduct product = DefaultLoanProduct.valueOf(loanProductName);
        Long loanProductId = loanProductResolver.resolve(product);
        log.info("loanProductId {}", loanProductId);

        Response<GetLoanProductsProductIdResponse> loanProductDetails = loanProductsApi.retrieveLoanProductDetails(loanProductId).execute();
        ErrorHelper.checkSuccessfulApiCall(loanProductDetails);
        List<AdvancedPaymentData> paymentAllocation = loanProductDetails.body().getPaymentAllocation();

        List<AdvancedPaymentData> newPaymentAllocation = new ArrayList<>();
        paymentAllocation.forEach(e -> {
            String transactionTypeOriginal = e.getTransactionType();
            String futureInstallmentAllocationRule = e.getFutureInstallmentAllocationRule();
            if (transactionTypeToChange.equals(transactionTypeOriginal)) {
                futureInstallmentAllocationRule = futureInstallmentAllocationRuleNew;
            }
            newPaymentAllocation.add(
                    LoanProductGlobalInitializerStep.createPaymentAllocation(transactionTypeOriginal, futureInstallmentAllocationRule));
        });

        PutLoanProductsProductIdRequest putLoanProductsProductIdRequest = new PutLoanProductsProductIdRequest()
                .transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue()).paymentAllocation(newPaymentAllocation);

        Response<PutLoanProductsProductIdResponse> response = loanProductsApi
                .updateLoanProduct(loanProductId, putLoanProductsProductIdRequest).execute();
        ErrorHelper.checkSuccessfulApiCall(response);
    }

    @When("Admin sets repaymentStartDateType for {string} loan product to {string}")
    public void editRepaymentStartDateType(String loanProductName, String repaymentStartDateType) throws IOException {
        DefaultLoanProduct product = DefaultLoanProduct.valueOf(loanProductName);
        Long loanProductId = loanProductResolver.resolve(product);
        log.info("loanProductId {}", loanProductId);

        Map<String, Integer> repaymentStartDateTypeMap = Map.of("DISBURSEMENT_DATE", 1, "SUBMITTED_ON_DATE", 2);

        if (!repaymentStartDateTypeMap.containsKey(repaymentStartDateType)) {
            throw new IllegalArgumentException(String
                    .format("Invalid repaymentStartDateType: %s. Must be DISBURSEMENT_DATE or SUBMITTED_ON_DATE.", repaymentStartDateType));
        }

        int repaymentStartDateTypeValue = repaymentStartDateTypeMap.get(repaymentStartDateType);
        PutLoanProductsProductIdRequest putLoanProductsProductIdRequest = new PutLoanProductsProductIdRequest()//
                .repaymentStartDateType(repaymentStartDateTypeValue)//
                .locale(DEFAULT_LOCALE);//

        Response<PutLoanProductsProductIdResponse> response = loanProductsApi
                .updateLoanProduct(loanProductId, putLoanProductsProductIdRequest).execute();
        ErrorHelper.checkSuccessfulApiCall(response);
    }

    @And("Admin does write-off the loan on {string}")
    public void writeOffLoan(String transactionDate) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        PostLoansLoanIdTransactionsRequest writeOffRequest = LoanRequestFactory.defaultWriteOffRequest().transactionDate(transactionDate)
                .dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);

        Response<PostLoansLoanIdTransactionsResponse> writeOffResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, writeOffRequest, "writeoff").execute();
        testContext().set(TestContextKey.LOAN_WRITE_OFF_RESPONSE, writeOffResponse);
        ErrorHelper.checkSuccessfulApiCall(writeOffResponse);
    }

    @Then("Admin fails to undo {string}th transaction made on {string}")
    public void undoTransaction(String nthTransaction, String transactionDate) throws IOException {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();
        List<GetLoansLoanIdTransactions> transactions = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute().body()
                .getTransactions();

        int nthItem = Integer.parseInt(nthTransaction) - 1;
        GetLoansLoanIdTransactions targetTransaction = transactions.stream()
                .filter(t -> transactionDate.equals(formatter.format(t.getDate()))).toList().get(nthItem);

        PostLoansLoanIdTransactionsTransactionIdRequest transactionUndoRequest = LoanRequestFactory.defaultTransactionUndoRequest()
                .transactionDate(transactionDate);

        Response<PostLoansLoanIdTransactionsResponse> transactionUndoResponse = loanTransactionsApi
                .adjustLoanTransaction(loanId, targetTransaction.getId(), transactionUndoRequest, "").execute();
        ErrorResponse errorDetails = ErrorResponse.from(transactionUndoResponse);
        assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.dateFailureErrorCodeMsg()).isEqualTo(503);

    }

    @Then("Loan {string} repayment transaction on {string} with {double} EUR transaction amount results in error")
    public void loanTransactionWithErrorCheck(String repaymentType, String transactionDate, double transactionAmount) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        DefaultPaymentType paymentType = DefaultPaymentType.valueOf(repaymentType);
        long paymentTypeValue = paymentTypeResolver.resolve(paymentType);

        Map<String, String> headerMap = new HashMap<>();

        PostLoansLoanIdTransactionsRequest repaymentRequest = LoanRequestFactory.defaultRepaymentRequest().transactionDate(transactionDate)
                .transactionAmount(transactionAmount).paymentTypeId(paymentTypeValue).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE);

        Response<PostLoansLoanIdTransactionsResponse> repaymentResponse = loanTransactionsApi
                .executeLoanTransaction(loanId, repaymentRequest, "repayment", headerMap).execute();

        ErrorResponse errorDetails = ErrorResponse.from(repaymentResponse);
        assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.dateFailureErrorCodeMsg()).isEqualTo(400);

    }

    @Then("Loan details has the downpayment amount {string} in summary.totalRepaymentTransaction")
    public void totalRepaymentTransaction(String expectedAmount) throws IOException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetails);

        Double expectedAmountParsed = Double.parseDouble(expectedAmount);
        Double totalRepaymentTransaction = loanDetails.body().getSummary().getTotalRepaymentTransaction();

        assertThat(totalRepaymentTransaction)
                .as(ErrorMessageHelper.wrongAmountInTotalRepaymentTransaction(totalRepaymentTransaction, expectedAmountParsed))
                .isEqualTo(expectedAmountParsed);
    }

    @Then("LoanDetails has fixedLength field with int value: {int}")
    public void checkLoanDetailsFieldAndValueInt(int fieldValue) throws IOException, NoSuchMethodException {
        Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
        long loanId = loanResponse.body().getLoanId();

        Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
        ErrorHelper.checkSuccessfulApiCall(loanDetails);

        Integer fixedLengthactual = loanDetails.body().getFixedLength();
        assertThat(fixedLengthactual).as(ErrorMessageHelper.wrongfixedLength(fixedLengthactual, fieldValue)).isEqualTo(fieldValue);
    }

    private LoanStatusEnumDataV1 getExpectedStatus(String loanStatus) {
        LoanStatusEnumDataV1 result = new LoanStatusEnumDataV1();
        switch (loanStatus) {
            case "Submitted and pending approval" -> {
                result.setId(100);
                result.setCode("loanStatusType.submitted.and.pending.approval");
                result.setValue("Submitted and pending approval");
                result.setPendingApproval(true);
                result.setWaitingForDisbursal(false);
                result.setActive(false);
                result.setClosedObligationsMet(false);
                result.setClosedWrittenOff(false);
                result.setClosedRescheduled(false);
                result.setClosed(false);
                result.setOverpaid(false);
            }
            case "Approved" -> {
                result.setId(200);
                result.setCode("loanStatusType.approved");
                result.setValue("Approved");
                result.setPendingApproval(false);
                result.setWaitingForDisbursal(true);
                result.setActive(false);
                result.setClosedObligationsMet(false);
                result.setClosedWrittenOff(false);
                result.setClosedRescheduled(false);
                result.setClosed(false);
                result.setOverpaid(false);
            }
            case "Active" -> {
                result.setId(300);
                result.setCode("loanStatusType.active");
                result.setValue("Active");
                result.setPendingApproval(false);
                result.setWaitingForDisbursal(false);
                result.setActive(true);
                result.setClosedObligationsMet(false);
                result.setClosedWrittenOff(false);
                result.setClosedRescheduled(false);
                result.setClosed(false);
                result.setOverpaid(false);
            }
            case "Closed (obligations met)" -> {
                result.setId(600);
                result.setCode("loanStatusType.closed.obligations.met");
                result.setValue("Closed (obligations met)");
                result.setPendingApproval(false);
                result.setWaitingForDisbursal(false);
                result.setActive(false);
                result.setClosedObligationsMet(true);
                result.setClosedWrittenOff(false);
                result.setClosedRescheduled(false);
                result.setClosed(true);
                result.setOverpaid(false);
            }
            case "Overpaid" -> {
                result.setId(700);
                result.setCode("loanStatusType.overpaid");
                result.setValue("Overpaid");
                result.setPendingApproval(false);
                result.setWaitingForDisbursal(false);
                result.setActive(false);
                result.setClosedObligationsMet(false);
                result.setClosedWrittenOff(false);
                result.setClosedRescheduled(false);
                result.setClosed(false);
                result.setOverpaid(true);

            }
            default -> throw new UnsupportedOperationException("Not yet covered loan status: " + loanStatus);
        }
        return result;
    }

    @SuppressFBWarnings("SF_SWITCH_NO_DEFAULT")
    private List<String> fetchValuesOfTransaction(List<String> header, GetLoansLoanIdTransactions t) {
        List<String> actualValues = new ArrayList<>();
        for (String headerName : header) {
            switch (headerName) {
                case "Transaction date" -> actualValues.add(t.getDate() == null ? null : FORMATTER.format(t.getDate()));
                case "Transaction Type" -> actualValues.add(t.getType().getValue() == null ? null : t.getType().getValue());
                case "Amount" -> actualValues.add(t.getAmount() == null ? null : String.valueOf(t.getAmount()));
                case "Principal" -> actualValues.add(t.getPrincipalPortion() == null ? null : String.valueOf(t.getPrincipalPortion()));
                case "Interest" -> actualValues.add(t.getInterestPortion() == null ? null : String.valueOf(t.getInterestPortion()));
                case "Fees" -> actualValues.add(t.getFeeChargesPortion() == null ? null : String.valueOf(t.getFeeChargesPortion()));
                case "Penalties" ->
                    actualValues.add(t.getPenaltyChargesPortion() == null ? null : String.valueOf(t.getPenaltyChargesPortion()));
                case "Loan Balance" ->
                    actualValues.add(t.getOutstandingLoanBalance() == null ? null : String.valueOf(t.getOutstandingLoanBalance()));
                case "Overpayment" ->
                    actualValues.add(t.getOverpaymentPortion() == null ? null : String.valueOf(t.getOverpaymentPortion()));
                case "Reverted" -> actualValues.add(t.getManuallyReversed() == null ? null : String.valueOf(t.getManuallyReversed()));
            }
        }
        return actualValues;
    }

    @SuppressFBWarnings("SF_SWITCH_NO_DEFAULT")
    private List<String> fetchValuesOfRepaymentSchedule(List<String> header, GetLoansLoanIdRepaymentPeriod repaymentPeriod) {
        List<String> actualValues = new ArrayList<>();
        for (String headerName : header) {
            switch (headerName) {
                case "Nr" -> actualValues.add(repaymentPeriod.getPeriod() == null ? null : String.valueOf(repaymentPeriod.getPeriod()));
                case "Days" ->
                    actualValues.add(repaymentPeriod.getDaysInPeriod() == null ? null : String.valueOf(repaymentPeriod.getDaysInPeriod()));
                case "Date" ->
                    actualValues.add(repaymentPeriod.getDueDate() == null ? null : FORMATTER.format(repaymentPeriod.getDueDate()));
                case "Paid date" -> actualValues.add(repaymentPeriod.getObligationsMetOnDate() == null ? null
                        : FORMATTER.format(repaymentPeriod.getObligationsMetOnDate()));
                case "Balance of loan" -> actualValues.add(repaymentPeriod.getPrincipalLoanBalanceOutstanding() == null ? null
                        : String.valueOf(repaymentPeriod.getPrincipalLoanBalanceOutstanding()));
                case "Principal due" ->
                    actualValues.add(repaymentPeriod.getPrincipalDue() == null ? null : String.valueOf(repaymentPeriod.getPrincipalDue()));
                case "Interest" ->
                    actualValues.add(repaymentPeriod.getInterestDue() == null ? null : String.valueOf(repaymentPeriod.getInterestDue()));
                case "Fees" -> actualValues
                        .add(repaymentPeriod.getFeeChargesDue() == null ? null : String.valueOf(repaymentPeriod.getFeeChargesDue()));
                case "Penalties" -> actualValues.add(
                        repaymentPeriod.getPenaltyChargesDue() == null ? null : String.valueOf(repaymentPeriod.getPenaltyChargesDue()));
                case "Due" -> actualValues.add(
                        repaymentPeriod.getTotalDueForPeriod() == null ? null : String.valueOf(repaymentPeriod.getTotalDueForPeriod()));
                case "Paid" -> actualValues.add(
                        repaymentPeriod.getTotalPaidForPeriod() == null ? null : String.valueOf(repaymentPeriod.getTotalPaidForPeriod()));
                case "In advance" -> actualValues.add(repaymentPeriod.getTotalPaidInAdvanceForPeriod() == null ? null
                        : String.valueOf(repaymentPeriod.getTotalPaidInAdvanceForPeriod()));
                case "Late" -> actualValues.add(repaymentPeriod.getTotalPaidLateForPeriod() == null ? null
                        : String.valueOf(repaymentPeriod.getTotalPaidLateForPeriod()));
                case "Waived" -> actualValues.add(repaymentPeriod.getTotalWaivedForPeriod() == null ? null
                        : String.valueOf(repaymentPeriod.getTotalWaivedForPeriod()));
                case "Outstanding" -> actualValues.add(repaymentPeriod.getTotalOutstandingForPeriod() == null ? null
                        : String.valueOf(repaymentPeriod.getTotalOutstandingForPeriod()));
            }
        }
        return actualValues;
    }

    @SuppressFBWarnings("SF_SWITCH_NO_DEFAULT")
    private List<String> validateRepaymentScheduleTotal(List<String> header, GetLoansLoanIdRepaymentSchedule repaymentSchedule,
            List<String> expectedAmounts) {
        List<String> actualValues = new ArrayList<>();
        // total paid for all periods
        Double paidActual = 0.0;
        List<GetLoansLoanIdRepaymentPeriod> periods = repaymentSchedule.getPeriods();
        for (GetLoansLoanIdRepaymentPeriod period : periods) {
            if (null != period.getTotalPaidForPeriod()) {
                paidActual += period.getTotalPaidForPeriod();
            }
        }
        BigDecimal paidActualBd = new BigDecimal(paidActual).setScale(2, RoundingMode.HALF_DOWN);

        for (int i = 0; i < header.size(); i++) {
            String headerName = header.get(i);
            String expectedValue = expectedAmounts.get(i);
            switch (headerName) {
                case "Principal due" -> assertThat(repaymentSchedule.getTotalPrincipalExpected())//
                        .as(ErrorMessageHelper.wrongAmountInRepaymentSchedulePrincipal(repaymentSchedule.getTotalPrincipalExpected(),
                                Double.valueOf(expectedValue)))//
                        .isEqualTo(Double.valueOf(expectedValue));//
                case "Interest" -> assertThat(repaymentSchedule.getTotalInterestCharged())//
                        .as(ErrorMessageHelper.wrongAmountInRepaymentScheduleInterest(repaymentSchedule.getTotalInterestCharged(),
                                Double.valueOf(expectedValue)))//
                        .isEqualTo(Double.valueOf(expectedValue));//
                case "Fees" -> assertThat(repaymentSchedule.getTotalFeeChargesCharged())//
                        .as(ErrorMessageHelper.wrongAmountInRepaymentScheduleFees(repaymentSchedule.getTotalFeeChargesCharged(),
                                Double.valueOf(expectedValue)))//
                        .isEqualTo(Double.valueOf(expectedValue));//
                case "Penalties" -> assertThat(repaymentSchedule.getTotalPenaltyChargesCharged())//
                        .as(ErrorMessageHelper.wrongAmountInRepaymentSchedulePenalties(repaymentSchedule.getTotalPenaltyChargesCharged(),
                                Double.valueOf(expectedValue)))//
                        .isEqualTo(Double.valueOf(expectedValue));//
                case "Due" -> assertThat(repaymentSchedule.getTotalRepaymentExpected())//
                        .as(ErrorMessageHelper.wrongAmountInRepaymentScheduleDue(repaymentSchedule.getTotalRepaymentExpected(),
                                Double.valueOf(expectedValue)))//
                        .isEqualTo(Double.valueOf(expectedValue));//
                case "Paid" -> assertThat(paidActualBd.doubleValue())//
                        .as(ErrorMessageHelper.wrongAmountInRepaymentSchedulePaid(paidActualBd.doubleValue(),
                                Double.valueOf(expectedValue)))//
                        .isEqualTo(Double.valueOf(expectedValue));//
                case "In advance" -> assertThat(repaymentSchedule.getTotalPaidInAdvance())//
                        .as(ErrorMessageHelper.wrongAmountInRepaymentScheduleInAdvance(repaymentSchedule.getTotalPaidInAdvance(),
                                Double.valueOf(expectedValue)))//
                        .isEqualTo(Double.valueOf(expectedValue));//
                case "Late" -> assertThat(repaymentSchedule.getTotalPaidLate())//
                        .as(ErrorMessageHelper.wrongAmountInRepaymentScheduleLate(repaymentSchedule.getTotalPaidLate(),
                                Double.valueOf(expectedValue)))//
                        .isEqualTo(Double.valueOf(expectedValue));//
                case "Waived" -> assertThat(repaymentSchedule.getTotalWaived())//
                        .as(ErrorMessageHelper.wrongAmountInRepaymentScheduleWaived(repaymentSchedule.getTotalWaived(),
                                Double.valueOf(expectedValue)))//
                        .isEqualTo(Double.valueOf(expectedValue));//
                case "Outstanding" -> assertThat(repaymentSchedule.getTotalOutstanding())//
                        .as(ErrorMessageHelper.wrongAmountInRepaymentScheduleOutstanding(repaymentSchedule.getTotalOutstanding(),
                                Double.valueOf(expectedValue)))//
                        .isEqualTo(Double.valueOf(expectedValue));//
            }
        }
        return actualValues;
    }
}
