/**
 * 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.portfolio.loanaccount.service.reamortization;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;

import java.time.Clock;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.domain.ActionContext;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor;
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactionProcessor;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class LoanReAmortizationValidatorTest {

    private final LocalDate actualDate = LocalDate.now(Clock.systemUTC());

    private LoanReAmortizationValidator underTest = new LoanReAmortizationValidator();

    @BeforeEach
    public void setUp() {
        ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
        ThreadLocalContextUtil.setActionContext(ActionContext.DEFAULT);
        ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, actualDate)));
    }

    @AfterEach
    public void tearDown() {
        ThreadLocalContextUtil.reset();
    }

    @Test
    public void testValidateReAmortize_ShouldNotThrowException() {
        // given
        Loan loan = loan();
        JsonCommand command = jsonCommand();
        // when
        underTest.validateReAmortize(loan, command);
        // then no exception thrown
    }

    @Test
    public void testValidateReAmortize_ShouldThrowException_WhenExternalIdIsLongerThan100() {
        // given
        Loan loan = loan();
        JsonCommand command = jsonCommand(RandomStringUtils.randomAlphabetic(120));
        // when
        PlatformApiDataValidationException result = assertThrows(PlatformApiDataValidationException.class,
                () -> underTest.validateReAmortize(loan, command));
        // then
        assertThat(result).isNotNull();
    }

    @Test
    public void testValidateReAmortize_ShouldThrowException_WhenLoanIsAfterMaturity() {
        // given
        Loan loan = loan();
        given(loan.getMaturityDate()).willReturn(actualDate.minusDays(2));
        JsonCommand command = jsonCommand();
        // when
        GeneralPlatformDomainRuleException result = assertThrows(GeneralPlatformDomainRuleException.class,
                () -> underTest.validateReAmortize(loan, command));
        // then
        assertThat(result).isNotNull();
        assertThat(result.getGlobalisationMessageCode()).isEqualTo("error.msg.loan.reamortize.cannot.be.submitted.after.maturity");
    }

    @Test
    public void testValidateReAmortize_ShouldThrowException_WhenLoanIsOnCumulativeSchedule() {
        // given
        Loan loan = loan();
        given(loan.getLoanProductRelatedDetail().getLoanScheduleType()).willReturn(LoanScheduleType.CUMULATIVE);
        JsonCommand command = jsonCommand();
        // when
        GeneralPlatformDomainRuleException result = assertThrows(GeneralPlatformDomainRuleException.class,
                () -> underTest.validateReAmortize(loan, command));
        // then
        assertThat(result).isNotNull();
        assertThat(result.getGlobalisationMessageCode())
                .isEqualTo("error.msg.loan.reamortize.supported.only.for.progressive.loan.schedule.type");
    }

    @Test
    public void testValidateReAmortize_ShouldThrowException_WhenLoanIsNotOnAdvancedPaymentAllocation() {
        // given
        Loan loan = loan();
        given(loan.getTransactionProcessingStrategyCode())
                .willReturn(DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactionProcessor.STRATEGY_CODE);
        JsonCommand command = jsonCommand();
        // when
        GeneralPlatformDomainRuleException result = assertThrows(GeneralPlatformDomainRuleException.class,
                () -> underTest.validateReAmortize(loan, command));
        // then
        assertThat(result).isNotNull();
        assertThat(result.getGlobalisationMessageCode())
                .isEqualTo("error.msg.loan.reamortize.supported.only.for.progressive.loan.schedule.type");
    }

    @Test
    public void testValidateReAmortize_ShouldThrowException_WhenLoanIsInterestBearing() {
        // given
        Loan loan = loan();
        given(loan.isInterestBearing()).willReturn(true);
        JsonCommand command = jsonCommand();
        // when
        GeneralPlatformDomainRuleException result = assertThrows(GeneralPlatformDomainRuleException.class,
                () -> underTest.validateReAmortize(loan, command));
        // then
        assertThat(result).isNotNull();
        assertThat(result.getGlobalisationMessageCode()).isEqualTo("error.msg.loan.reamortize.supported.only.for.non.interest.loans");
    }

    @Test
    public void testValidateReAmortize_ShouldThrowException_WhenLoanIsNotActive() {
        // given
        Loan loan = loan();
        given(loan.getStatus()).willReturn(LoanStatus.APPROVED);
        JsonCommand command = jsonCommand();
        // when
        GeneralPlatformDomainRuleException result = assertThrows(GeneralPlatformDomainRuleException.class,
                () -> underTest.validateReAmortize(loan, command));
        // then
        assertThat(result).isNotNull();
        assertThat(result.getGlobalisationMessageCode()).isEqualTo("error.msg.loan.reamortize.supported.only.for.active.loans");
    }

    @Test
    public void testValidateReAmortize_ShouldThrowException_WhenLoanAlreadyHasReAmortizationForToday() {
        // given
        List<LoanTransaction> transactions = List.of(loanTransaction(LoanTransactionType.DISBURSEMENT, actualDate.minusDays(2)),
                loanTransaction(LoanTransactionType.REAMORTIZE, actualDate));
        Loan loan = loan();
        given(loan.getLoanTransactions()).willReturn(transactions);
        JsonCommand command = jsonCommand();
        // when
        GeneralPlatformDomainRuleException result = assertThrows(GeneralPlatformDomainRuleException.class,
                () -> underTest.validateReAmortize(loan, command));
        // then
        assertThat(result).isNotNull();
        assertThat(result.getGlobalisationMessageCode())
                .isEqualTo("error.msg.loan.reamortize.reamortize.transaction.already.present.for.today");
    }

    @Test
    public void testValidateUndoReAmortize_ShouldThrowException_WhenLoanDoesntHaveReAmortization() {
        // given
        List<LoanTransaction> transactions = List.of(loanTransaction(LoanTransactionType.DISBURSEMENT, actualDate.minusDays(3)));
        Loan loan = loan();
        given(loan.getLoanTransactions()).willReturn(transactions);
        JsonCommand command = jsonCommand();
        // when
        GeneralPlatformDomainRuleException result = assertThrows(GeneralPlatformDomainRuleException.class,
                () -> underTest.validateUndoReAmortize(loan, command));
        // then
        assertThat(result).isNotNull();
        assertThat(result.getGlobalisationMessageCode()).isEqualTo("error.msg.loan.reamortize.reamortization.transaction.missing");
    }

    @Test
    public void testValidateUndoReAmortize_ShouldThrowException_WhenLoanAlreadyHasRepaymentAfterReAmortization() {
        // given
        List<LoanTransaction> transactions = List.of(loanTransaction(LoanTransactionType.DISBURSEMENT, actualDate.minusDays(3)),
                loanTransaction(LoanTransactionType.REAMORTIZE, actualDate.minusDays(2)),
                loanTransaction(LoanTransactionType.REPAYMENT, actualDate.minusDays(1)));
        Loan loan = loan();
        given(loan.getLoanTransactions()).willReturn(transactions);
        JsonCommand command = jsonCommand();
        // when
        GeneralPlatformDomainRuleException result = assertThrows(GeneralPlatformDomainRuleException.class,
                () -> underTest.validateUndoReAmortize(loan, command));
        // then
        assertThat(result).isNotNull();
        assertThat(result.getGlobalisationMessageCode()).isEqualTo("error.msg.loan.reamortize.repayment.exists.after.reamortization");
    }

    @Test
    public void testValidateUndoReAmortize_ShouldThrowException_WhenLoanAlreadyHasRepaymentAfterReAmortization_SameDay() {
        // given
        List<LoanTransaction> transactions = List.of(loanTransaction(LoanTransactionType.DISBURSEMENT, actualDate.minusDays(2)),
                loanTransaction(LoanTransactionType.REAMORTIZE, actualDate.minusDays(1),
                        OffsetDateTime.of(actualDate, LocalTime.of(10, 0), ZoneOffset.UTC)),
                loanTransaction(LoanTransactionType.REPAYMENT, actualDate.minusDays(1),
                        OffsetDateTime.of(actualDate, LocalTime.of(11, 0), ZoneOffset.UTC)));
        Loan loan = loan();
        given(loan.getLoanTransactions()).willReturn(transactions);
        JsonCommand command = jsonCommand();
        // when
        GeneralPlatformDomainRuleException result = assertThrows(GeneralPlatformDomainRuleException.class,
                () -> underTest.validateUndoReAmortize(loan, command));
        // then
        assertThat(result).isNotNull();
        assertThat(result.getGlobalisationMessageCode()).isEqualTo("error.msg.loan.reamortize.repayment.exists.after.reamortization");
    }

    @Test
    public void testValidateUndoReAmortize_ShouldNotThrowException_WhenLoanAlreadyHasRepaymentAfterReAmortization_SameDay_RepaymentBeforeReAmortization() {
        // given
        List<LoanTransaction> transactions = List.of(loanTransaction(LoanTransactionType.DISBURSEMENT, actualDate.minusDays(2)),
                loanTransaction(LoanTransactionType.REAMORTIZE, actualDate.minusDays(1),
                        OffsetDateTime.of(actualDate, LocalTime.of(10, 0), ZoneOffset.UTC)),
                loanTransaction(LoanTransactionType.REPAYMENT, actualDate.minusDays(1),
                        OffsetDateTime.of(actualDate, LocalTime.of(9, 0), ZoneOffset.UTC)));
        Loan loan = loan();
        given(loan.getLoanTransactions()).willReturn(transactions);
        JsonCommand command = jsonCommand();
        // when
        underTest.validateUndoReAmortize(loan, command);
        // then no exception thrown
    }

    private JsonCommand jsonCommand() {
        return jsonCommand("123456");
    }

    private JsonCommand jsonCommand(String externalId) {
        String json = """
                {
                    "externalId": "%s"
                }
                """.formatted(externalId);
        FromJsonHelper fromJsonHelper = new FromJsonHelper();
        return new JsonCommand(1L, fromJsonHelper.parse(json), fromJsonHelper);
    }

    private LoanTransaction loanTransaction(LoanTransactionType type, LocalDate txDate, OffsetDateTime creationTime) {
        LoanTransaction loanTransaction = loanTransaction(type, txDate);
        given(loanTransaction.getCreatedDateTime()).willReturn(creationTime);
        return loanTransaction;
    }

    private LoanTransaction loanTransaction(LoanTransactionType type, LocalDate txDate) {
        LoanTransaction loanTransaction = mock(LoanTransaction.class);
        given(loanTransaction.getTypeOf()).willReturn(type);
        given(loanTransaction.getTransactionDate()).willReturn(txDate);
        given(loanTransaction.getSubmittedOnDate()).willReturn(txDate);
        return loanTransaction;
    }

    private Loan loan() {
        Loan loan = mock(Loan.class);
        given(loan.getStatus()).willReturn(LoanStatus.ACTIVE);
        given(loan.getMaturityDate()).willReturn(actualDate.plusDays(30));
        given(loan.getTransactionProcessingStrategyCode())
                .willReturn(AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY);
        LoanProductRelatedDetail loanProductRelatedDetail = mock(LoanProductRelatedDetail.class);
        given(loan.getLoanProductRelatedDetail()).willReturn(loanProductRelatedDetail);
        given(loanProductRelatedDetail.getLoanScheduleType()).willReturn(LoanScheduleType.PROGRESSIVE);
        given(loan.isInterestBearing()).willReturn(false);
        given(loan.getLoanTransactions()).willReturn(List.of());
        return loan;
    }

}
