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

import com.arrebol.apc.controller.util.HibernateUtil;
import com.arrebol.apc.model.ModelParameter;
import com.arrebol.apc.model.admin.constance.ClosingDayCfg;
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.core.constance.HumanResourceCfg;
import com.arrebol.apc.model.core.constance.UserCfg;
import com.arrebol.apc.model.enums.HumanResourceStatus;
import com.arrebol.apc.model.views.GeneralBoxView;
import com.arrebol.apc.model.views.constance.GeneralBoxViewCfg;
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;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.query.Query;

/**
 *
 * @author Carlos Janitzio Zavala Lopez <janitzio.zavala@arrebol.com.mx>
 */
public class GenericController implements Serializable{

    /**
     *
     * Searching all user actives by office.
     *
     * @param officeId
     * @return
     */
    public List<User> getAllUsersByOffice(String officeId) {
        logger.debug("getAllUsersByOffice");
        List<ModelParameter> parameters = new ArrayList<>();

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

        return genericEntityRepository.xmlQueryAPCEntities(User.class, UserCfg.QUERY_FIND_ALL_USERS_COMPLETE, parameters);
    }
    
    /**
     *
     * Searching all human resources actives by office.
     *
     * @param officeId
     * @return
     */
    public List<HumanResource> getAllHRByOffice(String officeId) {
        logger.debug("getAllHRByOffice");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(HumanResourceCfg.FIELD_OFFICE, new Office(officeId)));
        parameters.add(new ModelParameter(HumanResourceCfg.FIELD_HR_STATUS, HumanResourceStatus.ENEBLED));

        return genericEntityRepository.xmlQueryAPCEntities(HumanResource.class, HumanResourceCfg.QUERY_FIND_ALL_HR_BY_OFFICE, parameters);
    }
    
    /**
     *
     * Searching all details by general box by office.
     *
     * @param officeId
     * @return
     */
    public BigDecimal findAllGeneralBox(String officeId) {
        logger.debug("findAllGeneralBox");
        List<GeneralBoxView> generalBox = null;
        BigDecimal totalBox;
        totalBox = BigDecimal.ZERO;
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(GeneralBoxViewCfg.FIELD_OFFICE, officeId));

        generalBox = genericEntityRepository.xmlQueryAPCEntities(GeneralBoxView.class, GeneralBoxViewCfg.QUERY_FIND_ALL_DETAILS, parameters);
        
        if(generalBox != null && !generalBox.isEmpty())
        {
            for(GeneralBoxView total : generalBox)
            {
               if(total.getType().equalsIgnoreCase("Inicio")) 
                totalBox = totalBox.subtract(total.getAmount());
               if(total.getType().equalsIgnoreCase("Corte del día")) 
                totalBox = totalBox.add(total.getAmount());
               if(total.getType().equalsIgnoreCase("Entrada")) 
                totalBox = totalBox.add(total.getAmount());
               if(total.getType().equalsIgnoreCase("Salida")) 
                totalBox = totalBox.subtract(total.getAmount());
               if(total.getType().equalsIgnoreCase("Adelanto")) 
                totalBox = totalBox.subtract(total.getAmount());
               if(total.getType().equalsIgnoreCase("Nomina")) 
                totalBox = totalBox.subtract(total.getAmount());
               if(total.getType().equalsIgnoreCase("Préstamo Empleado")) 
                totalBox = totalBox.subtract(total.getAmount());
            }
        }
        
        return totalBox;
    }
    
    public BigDecimal findAllSmallBox(String officeId) {
        logger.debug("findAllSmallBox");
        BigDecimal totalBox;
        totalBox = BigDecimal.ZERO;
        List<ModelParameter> parameters = new ArrayList<>();

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

        totalBox = (BigDecimal)genericEntityRepository.xmlQueryAPCEntityUniqueResult(BigDecimal.class, 
                ClosingDayCfg.QUERY_SUM_CLOSING_DAY_BY_CURDATE_AND_OFFICE, parameters);
        
        return totalBox;
    }
    
    
    public BigDecimal findAllSmallBoxByLastSmallBox(String officeId, Date lastSmallBox) {
        logger.debug("findAllSmallBoxByLastSmalBox");
        BigDecimal totalBox;
        totalBox = BigDecimal.ZERO;
        
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            
            Query query = session.createQuery("SELECT SUM(amountPaid) FROM ClosingDay WHERE office.id = :idOffice AND createdOn > :lastBox AND activeStatus = 'ENEBLED'");
            query.setParameter("idOffice", officeId);
            query.setParameter("lastBox", lastSmallBox);
            query.setMaxResults(1);
            totalBox = (BigDecimal) query.uniqueResult();

            

            transaction.commit();

        } catch (HibernateException e) {
            logger.error("Driver", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error(e);
            rollback(transaction);
        }

        
        return totalBox;
    }
    
    public Date getMaxDateStableGeneralBoxByOffice(String officeid) {
        logger.debug("getMaxDateStableGeneralBoxByOffice");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(StableGeneralBoxCfg.FIELD_OFFICE, new Office(officeid)));

        return (Date) genericEntityRepository.xmlQueryAPCEntityUniqueResult(Date.class, StableGeneralBoxCfg.QUERY_MAX_STABLE_GENERAL_BOX_BY_OFFICE, parameters);
    }
    
    public Date getMaxDateClosingDayByOffice(String officeid) {
        logger.debug("getMaxDateClosingDayByOffice");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(StableGeneralBoxCfg.FIELD_OFFICE, new Office(officeid)));

        return (Date) genericEntityRepository.xmlQueryAPCEntityUniqueResult(Date.class, StableGeneralBoxCfg.QUERY_MAX_CLOSING_DAY_BY_OFFICE, parameters);
    }
    
    public boolean verifyStableGeneralBoxVsClosingDay(String officeid)
    {
        if(getMaxDateStableGeneralBoxByOffice(officeid) == null || getMaxDateClosingDayByOffice(officeid) == null)
        {
            return true;
        }
        if(getMaxDateStableGeneralBoxByOffice(officeid).compareTo(getMaxDateClosingDayByOffice(officeid)) == 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    
    public boolean existStableSmallBoxByCreatedOn(Date date) {
        logger.info("existStableSmallBoxByCreatedOn");

        String query = "SELECT ssb.id "
                    + "FROM APC_STABLE_SMALL_BOX ssb "
                    + "WHERE DATE(ssb.created_on) = DATE(:date) "
                    + "AND ssb.active_status = 'ENEBLED'";

        return genericEntityRepository.existRecordsUsingSQLQueryFindByCreatedOnField(date, query);
    }
    
    /**
     *
     * @param date
     * @return
     */
    public boolean existStableGeneralBoxByCreatedOn(Date date) {
        logger.info("existStableGeneralBoxByCreatedOn");

        String query = "SELECT sgb.id "
                + "FROM APC_STABLE_GENERAL_BOX sgb "
                + "WHERE DATE(sgb.created_on) = DATE(:date) "
                + "AND sgb.active_status = 'ENEBLED'";

        return genericEntityRepository.existRecordsUsingSQLQueryFindByCreatedOnField(date, query);
    }
    
    protected void rollback(Transaction transaction) {
        if (null != transaction) {
            transaction.rollback();
        }
    }

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

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