/*
 * Arrebol Consultancy copyright.
 * 
 * This code belongs to Arrebol Consultancy
 * its use, redistribution or modification are prohibited 
 * without written authorization from Arrebol Consultancy.
 */
package com.arrebol.apc.controller.admin;

import com.arrebol.apc.model.ModelParameter;
import com.arrebol.apc.model.catalog.People;
import com.arrebol.apc.model.catalog.RouteCtlg;
import com.arrebol.apc.model.core.User;
import com.arrebol.apc.model.core.constance.LoanByRenovationCfg;
import com.arrebol.apc.model.core.constance.LoanByUserCfg;
import com.arrebol.apc.model.core.constance.LoanCfg;
import com.arrebol.apc.model.core.constance.LoanDetailsCfg;
import com.arrebol.apc.model.enums.ActiveStatus;
import com.arrebol.apc.model.enums.LoanRenovationStatus;
import com.arrebol.apc.model.enums.LoanStatus;
import com.arrebol.apc.model.loan.Loan;
import com.arrebol.apc.model.loan.LoanByRenovation;
import com.arrebol.apc.model.loan.LoanByUser;
import com.arrebol.apc.model.loan.LoanDetails;
import com.arrebol.apc.model.loan.LoanFeeNotification;
import com.arrebol.apc.model.views.HistoryLoanView;
import com.arrebol.apc.repository.GenericEntityRepository;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 *
 * @author Oscar Armando Vargas Cardenas <oscar.vargas@arrebol.com.mx>
 */
public class LoanController implements Serializable {

    /**
     *
     * Searching all loan by status pending.
     *
     * @param officeId
     * @return
     */
    public List<Loan> fillLoanByStatusPendingDatatable(String officeId) {
        logger.debug("fillLoanByStatusPendingDatatable");
        List<ModelParameter> parameters = new ArrayList<>();

        //parameters.add(new ModelParameter(LoanCfg.FIELD_CUSTOMER_OFFICE, new Office(officeId)));
        return genericEntityRepository.xmlQueryAPCEntities(Loan.class, LoanCfg.QUERY_FIND_LOAN_BY_STATUS_PENDING, parameters);
    }

    /**
     *
     * Searching all loan
     *
     * @return
     */
    public List<Loan> fillAllLoansDatatable() {
        logger.debug("fillAllLoansDatatable");
        List<ModelParameter> parameters = new ArrayList<>();
        return genericEntityRepository.xmlQueryAPCEntities(Loan.class, LoanCfg.QUERY_FIND_ALL_LOANS, parameters);
    }

    /**
     *
     * Searching all loan
     *
     * @return
     */
    public List<HistoryLoanView> fillAllLoansViewDatatable() {
        logger.debug("fillAllLoansViewDatatable");
        List<ModelParameter> parameters = new ArrayList<>();
        return genericEntityRepository.xmlQueryAPCEntities(HistoryLoanView.class, LoanCfg.QUERY_FIND_ALL_LOANS_VIEW, parameters);
    }

    /**
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public List<HistoryLoanView> fillAllLoansViewDatatable(Date startDate, Date endDate) {
        logger.debug("fillAllLoansViewDatatable from start and end date");
        try {
            List<ModelParameter> parameters = new ArrayList<>();

            parameters.add(new ModelParameter(LoanCfg.PARAM_START_DATE, startDate));
            parameters.add(new ModelParameter(LoanCfg.PARAM_END_DATE, endDate));

            return genericEntityRepository.xmlQueryAPCEntities(HistoryLoanView.class, LoanCfg.QUERY_FIND_ALL_LOANS_VIEW_BY_START_AND_END_DATE, parameters);
        } catch (Exception e) {
            logger.info("fillAllLoansViewDatatable from start and end date", e);
            return new ArrayList<>();
        }
    }

    /**
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public List<HistoryLoanView> fillAllLoansJuridicalViewDatatable(Date startDate, Date endDate) {
        logger.debug("fillAllLoansJuridicalViewDatatable from start and end date");
        try {
            List<ModelParameter> parameters = new ArrayList<>();

            parameters.add(new ModelParameter(LoanCfg.PARAM_START_DATE, startDate));
            parameters.add(new ModelParameter(LoanCfg.PARAM_END_DATE, endDate));

            return genericEntityRepository.xmlQueryAPCEntities(HistoryLoanView.class, LoanCfg.QUERY_FIND_ALL_LOANS_JURIDICAL_VIEW_BY_START_AND_END_DATE, parameters);
        } catch (Exception e) {
            logger.info("fillAllLoansJuridicalViewDatatable from start and end date", e);
            return new ArrayList<>();
        }
    }

    /**
     *
     * Searching loan by id.
     *
     * @param loanId
     * @return
     */
    public Loan getLoanById(String loanId) {
        logger.debug("getLoanById");

        return (Loan) genericEntityRepository.selectAPCEntityById(Loan.class, loanId);
    }

    /**
     *
     * @param status
     * @param loanIdToUpdate
     * @param lastUpdatedBy
     * @return
     */
    public boolean updateLoanByStatus(LoanStatus status, String loanIdToUpdate, String lastUpdatedBy) {
        logger.debug("updateLoanByStatus");

        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanCfg.FIELD_LOAN_STATUS, status));
        parameters.add(new ModelParameter(LoanCfg.FIELD_AMOUNT_PAID, new BigDecimal(0)));
        parameters.add(new ModelParameter(LoanCfg.FIELD_LAST_REFERENCE_NUMBER, 0));
        parameters.add(new ModelParameter(LoanCfg.FIELD_LAST_UPDATED_BY, lastUpdatedBy));
        parameters.add(new ModelParameter(LoanCfg.FIELD_LAST_UPDATED_ON, new Date()));
        parameters.add(new ModelParameter(LoanCfg.FIELD_ID, loanIdToUpdate));

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(LoanCfg.QUERY_UPDATE_LOAN_FROM_RENOVATION, parameters);
    }

    /**
     *
     * @param status
     * @param loanIdToUpdate
     * @param lastUpdatedBy
     * @return
     */
    public boolean updateLoanByStatusWeb(LoanStatus status, String loanIdToUpdate, String lastUpdatedBy) {
        logger.debug("updateLoanByStatusWeb");

        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanCfg.FIELD_LOAN_STATUS, status));
        parameters.add(new ModelParameter(LoanCfg.FIELD_LAST_UPDATED_BY, lastUpdatedBy));
        parameters.add(new ModelParameter(LoanCfg.FIELD_LAST_UPDATED_ON, new Date()));
        parameters.add(new ModelParameter(LoanCfg.FIELD_ID, loanIdToUpdate));

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(LoanCfg.QUERY_UPDATE_LOAN_FROM_WEB, parameters);
    }

    /**
     *
     * Searching all loan details by id.
     *
     * @param loanId
     * @return
     */
    public List<LoanDetails> getLoanDetailsbyId(String loanId) {
        logger.debug("getLoanDetailsbyId");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanCfg.FIELD_DETAILS_LOAN, new Loan(loanId)));

        return genericEntityRepository.xmlQueryAPCEntities(LoanDetails.class, LoanCfg.QUERY_FIND_LOAN_DETAILS_BY_ID, parameters);
    }

    public LoanDetails getLoanDetailbyId(String loanDetailsId) {
        logger.debug("getLoanDetailbyId");

        return (LoanDetails) genericEntityRepository.selectAPCEntityById(LoanDetails.class, loanDetailsId);
    }

    public boolean updateAuthorizeLoanDetailById(String loanDetailId) {
        logger.debug("updateAuthorizeLoanDetailById");

        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanDetailsCfg.FIELD_ID, loanDetailId));

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(LoanDetailsCfg.UPDATE_AUTHORIZE_LOAN_DETAIL, parameters);
    }

    public Long countLoanDetailsAuthorize(String user) {
        logger.debug("countLoanDetailsAutorize");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanDetailsCfg.FIELD_USER, user));
        return (Long) genericEntityRepository.xmlQueryAPCEntityUniqueResult(Long.class, LoanDetailsCfg.COUNT_LOAN_DETAILS_AUTHORIZE, parameters);

    }

    public boolean updateRejectLoanDetailById(String loanDetailId) {
        logger.debug("updateAuthorizeLoanDetailById");

        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanDetailsCfg.FIELD_ID, loanDetailId));

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(LoanDetailsCfg.UPDATE_REJECT_LOAN_DETAIL, parameters);
    }

    public List<LoanDetails> fillAllTransfersLoanDetails() {
        logger.debug("findAllTransfersLoanDetail");

        return genericEntityRepository.xmlQueryAPCEntities(LoanDetails.class, LoanDetailsCfg.QUERY_FIND_ALL_TRANSFERS_LOAN_DETAIL);
    }

    /**
     *
     * Searching all loan details by id.
     *
     * @param loanId
     * @return
     */
    public List<LoanDetails> getLoanDetailsCurdatebyIdLoan(String loanId) {
        logger.debug("getLoanDetailsCurdatebyIdLoan");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanCfg.FIELD_DETAILS_LOAN, new Loan(loanId)));

        return genericEntityRepository.xmlQueryAPCEntities(LoanDetails.class, LoanCfg.QUERY_FIND_LOAN_DETAILS_CURDATE_BY_LOAN, parameters);
    }

    /**
     *
     * @param loan
     * @return boolean
     */
    public boolean saveLoan(Loan loan) {
        logger.debug("saveLoan");
        boolean success = genericEntityRepository.insertAPCEntity(loan);

        return success;
    }

    /**
     *
     * @param loan
     * @return boolean
     */
    public boolean updateLoan(Loan loan) {
        logger.debug("updateLoan");
        boolean success = genericEntityRepository.updateAPCEntity(loan);

        return success;
    }

    /**
     *
     * @param loan
     * @return boolean
     */
    public boolean updateLoanByUser(LoanByUser loan) {
        logger.debug("updateLoanByUser");
        boolean success = genericEntityRepository.updateAPCEntity(loan);

        return success;
    }

    /**
     *
     * @param loan
     * @return boolean
     */
    public boolean saveLoanNotificationFee(LoanFeeNotification notification) {
        logger.debug("saveLoanNotificationFee");
        boolean success = genericEntityRepository.insertAPCEntity(notification);

        return success;
    }

    /**
     *
     * @param loan detail
     * @return boolean
     */
    public boolean saveLoanDetail(LoanDetails loan) {
        logger.debug("saveLoanDetail");
        boolean success = genericEntityRepository.insertAPCEntity(loan);

        return success;
    }

    /**
     *
     * @param loanByUser
     * @return boolean
     */
    public boolean saveLoanByUser(LoanByUser loanByUser) {
        logger.debug("saveLoanByUser");
        boolean success = genericEntityRepository.insertAPCEntity(loanByUser);

        return success;
    }

    /**
     *
     * @param status
     * @param loanIdToUpdate
     * @return
     */
    public boolean updateLoanByUserByStatus(LoanStatus status, Loan loanIdToUpdate) {
        logger.debug("updateLoanByUserByStatus");

        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanByUserCfg.FIELD_LOAN_BY_USER_STATUS, status));
        parameters.add(new ModelParameter(LoanByUserCfg.FIELD_LOAN, loanIdToUpdate));

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(LoanByUserCfg.QUERY_UPDATE_LOAN_BY_USER_BY_LOAND_ID, parameters);
    }

    /**
     *
     * Searching the loan by renovation by id
     *
     * @param loanId
     * @return
     */
    public LoanByRenovation getLoanByRenovationByIdLoanNew(Loan loan) {
        logger.debug("getLoanByRenovationByIdLoanNew");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanByRenovationCfg.FIELD_LOAN_NEW, loan));

        return (LoanByRenovation) genericEntityRepository.xmlQueryAPCEntityUniqueResult(LoanByRenovation.class, LoanByRenovationCfg.QUERY_FIND_LOAN_RENOVATION_BY_NEW_LOAN_ID, parameters);
    }

    /**
     *
     * @param status
     * @param loanIdToUpdate
     * @param lastUpdatedBy
     * @return
     */
    public boolean updateLoanByRenovationByStatus(LoanRenovationStatus status, Loan loanIdToUpdate, String lastUpdatedBy) {
        logger.debug("updateLoanByRenovationByStatus");

        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanByRenovationCfg.FIELD_LOAN_RENOVATION_STATUS, status));
        parameters.add(new ModelParameter(LoanByRenovationCfg.FIELD_LOAN_NEW, loanIdToUpdate));
        parameters.add(new ModelParameter(LoanByRenovationCfg.FIELD_COMMENTS, "Se rechazó la renovación"));
        parameters.add(new ModelParameter(LoanByRenovationCfg.FIELD_LAST_UPDATED_BY, new User(lastUpdatedBy)));
        parameters.add(new ModelParameter(LoanByRenovationCfg.FIELD_LAST_UPDATED_ON, new Date()));

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(LoanByRenovationCfg.QUERY_UPDATE_LOAN_RENOVATION_WEB, parameters);
    }

    /**
     *
     * @param userId
     * @param loanIdToUpdate
     * @return
     */
    public boolean updateLoandByUserByUserId(String userId, Loan loanIdToUpdate) {
        logger.debug("updateLoandByUserByUserId");

        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanByUserCfg.FIELD_USER, new User(userId)));
        parameters.add(new ModelParameter(LoanByUserCfg.FIELD_LOAN, loanIdToUpdate));

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(LoanByUserCfg.QUERY_UPDATE_LOAN_BY_USER_BU_USER_ID, parameters);
    }

    /**
     *
     * Searching the loan by user by id
     *
     * @param loan
     * @return
     */
    public LoanByUser getLoanByUserByIdLoan(Loan loan) {
        logger.debug("getLoanByUserByIdLoan");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanByUserCfg.FIELD_LOAN, loan));

        return (LoanByUser) genericEntityRepository.xmlQueryAPCEntityUniqueResult(LoanByUser.class, LoanByUserCfg.QUERY_FIND_LOAN_BY_USER_BY_LOAND_ID, parameters);
    }

    /**
     *
     * @param loanByUser
     * @return boolean
     */
    public boolean deleteLoanByUser(LoanByUser loanByUser) {
        logger.debug("deleteLoanByUser");
        boolean success = genericEntityRepository.deleteAPCEntityById(loanByUser);

        return success;
    }

    /**
     *
     * @param loanByUser
     * @return boolean
     */
    public boolean deleteLoanDetails(LoanDetails loanDetail) {
        logger.debug("deleteLoanDetails");
        boolean success = genericEntityRepository.deleteAPCEntityById(loanDetail);

        return success;
    }

    /**
     *
     * @param userId
     * @param loanIdToUpdate
     * @return
     */
    public boolean deleteLoanDetailsByLoanCurdate(Loan loanIdToUpdate) {
        logger.debug("updateLoandByUserByUserId");

        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanCfg.FIELD_DETAILS_LOAN, loanIdToUpdate));

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(LoanCfg.QUERY_DELETE_LOAN_DETAILS_CURDATE_BY_LOAN, parameters);
    }

    /**
     *
     * @param route
     * @param routeIdToUpdate
     * @param lastUpdatedBy
     * @return
     */
    public boolean updateRouteById(RouteCtlg route, String routeIdToUpdate, String lastUpdatedBy) {
        logger.debug("updateRouteById");

        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanCfg.FIELD_ROUTE, route));
        parameters.add(new ModelParameter(LoanCfg.FIELD_LAST_UPDATED_BY, lastUpdatedBy));
        // parameters.add(new ModelParameter(LoanCfg.FIELD_LAST_UPDATED_ON, new Date()));
        parameters.add(new ModelParameter(LoanCfg.FIELD_ID, routeIdToUpdate));

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(LoanCfg.QUERY_UPDATE_ROUTE_BY_ID, parameters);
    }

    public boolean updatePeopleRoute(RouteCtlg route, People people) {
        people.setRouteCtlg(route);
        return genericEntityRepository.updateAPCEntity(people);
    }

    /**
     *
     * Searching all loan details by id.
     *
     * @param loanId
     * @return
     */
    public List<LoanDetails> getLoanDetailsFeeCurdatebyIdLoan(String loanId) {
        logger.debug("getLoanDetailsFeeCurdatebyIdLoan");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanCfg.FIELD_DETAILS_LOAN, new Loan(loanId)));

        return genericEntityRepository.xmlQueryAPCEntities(LoanDetails.class, LoanCfg.QUERY_FIND_LOAN_DETAILS_FEE_CURDATE_BY_LOAN, parameters);
    }

    /**
     *
     * @param userId
     * @param loanIdToUpdate
     * @return
     */
    public boolean deleteLoanDetailsFeeByLoanCurdate(Loan loanIdToUpdate) {
        logger.debug("deleteLoanDetailsFeeByLoanCurdate");

        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanCfg.FIELD_DETAILS_LOAN, loanIdToUpdate));

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(LoanCfg.QUERY_DELETE_LOAN_DETAILS_FEE_CURDATE_BY_LOAN, parameters);
    }

    /**
     *
     * @param userId
     * @param loanIdToUpdate
     * @return
     */
    public boolean deleteLoanFeeNotificationByLoanCurdate(Loan loanIdToUpdate) {
        logger.debug("deleteLoanFeeNotificationByLoanCurdate");

        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanCfg.FIELD_DETAILS_LOAN, loanIdToUpdate));

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(LoanCfg.QUERY_DELETE_LOAN_FEE_NOTIFICATION_CURDATE_BY_LOAN, parameters);
    }

    /**
     * Borra los registros de LoanFeeNotifications del préstamo que recibe
     *
     * @param loanIdToUpdate
     * @return
     */
    public boolean deleteLoanFeeNotificationByLoan(Loan loanIdToUpdate) {
        logger.debug("deleteLoanFeeNotification");

        List<ModelParameter> parameters = new ArrayList<>();
        parameters.add(new ModelParameter(LoanCfg.FIELD_DETAILS_LOAN, loanIdToUpdate));

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(LoanCfg.QUERY_DELETE_LOAN_FEE_NOTIFICATION_BY_LOAN, parameters);
    }

    /**
     *
     * @param status
     * @param loanIdToUpdate
     * @param lastUpdatedBy
     * @return
     */
    public boolean updateBonusNewCustomer(ActiveStatus status, String loanIdToUpdate, String lastUpdatedBy) {
        logger.debug("updateBonusNewCustomer");

        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanCfg.FIELD_NEW_CUSTOMER, status));
        parameters.add(new ModelParameter(LoanCfg.FIELD_LAST_UPDATED_BY, lastUpdatedBy));
        parameters.add(new ModelParameter(LoanCfg.FIELD_ID, loanIdToUpdate));

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(LoanCfg.QUERY_UPDATE_LOAN_BONUS_NEW_CUSTOMER, parameters);
    }

    final Logger logger = LogManager.getLogger(LoanController.class);
    private final GenericEntityRepository genericEntityRepository;

    public LoanController() {
        this.genericEntityRepository = new GenericEntityRepository();
    }
}
