/**
 * 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.integrationtests;

import static org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType.BUSINESS_DATE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.math.BigDecimal;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.fineract.client.models.BusinessDateRequest;
import org.apache.fineract.client.models.GetLoansLoanIdLoanInstallmentLevelDelinquency;
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.PostLoanProductsRequest;
import org.apache.fineract.client.models.PostLoanProductsResponse;
import org.apache.fineract.client.models.PostLoansResponse;
import org.apache.fineract.client.models.PutLoanProductsProductIdRequest;
import org.apache.fineract.client.models.PutLoansLoanIdRequest;
import org.apache.fineract.client.models.PutLoansLoanIdResponse;
import org.apache.fineract.client.util.CallFailedRuntimeException;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.SchedulerJobHelper;
import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
import org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

@Slf4j
@ExtendWith(LoanTestLifecycleExtension.class)
public class InstallmentLevelDelinquencyAPIIntegrationTests extends BaseLoanIntegrationTest {

    private SchedulerJobHelper schedulerJobHelper = new SchedulerJobHelper(this.requestSpec);

    @Test
    public void testInstallmentLevelDelinquencyFourRangesInTheBucket() {
        runAt("31 May 2023", () -> {
            // Create Client
            Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();

            // Create DelinquencyBuckets
            Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec, List.of(//
                    Pair.of(1, 10), //
                    Pair.of(11, 30), //
                    Pair.of(31, 60), //
                    Pair.of(61, null)//
            ));

            // Create Loan Product
            PostLoanProductsRequest loanProductsRequest = create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
                    InterestType.FLAT, AmortizationType.EQUAL_INSTALLMENTS);
            loanProductsRequest.setEnableInstallmentLevelDelinquency(true);
            loanProductsRequest.setDelinquencyBucketId(delinquencyBucketId.longValue());
            PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(loanProductsRequest);

            // Apply and Approve Loan
            Long loanId = applyAndApproveLoan(clientId, loanProductResponse.getResourceId(), "01 January 2023", 1250.0, 4);

            // Disburse Loan
            disburseLoan(loanId, BigDecimal.valueOf(1250), "01 January 2023");

            // Verify Repayment Schedule and Due Dates
            verifyRepaymentSchedule(loanId, //
                    installment(1250.0, null, "01 January 2023"), //
                    installment(312.0, false, "31 January 2023"), // 120 days delinquent -> range4
                    installment(312.0, false, "02 March 2023"), // 90 days delinquent -> range4
                    installment(312.0, false, "01 April 2023"), // 60 days delinquent -> range3
                    installment(314.0, false, "01 May 2023") // 30 days delinquent -> range2
            );

            // since the current day is 31 May 2023, therefore all the installments are delinquent
            verifyDelinquency(loanId, 120, "1250.0", //
                    delinquency(11, 30, "314.0"), // 4th installment
                    delinquency(31, 60, "312.0"), // 3rd installment
                    delinquency(61, null, "624.0") // 1st installment + 2nd installment
            );

            // Repayment of the first two installments
            addRepaymentForLoan(loanId, 626.0, "31 May 2023");
            verifyDelinquency(loanId, 60, "624.0", //
                    delinquency(11, 30, "314.0"), // 4th installment
                    delinquency(31, 60, "310.0") // 3rd installment
            );

            // Partial repayment
            addRepaymentForLoan(loanId, 100.0, "31 May 2023");
            verifyDelinquency(loanId, 60, "524.0", //
                    delinquency(11, 30, "314.0"), // 4th installment
                    delinquency(31, 60, "210.0") // 3rd installment
            );

            // Repay the loan fully
            addRepaymentForLoan(loanId, 524.0, "31 May 2023");
            verifyDelinquency(loanId, 0, "0.0");
        });
    }

    @Test
    public void testInstallmentLevelDelinquencyTwoRangesInTheBucket() {
        runAt("31 May 2023", () -> {
            // Create Client
            Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();

            // Create DelinquencyBuckets
            Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec, List.of(//
                    Pair.of(1, 60), //
                    Pair.of(61, null)//
            ));

            // Create Loan Product
            PostLoanProductsRequest loanProductsRequest = create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
                    InterestType.FLAT, AmortizationType.EQUAL_INSTALLMENTS);
            loanProductsRequest.setEnableInstallmentLevelDelinquency(true);
            loanProductsRequest.setDelinquencyBucketId(delinquencyBucketId.longValue());
            PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(loanProductsRequest);

            // Apply and Approve Loan
            Long loanId = applyAndApproveLoan(clientId, loanProductResponse.getResourceId(), "01 January 2023", 1250.0, 4);

            // Disburse Loan
            disburseLoan(loanId, BigDecimal.valueOf(1250), "01 January 2023");

            // Verify Repayment Schedule and Due Dates
            verifyRepaymentSchedule(loanId, //
                    installment(1250.0, null, "01 January 2023"), //
                    installment(312.0, false, "31 January 2023"), // 120 days delinquent -> range2
                    installment(312.0, false, "02 March 2023"), // 90 days delinquent -> range2
                    installment(312.0, false, "01 April 2023"), // 60 days delinquent -> range1
                    installment(314.0, false, "01 May 2023") // 30 days delinquent -> range1
            );

            verifyDelinquency(loanId, 120, "1250.0", //
                    delinquency(1, 60, "626.0"), // 4th installment
                    delinquency(61, null, "624.0") // 1st installment + 2nd installment
            );

            // repay the first installment
            addRepaymentForLoan(loanId, 313.0, "31 May 2023");

            verifyDelinquency(loanId, 90, "937.0", //
                    delinquency(1, 60, "626.0"), // 4th installment
                    delinquency(61, null, "311.0") // 1st installment + 2nd installment
            );

        });
    }

    @Test
    public void testInstallmentLevelDelinquencyIsTurnedOff() {
        runAt("31 May 2023", () -> {
            // Create Client
            Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();

            // Create DelinquencyBuckets
            Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec, List.of(//
                    Pair.of(1, 60), //
                    Pair.of(61, null)//
            ));

            // Create Loan Product
            PostLoanProductsRequest loanProductsRequest = create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
                    InterestType.FLAT, AmortizationType.EQUAL_INSTALLMENTS);
            loanProductsRequest.setEnableInstallmentLevelDelinquency(false);
            loanProductsRequest.setDelinquencyBucketId(delinquencyBucketId.longValue());
            PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(loanProductsRequest);

            // Apply and Approve Loan
            Long loanId = applyAndApproveLoan(clientId, loanProductResponse.getResourceId(), "01 January 2023", 1250.0, 4);

            // Disburse Loan
            disburseLoan(loanId, BigDecimal.valueOf(1250), "01 January 2023");

            // Verify Repayment Schedule and Due Dates
            verifyRepaymentSchedule(loanId, //
                    installment(1250.0, null, "01 January 2023"), //
                    installment(312.0, false, "31 January 2023"), // 120 days delinquent -> range2
                    installment(312.0, false, "02 March 2023"), // 90 days delinquent -> range2
                    installment(312.0, false, "01 April 2023"), // 60 days delinquent -> range1
                    installment(314.0, false, "01 May 2023") // 30 days delinquent -> range1
            );

            // this should be empty as the installment level delinquency is not enabled for this loan
            verifyDelinquency(loanId, 120, "1250.0");
        });
    }

    @Test
    public void testInstallmentLevelDelinquencyUpdatedWhenCOBIsExecuted() {
        runAt("01 February 2023", () -> {
            // Create Client
            Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();

            // Create DelinquencyBuckets
            Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec, List.of(//
                    Pair.of(1, 1), //
                    Pair.of(2, null)//
            ));

            // Create Loan Product
            PostLoanProductsRequest loanProductsRequest = create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
                    InterestType.FLAT, AmortizationType.EQUAL_INSTALLMENTS);
            loanProductsRequest.setEnableInstallmentLevelDelinquency(true);
            loanProductsRequest.setDelinquencyBucketId(delinquencyBucketId.longValue());
            PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(loanProductsRequest);

            // Apply and Approve Loan
            Long loanId = applyAndApproveLoan(clientId, loanProductResponse.getResourceId(), "01 January 2023", 1250.0, 4);

            // Disburse Loan
            disburseLoan(loanId, BigDecimal.valueOf(1250), "01 January 2023");

            // Verify Repayment Schedule and Due Dates
            verifyRepaymentSchedule(loanId, //
                    installment(1250.0, null, "01 January 2023"), installment(312.0, false, "31 January 2023"),
                    installment(312.0, false, "02 March 2023"), installment(312.0, false, "01 April 2023"),
                    installment(314.0, false, "01 May 2023"));

            // The first installment falls into the first range
            verifyDelinquency(loanId, 1, "312.0", //
                    delinquency(1, 1, "312.0") // 4th installment
            );

            // Let's go one day ahead in the time
            updateBusinessDateAndExecuteCOBJob("2 February 2023");

            // The first installment is not two days delinquent and therefore falls into the second range
            verifyDelinquency(loanId, 2, "312.0", //
                    delinquency(2, null, "312.0") // 4th installment
            );
        });
    }

    @Test
    public void testInstallmentLevelDelinquencyTurnedOnForProductAndOffForLoan() {
        runAt("31 May 2023", () -> {
            // Create Client
            Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();

            // Create DelinquencyBuckets
            Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec, List.of(//
                    Pair.of(1, 10), //
                    Pair.of(11, 30), //
                    Pair.of(31, 60), //
                    Pair.of(61, null)//
            ));

            // Create Loan Product
            PostLoanProductsRequest loanProductsRequest = create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
                    InterestType.FLAT, AmortizationType.EQUAL_INSTALLMENTS);
            // set installment level delinquency as true
            loanProductsRequest.setEnableInstallmentLevelDelinquency(true);
            loanProductsRequest.setDelinquencyBucketId(delinquencyBucketId.longValue());
            PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(loanProductsRequest);

            // Apply and Approve Loan, turn loan level installment delinquency as false
            Long loanId = applyAndApproveLoan(clientId, loanProductResponse.getResourceId(), "01 January 2023", 1250.0, 4,
                    req -> req.setEnableInstallmentLevelDelinquency(false));

            // Disburse Loan
            disburseLoan(loanId, BigDecimal.valueOf(1250), "01 January 2023");

            // Verify Repayment Schedule and Due Dates
            verifyRepaymentSchedule(loanId, //
                    installment(1250.0, null, "01 January 2023"), //
                    installment(312.0, false, "31 January 2023"), // 120 days delinquent -> range4
                    installment(312.0, false, "02 March 2023"), // 90 days delinquent -> range4
                    installment(312.0, false, "01 April 2023"), // 60 days delinquent -> range3
                    installment(314.0, false, "01 May 2023") // 30 days delinquent -> range2
            );

            // since the installment level delinquency is overridden and set as false for loan application, therefore it
            // is not calculated
            verifyDelinquency(loanId, 120, "1250.0");
        });

    }

    @Test
    public void testInstallmentLevelDelinquencyTurnedOffForProductAndOnForLoan() {
        runAt("31 May 2023", () -> {
            // Create Client
            Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();

            // Create DelinquencyBuckets
            Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec, List.of(//
                    Pair.of(1, 10), //
                    Pair.of(11, 30), //
                    Pair.of(31, 60), //
                    Pair.of(61, null)//
            ));

            // Create Loan Product
            PostLoanProductsRequest loanProductsRequest = create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
                    InterestType.FLAT, AmortizationType.EQUAL_INSTALLMENTS);
            // set installment level delinquency as false
            loanProductsRequest.setEnableInstallmentLevelDelinquency(false);
            loanProductsRequest.setDelinquencyBucketId(delinquencyBucketId.longValue());
            PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(loanProductsRequest);

            // Apply and Approve Loan, turn loan level installment delinquency as true
            Long loanId = applyAndApproveLoan(clientId, loanProductResponse.getResourceId(), "01 January 2023", 1250.0, 4,
                    req -> req.setEnableInstallmentLevelDelinquency(true));

            // Disburse Loan
            disburseLoan(loanId, BigDecimal.valueOf(1250), "01 January 2023");

            // Verify Repayment Schedule and Due Dates
            verifyRepaymentSchedule(loanId, //
                    installment(1250.0, null, "01 January 2023"), //
                    installment(312.0, false, "31 January 2023"), // 120 days delinquent -> range4
                    installment(312.0, false, "02 March 2023"), // 90 days delinquent -> range4
                    installment(312.0, false, "01 April 2023"), // 60 days delinquent -> range3
                    installment(314.0, false, "01 May 2023") // 30 days delinquent -> range2
            );

            // since the installment level delinquency is overridden and set as true for loan application, therefore it
            // is calculated
            verifyDelinquency(loanId, 120, "1250.0", //
                    delinquency(11, 30, "314.0"), // 4th installment
                    delinquency(31, 60, "312.0"), // 3rd installment
                    delinquency(61, null, "624.0") // 1st installment + 2nd installment
            );
        });

    }

    @Test
    public void testLoanInheritsInstallmentLevelSettingFromLoanProductIfNotSet() {
        runAt("31 May 2023", () -> {
            // Create Client
            Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();

            // Create DelinquencyBuckets
            Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec, List.of(//
                    Pair.of(1, 10), //
                    Pair.of(11, 30), //
                    Pair.of(31, 60), //
                    Pair.of(61, null)//
            ));

            // Create Loan Product
            PostLoanProductsRequest loanProductsRequest = create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
                    InterestType.FLAT, AmortizationType.EQUAL_INSTALLMENTS);
            // set installment level delinquency as true
            loanProductsRequest.setEnableInstallmentLevelDelinquency(true);
            loanProductsRequest.setDelinquencyBucketId(delinquencyBucketId.longValue());
            PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(loanProductsRequest);

            // Apply and Approve Loan, do not set installment level delinquency
            Long loanId = applyAndApproveLoan(clientId, loanProductResponse.getResourceId(), "01 January 2023", 1250.0, 4);

            // Disburse Loan
            disburseLoan(loanId, BigDecimal.valueOf(1250), "01 January 2023");

            // Verify Repayment Schedule and Due Dates
            verifyRepaymentSchedule(loanId, //
                    installment(1250.0, null, "01 January 2023"), //
                    installment(312.0, false, "31 January 2023"), // 120 days delinquent -> range4
                    installment(312.0, false, "02 March 2023"), // 90 days delinquent -> range4
                    installment(312.0, false, "01 April 2023"), // 60 days delinquent -> range3
                    installment(314.0, false, "01 May 2023") // 30 days delinquent -> range2
            );

            // since the installment level delinquency is inherited from loan product, therefore it
            // is calculated
            verifyDelinquency(loanId, 120, "1250.0", //
                    delinquency(11, 30, "314.0"), // 4th installment
                    delinquency(31, 60, "312.0"), // 3rd installment
                    delinquency(61, null, "624.0") // 1st installment + 2nd installment
            );
        });

    }

    @Test
    public void tesInstallmentLevelSettingForLoanWithLoanProductWithoutDelinquencyBucketValidation() {

        runAt("31 May 2023", () -> {
            // Create Client
            Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();

            // Create Loan Product
            PostLoanProductsRequest loanProductsRequest = create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
                    InterestType.FLAT, AmortizationType.EQUAL_INSTALLMENTS);
            PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(loanProductsRequest);

            // Apply For Loan with installment level delinquency setting
            CallFailedRuntimeException callFailedRuntimeException = Assertions.assertThrows(CallFailedRuntimeException.class,
                    () -> loanTransactionHelper.applyLoan(applyLoanRequest(clientId, loanProductResponse.getResourceId(), "01 January 2023",
                            1250.0, 4, req -> req.setEnableInstallmentLevelDelinquency(true))));

            Assertions.assertTrue(callFailedRuntimeException.getMessage().contains(
                    "Installment level delinquency cannot be enabled for a loan if Delinquency bucket is not configured for loan product"));

        });

    }

    @Test
    public void testLoanInstallmentLevelSettingModification() {
        runAt("31 May 2023", () -> {
            // Create Client
            Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();

            // Create DelinquencyBuckets
            Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec, List.of(//
                    Pair.of(1, 10), //
                    Pair.of(11, 30), //
                    Pair.of(31, 60), //
                    Pair.of(61, null)//
            ));

            // Create Loan Product
            PostLoanProductsRequest loanProductsRequest = create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
                    InterestType.FLAT, AmortizationType.EQUAL_INSTALLMENTS);

            // set delinquency bucket
            loanProductsRequest.setDelinquencyBucketId(delinquencyBucketId.longValue());
            PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(loanProductsRequest);

            // Apply for loan
            Long loanId = loanTransactionHelper
                    .applyLoan(applyLoanRequest(clientId, loanProductResponse.getResourceId(), "01 January 2023", 1250.0, 4))
                    .getResourceId();

            // verify installment level delinquency setting for loan
            GetLoansLoanIdResponse loanResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId.intValue());
            assertThat(loanResponse.getEnableInstallmentLevelDelinquency()).isFalse();

            // Modify installment level delinquency as true for loan
            PutLoansLoanIdResponse loansModificationResponse = loanTransactionHelper.modifyApplicationForLoan(loanId, "modify",
                    new PutLoansLoanIdRequest().clientId(clientId).productId(loanProductResponse.getResourceId()).loanType("individual")
                            .enableInstallmentLevelDelinquency(true).locale("en").dateFormat(DATETIME_PATTERN));

            // verify installment level delinquency setting for loan
            loanResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId.intValue());
            assertThat(loanResponse.getEnableInstallmentLevelDelinquency()).isTrue();

            // Approve Loan
            loanTransactionHelper.approveLoan(loanId, approveLoanRequest(1250.0, "01 January 2023"));

            // Disburse Loan
            disburseLoan(loanId, BigDecimal.valueOf(1250), "01 January 2023");

            // Verify Repayment Schedule and Due Dates
            verifyRepaymentSchedule(loanId, //
                    installment(1250.0, null, "01 January 2023"), //
                    installment(312.0, false, "31 January 2023"), // 120 days delinquent -> range4
                    installment(312.0, false, "02 March 2023"), // 90 days delinquent -> range4
                    installment(312.0, false, "01 April 2023"), // 60 days delinquent -> range3
                    installment(314.0, false, "01 May 2023") // 30 days delinquent -> range2
            );

            // since the installment level delinquency is modified as true for loan, therefore it
            // is calculated
            verifyDelinquency(loanId, 120, "1250.0", //
                    delinquency(11, 30, "314.0"), // 4th installment
                    delinquency(31, 60, "312.0"), // 3rd installment
                    delinquency(61, null, "624.0") // 1st installment + 2nd installment
            );

        });

    }

    @Test
    public void tesInstallmentLevelSettingModificationForLoanWithLoanProductWithoutDelinquencyBucketValidation() {

        runAt("31 May 2023", () -> {
            // Create Client
            Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();

            // Create Loan Product without delinquency bucket
            PostLoanProductsRequest loanProductsRequest = create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
                    InterestType.FLAT, AmortizationType.EQUAL_INSTALLMENTS);
            PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(loanProductsRequest);

            // Apply for loan
            Long loanId = loanTransactionHelper
                    .applyLoan(applyLoanRequest(clientId, loanProductResponse.getResourceId(), "01 January 2023", 1250.0, 4))
                    .getResourceId();

            // Modify Loan with installment level delinquency setting
            CallFailedRuntimeException callFailedRuntimeException = Assertions.assertThrows(CallFailedRuntimeException.class,
                    () -> loanTransactionHelper.modifyApplicationForLoan(loanId, "modify",
                            new PutLoansLoanIdRequest().clientId(clientId).productId(loanProductResponse.getResourceId())
                                    .loanType("individual").enableInstallmentLevelDelinquency(true).locale("en")
                                    .dateFormat(DATETIME_PATTERN)));

            Assertions.assertTrue(callFailedRuntimeException.getMessage().contains(
                    "Installment level delinquency cannot be enabled for a loan if Delinquency bucket is not configured for loan product"));

        });
    }

    @Test
    public void testCalculateRepaymentScheduleWorksWithInstallmentLevelDelinquencySetting() {
        runAt("31 May 2023", () -> {
            // Create Client
            Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();

            // Create DelinquencyBuckets
            Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec, List.of(//
                    Pair.of(1, 10), //
                    Pair.of(11, 30), //
                    Pair.of(31, 60), //
                    Pair.of(61, null)//
            ));

            // Create Loan Product
            PostLoanProductsRequest loanProductsRequest = create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
                    InterestType.FLAT, AmortizationType.EQUAL_INSTALLMENTS);

            // set installment level delinquency as false
            loanProductsRequest.setEnableInstallmentLevelDelinquency(false);
            loanProductsRequest.setDelinquencyBucketId(delinquencyBucketId.longValue());
            PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(loanProductsRequest);

            // run calculateLoanSchedule command works, while Applying for loan with installment level delinquency
            PostLoansResponse loansResponse = loanTransactionHelper
                    .calculateRepaymentScheduleForApplyLoan(applyLoanRequest(clientId, loanProductResponse.getResourceId(),
                            "01 January 2023", 1250.0, 4, req -> req.setEnableInstallmentLevelDelinquency(true)), "calculateLoanSchedule");

            assertThat(loansResponse).isNotNull();
            assertNotNull(loansResponse.getPeriods());
            assertThat(loansResponse.getPeriods().size()).isEqualTo(5);

        });

    }

    @Test
    public void tesInstallmentLevelSettingForLoanProductWithoutDelinquencyBucketValidation() {

        runAt("31 May 2023", () -> {
            // Create Client
            Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();

            // Create Loan Product without delinquency bucket
            PostLoanProductsRequest loanProductsRequest = create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
                    InterestType.FLAT, AmortizationType.EQUAL_INSTALLMENTS);
            // set installment level delinquency as true
            loanProductsRequest.setEnableInstallmentLevelDelinquency(true);

            // Create loan product with installment level delinquency setting
            CallFailedRuntimeException callFailedRuntimeException = Assertions.assertThrows(CallFailedRuntimeException.class,
                    () -> loanProductHelper.createLoanProduct(loanProductsRequest));

            Assertions.assertTrue(callFailedRuntimeException.getMessage()
                    .contains("Installment level delinquency cannot be enabled if Delinquency bucket is not configured for loan product"));

        });

    }

    @Test
    public void tesUpdateInstallmentLevelSettingForLoanProductWithoutDelinquencyBucketValidation() {

        runAt("31 May 2023", () -> {
            // Create Client
            Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();

            // Create Loan Product without delinquency bucket
            PostLoanProductsRequest loanProductsRequest = create1InstallmentAmountInMultiplesOf4Period1MonthLongWithInterestAndAmortizationProduct(
                    InterestType.FLAT, AmortizationType.EQUAL_INSTALLMENTS);

            PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(loanProductsRequest);

            // Update loan product with installment level delinquency setting
            CallFailedRuntimeException callFailedRuntimeException = Assertions.assertThrows(CallFailedRuntimeException.class,
                    () -> loanProductHelper.updateLoanProductById(loanProductResponse.getResourceId(),
                            new PutLoanProductsProductIdRequest().enableInstallmentLevelDelinquency(true).locale("en")));

            Assertions.assertTrue(callFailedRuntimeException.getMessage()
                    .contains("Installment level delinquency cannot be enabled if Delinquency bucket is not configured for loan product"));

        });

    }

    private void updateBusinessDateAndExecuteCOBJob(String date) {
        businessDateHelper.updateBusinessDate(
                new BusinessDateRequest().type(BUSINESS_DATE.getName()).date(date).dateFormat(DATETIME_PATTERN).locale("en"));
        schedulerJobHelper.executeAndAwaitJob("Loan COB");
    }

    @AllArgsConstructor
    public static class DelinquencyData {

        Integer minAgeDays;
        Integer maxAgeDays;
        BigDecimal delinquentAmount;
    }

    private static DelinquencyData delinquency(Integer minAgeDays, Integer maxAgeDays, String delinquentAmount) {
        return new DelinquencyData(minAgeDays, maxAgeDays, new BigDecimal(delinquentAmount));
    }

    private void verifyDelinquency(Long loanId, Integer loanLevelDelinquentDays, String loanLevelDelinquentAmount,
            DelinquencyData... expectedInstallmentLevelDelinquencyData) {
        GetLoansLoanIdResponse loan = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId.intValue());
        assertThat(loan.getDelinquent()).isNotNull();
        List<GetLoansLoanIdLoanInstallmentLevelDelinquency> installmentLevelDelinquency = loan.getDelinquent()
                .getInstallmentLevelDelinquency();

        assertThat(loan.getDelinquent().getDelinquentDays()).isEqualTo(loanLevelDelinquentDays);
        assertThat(loan.getDelinquent().getDelinquentAmount()).isEqualByComparingTo(Double.valueOf(loanLevelDelinquentAmount));

        if (expectedInstallmentLevelDelinquencyData != null && expectedInstallmentLevelDelinquencyData.length > 0) {
            assertThat(installmentLevelDelinquency).isNotNull();
            assertThat(installmentLevelDelinquency).hasSize(expectedInstallmentLevelDelinquencyData.length);
            for (int i = 0; i < expectedInstallmentLevelDelinquencyData.length; i++) {
                assertThat(installmentLevelDelinquency.get(i).getMaximumAgeDays())
                        .isEqualTo(expectedInstallmentLevelDelinquencyData[i].maxAgeDays);
                assertThat(installmentLevelDelinquency.get(i).getMinimumAgeDays())
                        .isEqualTo(expectedInstallmentLevelDelinquencyData[i].minAgeDays);
                assertThat(installmentLevelDelinquency.get(i).getDelinquentAmount())
                        .isEqualByComparingTo(expectedInstallmentLevelDelinquencyData[i].delinquentAmount);
            }
        } else {
            assertThat(installmentLevelDelinquency).isNull();
        }
    }

}
