/*
 * 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.admin.EmployeeSaving;
import com.arrebol.apc.model.admin.Goal;
import com.arrebol.apc.model.admin.LoanEmployee;
import com.arrebol.apc.model.admin.LoanEmployeeDetails;
import com.arrebol.apc.model.admin.StableGeneralBox;
import com.arrebol.apc.model.admin.constance.StableGeneralBoxCfg;
import com.arrebol.apc.model.core.HumanResource;
import com.arrebol.apc.model.core.Office;
import com.arrebol.apc.model.core.User;
import com.arrebol.apc.model.enums.ActiveStatus;
import com.arrebol.apc.model.loan.Loan;
import com.arrebol.apc.model.payroll.Payroll;
import com.arrebol.apc.model.payroll.constance.PayRollCfg;
import com.arrebol.apc.model.views.LoanEmployeeView;
import com.arrebol.apc.model.views.constance.LoanEmployeeAllDataCfg;
import com.arrebol.apc.model.views.constance.LoanEmployeeViewCfg;
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 PayRollController implements Serializable {

    /**
     *
     * Searching all stable general box by office.
     *
     * @param officeId
     * @param startDate
     * @param endDate
     * @return
     */
    public List<Payroll> fillPayrollDatatable(String officeId, Date startDate, Date endDate) {
        logger.debug("fillPayrollDatatable");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(PayRollCfg.FIELD_OFFICE, new Office(officeId)));
        //parameters.add(new ModelParameter(PayRollCfg.FIELD_ACTIVE_STATUS, ActiveStatus.ENEBLED));
        parameters.add(new ModelParameter(PayRollCfg.PARAM_START_DATE, startDate));
        parameters.add(new ModelParameter(PayRollCfg.PARAM_END_DATE, endDate));

        return genericEntityRepository.xmlQueryAPCEntities(Payroll.class, PayRollCfg.QUERY_FIND_PAYROLL_BY_OFFICE_BETWEEN_DATES, parameters);
    }

    public boolean updatePayrollByStatus(ActiveStatus status, String payrollIdToUpdate, String lastUpdatedBy) {
        logger.debug("updatePayrollByStatus");

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

        parameters.add(new ModelParameter(PayRollCfg.FIELD_ACTIVE_STATUS, status));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_LAST_UPDATED_BY, lastUpdatedBy));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_LAST_UPDATED_ON, new Date()));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_ID, payrollIdToUpdate));

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(PayRollCfg.QUERY_UPDATE_PAYROLL_BY_STATUS, parameters);
    }

    public List<StableGeneralBox> getStableGeneralBoxByDate(String officeId, Date startDate, Date endDate) {
        logger.debug("fillStableGeneralBoxDatatable");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(StableGeneralBoxCfg.FIELD_OFFICE, new Office(officeId)));
        parameters.add(new ModelParameter(StableGeneralBoxCfg.PARAM_START_DATE, startDate));
        parameters.add(new ModelParameter(StableGeneralBoxCfg.PARAM_END_DATE, endDate));

        return genericEntityRepository.xmlQueryAPCEntities(StableGeneralBox.class, StableGeneralBoxCfg.QUERY_FIND_ALL_STABLE_GENERAL_BOX_BY_OFFICE_BETWEEN_DATES, parameters);
    }
    
    /**
     *
     * Searching user by id.
     *
     * @param userId
     * @return
     */
    public User getUserById(String userId) {
        logger.debug("getUserById");

        return (User) genericEntityRepository.selectAPCEntityById(User.class, userId);
    }

    /**
     *
     * Searching the advance sum by user
     *
     * @param humanResourceId
     * @param officeId
     * @param dateInit
     * @param dateEnd
     * @return
     */
    public BigDecimal getSumAdvanceByUser(String humanResourceId, String officeId, Date dateInit, Date dateEnd) {
        logger.debug("getSumAdvanceByUser");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(PayRollCfg.FIELD_ACTIVE_STATUS, ActiveStatus.ENEBLED));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_OFFICE, new Office(officeId)));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_HUMAN_RESOURCE, new HumanResource(humanResourceId)));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_DATE_INIT, dateInit));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_DATE_END, dateEnd));

        return (BigDecimal) genericEntityRepository.xmlQueryAPCEntityUniqueResult(BigDecimal.class, PayRollCfg.QUERY_SUM_ALL_ADVANCE_BY_USER, parameters);
    }

    /**
     *
     * Searching the count for new customer by loan by user
     *
     * @param userId
     * @param dateInit
     * @param dateEnd
     * @return
     */
    public List<Loan> getTotalNewCustomerLoansByUser(String userId, Date dateInit, Date dateEnd) {
        logger.debug("getTotalNewCustomerLoansByUser");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(PayRollCfg.FIELD_USER, userId));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_DATE_INIT, dateInit));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_DATE_END, dateEnd));

        return genericEntityRepository.xmlQueryAPCEntities(Loan.class, PayRollCfg.QUERY_COUNT_NEW_CUSTOMER_FOR_LOANS_BY_USER, parameters);
    }

    /**
     *
     * Searching the sum amount by loan by user
     *
     * @param userId
     * @param dateInit
     * @param dateEnd
     * @return
     */
    public BigDecimal getTotalLoansByUserForDates(String userId, Date dateInit, Date dateEnd) {
        logger.debug("getTotalLoansByUserForDates");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(PayRollCfg.FIELD_USER, userId));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_DATE_INIT, dateInit));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_DATE_END, dateEnd));

        return (BigDecimal) genericEntityRepository.xmlQueryAPCEntityUniqueResult(BigDecimal.class, PayRollCfg.QUERY_SUM_FOR_LOANS_BY_USER, parameters);
    }

    /**
     *
     * Searching the goal by dates
     *
     * @param officeId
     * @param dateInit
     * @param dateEnd
     * @return
     */
    public Goal getGoalByDates(String officeId, Date dateInit, Date dateEnd) {
        logger.debug("getGoalByDates");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(PayRollCfg.FIELD_OFFICE, new Office(officeId)));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_DATE_INIT, dateInit));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_DATE_END, dateEnd));

        return (Goal) genericEntityRepository.xmlQueryAPCEntityUniqueResult(Goal.class, PayRollCfg.QUERY_FIND_GOAL_BY_DATES, parameters);
    }

    public Goal getLastGoal(String officeId) {
        logger.debug("getLastGoal");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(PayRollCfg.FIELD_OFFICE, new Office(officeId)));

        return (Goal) genericEntityRepository.xmlQueryAPCEntityUniqueResult(Goal.class, PayRollCfg.QUERY_FIND_LAST_GOAL, parameters);
    }

    public List<LoanEmployeeView> getPaymentToDebtByUser(String userId) {

        logger.debug("fillLoanEmployeeDataTable");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanEmployeeViewCfg.FIEL_LOAN_EMPLOYEE_USERID, userId));
        List<LoanEmployeeView> dataComplete = genericEntityRepository.xmlQueryAPCEntities(LoanEmployeeView.class, LoanEmployeeViewCfg.QUERY_FIND_ALL_LOAN_EMPLOYEE_BY_ID, parameters);
        return dataComplete;
    }

    public LoanEmployee getLoanEmployeeById(String idLoanEmployee) {

        logger.debug("getLoanEmployeeById");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(LoanEmployeeAllDataCfg.FIELD_ID_LOAN, idLoanEmployee));
        List<LoanEmployee> dataComplete = genericEntityRepository.xmlQueryAPCEntities(LoanEmployee.class,
                LoanEmployeeAllDataCfg.QUERY_FIND_ALL_LOAN_EMPLOYEE_BY_ID, parameters);

        return dataComplete.get(0);
    }

    public boolean saveLoanEmployeeDetail(LoanEmployeeDetails loanDetail, HumanResource hr, LoanEmployee loanEmployee) {
        logger.debug("saveLoanEmployeeDetail");
        boolean success = genericEntityRepository.insertAPCEntity(loanDetail);

        if (hr != null) {
            genericEntityRepository.updateAPCEntity(hr);
        }

        if (loanEmployee != null) {
            genericEntityRepository.updateAPCEntity(loanEmployee);
        }

        return success;
    }
            
    public boolean saveEmployeeSaving(EmployeeSaving employeeSaving, HumanResource hr) {
        logger.debug("saveEmployeeSaving");
        boolean success = genericEntityRepository.insertAPCEntity(employeeSaving);

        if (hr != null) {
            genericEntityRepository.updateAPCEntity(hr);
        }

        return success;
    }

    /**
     *
     * Searching the sum of loan details for type Payment by user
     *
     * @param userId
     * @param dateInit
     * @param dateEnd
     * @return
     */
    public BigDecimal getLoanDetailsByUserForDates(String userId, Date dateInit, Date dateEnd) {
        logger.debug("getLoanDetailsByUserForDates");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(PayRollCfg.FIELD_USER, new User(userId)));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_DATE_INIT, dateInit));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_DATE_END, dateEnd));

        return (BigDecimal) genericEntityRepository.xmlQueryAPCEntityUniqueResult(BigDecimal.class, PayRollCfg.QUERY_SUM_LOAN_DETAILS_PAYMENT_BY_USER, parameters);
    }

    /**
     *
     * Searching the sum of loan details for type Payment by user
     *
     * @param userId
     * @param dateInit
     * @param dateEnd
     * @return
     */
    public BigDecimal getFeeByUserForDates(String userId, Date dateInit, Date dateEnd) {
        logger.debug("getFeeByUserForDates");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(PayRollCfg.FIELD_USER_ID, userId));

        return (BigDecimal) genericEntityRepository.xmlQueryAPCEntityUniqueResult(BigDecimal.class, PayRollCfg.QUERY_SUM_DIFERENCES_BY_USER, parameters);
    }

    /**
     *
     * Searching the sum of loan details for type Payment by user
     *
     * @param userId
     * @param dateInit
     * @param dateEnd
     * @return
     */
    public BigDecimal getDiscountByUserThisWeek(String userId) {
        logger.debug("getDiscountByUserThisWeek");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(PayRollCfg.FIELD_USER, new User(userId)));

        return (BigDecimal) genericEntityRepository.xmlQueryAPCEntityUniqueResult(BigDecimal.class, PayRollCfg.QUERY_SUM_DIFERENCES_BETWEEN_CLOSING_DAY_BY_USER, parameters);
    }

    /**
     *
     * Searching the sum of loan details for type Payment by user
     *
     * @param userId
     * @param dateInit
     * @param dateEnd
     * @return
     */
    public Long getTotalOpeningFeeByUser(String userId, Date dateInit, Date dateEnd) {
        logger.debug("getDiscountByUserThisWeek");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(PayRollCfg.FIELD_USER, new User(userId)));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_DATE_INIT, dateInit));
        parameters.add(new ModelParameter(PayRollCfg.FIELD_DATE_END, dateEnd));

        return (Long) genericEntityRepository.xmlQueryAPCEntityUniqueResult(Long.class, PayRollCfg.QUERY_SUM_OPENING_FEE_BY_USER, parameters);
    }

    public BigDecimal getTotalExpectedWeekByUser(String userId) {
        logger.debug("getTotalExpectedWeekByUser");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(PayRollCfg.FIELD_USER, new User(userId)));

        return (BigDecimal) genericEntityRepository.xmlQueryAPCEntityUniqueResult(BigDecimal.class, PayRollCfg.QUERY_SUM_TOTAL_EXPECTED_FOR_WEEK_BY_USER, parameters);
    }

    /**
     *
     * @param payroll
     * @return boolean
     */
    public boolean savePayroll(Payroll payroll) {
        logger.debug("savePayroll");
        boolean success = genericEntityRepository.insertAPCEntity(payroll);

        return success;
    }

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

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