/**
 * 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.infrastructure.jobs.filter;

import static org.apache.fineract.batch.command.CommandStrategyUtils.isRelativeUrlVersioned;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.batch.domain.BatchRequest;
import org.apache.fineract.cob.conditions.LoanCOBEnabledCondition;
import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate;
import org.apache.fineract.cob.loan.RetrieveLoanIdService;
import org.apache.fineract.cob.service.InlineLoanCOBExecutorServiceImpl;
import org.apache.fineract.cob.service.LoanAccountLockService;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.jobs.exception.LoanIdsHardLockedException;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.loanaccount.domain.GLIMAccountInfoRepository;
import org.apache.fineract.portfolio.loanaccount.domain.GroupLoanIndividualMonitoringAccount;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequestRepository;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Conditional;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;

@RequiredArgsConstructor
@Component
@Conditional(LoanCOBEnabledCondition.class)
public class LoanCOBFilterHelper implements InitializingBean {

    private final GLIMAccountInfoRepository glimAccountInfoRepository;
    private final LoanAccountLockService loanAccountLockService;
    private final PlatformSecurityContext context;
    private final InlineLoanCOBExecutorServiceImpl inlineLoanCOBExecutorService;
    private final LoanRepository loanRepository;
    private final FineractProperties fineractProperties;
    private final RetrieveLoanIdService retrieveLoanIdService;

    private final LoanRescheduleRequestRepository loanRescheduleRequestRepository;
    private final ObjectMapper objectMapper = new ObjectMapper();

    private static final List<HttpMethod> HTTP_METHODS = List.of(HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE);

    public static final Pattern IGNORE_LOAN_PATH_PATTERN = Pattern.compile("/v[1-9][0-9]*/loans/catch-up");
    public static final Pattern LOAN_PATH_PATTERN = Pattern.compile("/v[1-9][0-9]*/(?:reschedule)?loans/(?:external-id/)?([^/?]+).*");

    public static final Pattern LOAN_GLIMACCOUNT_PATH_PATTERN = Pattern.compile("/v[1-9][0-9]*/loans/glimAccount/(\\d+).*");
    private static final Predicate<String> URL_FUNCTION = s -> LOAN_PATH_PATTERN.matcher(s).find()
            || LOAN_GLIMACCOUNT_PATH_PATTERN.matcher(s).find();

    private static final String JOB_NAME = "INLINE_LOAN_COB";

    private Long getLoanId(boolean isGlim, String pathInfo) {
        if (!isGlim) {
            String id = LOAN_PATH_PATTERN.matcher(pathInfo).replaceAll("$1");
            if (isExternal(pathInfo)) {
                String externalId = id;
                return loanRepository.findIdByExternalId(new ExternalId(externalId));
            } else if (isRescheduleLoans(pathInfo)) {
                return loanRescheduleRequestRepository.getLoanIdByRescheduleRequestId(Long.valueOf(id)).orElse(null);
            } else if (StringUtils.isNumeric(id)) {
                return Long.valueOf(id);
            } else {
                return null;
            }
        } else {
            return Long.valueOf(LOAN_GLIMACCOUNT_PATH_PATTERN.matcher(pathInfo).replaceAll("$1"));
        }
    }

    private boolean isExternal(String pathInfo) {
        return LOAN_PATH_PATTERN.matcher(pathInfo).matches() && pathInfo.contains("external-id");
    }

    private boolean isRescheduleLoans(String pathInfo) {
        return LOAN_PATH_PATTERN.matcher(pathInfo).matches() && pathInfo.contains("/v1/rescheduleloans/");
    }

    public boolean isOnApiList(HttpServletRequest request) throws IOException {
        String pathInfo = request.getPathInfo();
        String method = request.getMethod();
        if (StringUtils.isBlank(pathInfo)) {
            return false;
        }
        if (isBatchApi(pathInfo)) {
            return isBatchApiMatching(request);
        } else {
            return isApiMatching(method, pathInfo);
        }
    }

    private boolean isBatchApiMatching(HttpServletRequest request) throws IOException {
        for (BatchRequest batchRequest : getBatchRequests(request)) {
            String method = batchRequest.getMethod();
            String pathInfo = batchRequest.getRelativeUrl();
            if (isApiMatching(method, pathInfo)) {
                return true;
            }
        }
        return false;
    }

    private List<BatchRequest> getBatchRequests(HttpServletRequest request) throws IOException {
        List<BatchRequest> batchRequests = objectMapper.readValue(request.getInputStream(), new TypeReference<>() {});
        for (BatchRequest batchRequest : batchRequests) {
            String pathInfo = "/" + batchRequest.getRelativeUrl();
            if (!isRelativeUrlVersioned(batchRequest.getRelativeUrl())) {
                pathInfo = "/v1/" + batchRequest.getRelativeUrl();
            }
            batchRequest.setRelativeUrl(pathInfo);
        }
        return batchRequests;
    }

    private boolean isApiMatching(String method, String pathInfo) {
        return HTTP_METHODS.contains(HttpMethod.valueOf(method)) && !IGNORE_LOAN_PATH_PATTERN.matcher(pathInfo).find()
                && URL_FUNCTION.test(pathInfo);
    }

    private boolean isBatchApi(String pathInfo) {
        return pathInfo.startsWith("/v1/batches");
    }

    private boolean isGlim(String pathInfo) {
        return LOAN_GLIMACCOUNT_PATH_PATTERN.matcher(pathInfo).matches();
    }

    public boolean isBypassUser() {
        return context.authenticatedUser().isBypassUser();
    }

    private List<Long> getGlimChildLoanIds(Long loanIdFromRequest) {
        GroupLoanIndividualMonitoringAccount glimAccount = glimAccountInfoRepository.findOneByIsAcceptingChildAndApplicationId(true,
                BigDecimal.valueOf(loanIdFromRequest));
        if (glimAccount != null) {
            return glimAccount.getChildLoan().stream().map(Loan::getId).toList();
        } else {
            return Collections.emptyList();
        }
    }

    private boolean isLoanHardLocked(Long... loanIds) {
        return isLoanHardLocked(Arrays.asList(loanIds));
    }

    private boolean isLoanHardLocked(List<Long> loanIds) {
        return loanIds.stream().anyMatch(loanAccountLockService::isLoanHardLocked);
    }

    public boolean isLoanBehind(List<Long> loanIds) {
        List<LoanIdAndLastClosedBusinessDate> loanIdAndLastClosedBusinessDates = new ArrayList<>();
        List<List<Long>> partitions = Lists.partition(loanIds, fineractProperties.getQuery().getInClauseParameterSizeLimit());
        partitions.forEach(partition -> loanIdAndLastClosedBusinessDates.addAll(retrieveLoanIdService
                .retrieveLoanIdsBehindDate(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE), partition)));
        return CollectionUtils.isNotEmpty(loanIdAndLastClosedBusinessDates);
    }

    public List<Long> calculateRelevantLoanIds(HttpServletRequest request) throws IOException {
        String pathInfo = request.getPathInfo();
        if (isBatchApi(pathInfo)) {
            return getLoanIdsFromBatchApi(request);
        } else {
            return getLoanIdsFromApi(pathInfo);
        }
    }

    private List<Long> getLoanIdsFromBatchApi(HttpServletRequest request) throws IOException {
        List<Long> loanIds = new ArrayList<>();
        for (BatchRequest batchRequest : getBatchRequests(request)) {
            // check the URL for Loan related ID
            String relativeUrl = batchRequest.getRelativeUrl();
            if (!relativeUrl.contains("$.resourceId")) {
                // if resourceId reference is used, we simply don't know the resourceId without executing the requests
                // first, so skipping it
                loanIds.addAll(getLoanIdsFromApi(relativeUrl));
            }

            // check the body for Loan ID
            Long loanId = getTopLevelLoanIdFromBatchRequest(batchRequest);
            if (loanId != null) {
                if (isLoanHardLocked(loanId)) {
                    throw new LoanIdsHardLockedException(loanId);
                } else {
                    loanIds.add(loanId);
                }
            }
        }
        return loanIds;
    }

    private Long getTopLevelLoanIdFromBatchRequest(BatchRequest batchRequest) throws JsonProcessingException {
        String body = batchRequest.getBody();
        if (StringUtils.isNotBlank(body)) {
            JsonNode jsonNode = objectMapper.readTree(body);
            if (jsonNode.has("loanId")) {
                return jsonNode.get("loanId").asLong();
            }
        }
        return null;
    }

    private List<Long> getLoanIdsFromApi(String pathInfo) {
        List<Long> loanIds = getLoanIdList(pathInfo);
        if (isLoanHardLocked(loanIds)) {
            throw new LoanIdsHardLockedException(loanIds.get(0));
        } else {
            return loanIds;
        }
    }

    private List<Long> getLoanIdList(String pathInfo) {
        boolean isGlim = isGlim(pathInfo);
        Long loanIdFromRequest = getLoanId(isGlim, pathInfo);
        if (loanIdFromRequest == null) {
            return Collections.emptyList();
        }
        if (isGlim) {
            return getGlimChildLoanIds(loanIdFromRequest);
        } else {
            return Collections.singletonList(loanIdFromRequest);
        }
    }

    public void executeInlineCob(List<Long> loanIds) {
        inlineLoanCOBExecutorService.execute(loanIds, JOB_NAME);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        objectMapper.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true);
    }

}
