/*
 * 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.controller.util.ConnectionManager;
import com.arrebol.apc.controller.util.HibernateUtil;
import com.arrebol.apc.model.ModelParameter;
import com.arrebol.apc.model.admin.OtherExpense;
import com.arrebol.apc.model.admin.StableSmallBox;
import com.arrebol.apc.model.admin.constance.OtherExpenseCfg;
import com.arrebol.apc.model.admin.constance.StableSmallBoxCfg;
import com.arrebol.apc.model.core.Office;
import com.arrebol.apc.model.enums.ActiveStatus;
import com.arrebol.apc.repository.GenericEntityRepository;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
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;

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

    /**
     *
     * Searching all stable general box by office.
     *
     * @param officeId
     * @param startDate
     * @param endDate
     * @return
     */
    public List<StableSmallBox> fillStableSmallBoxDatatable(String officeId, Date startDate, Date endDate) {
        logger.debug("fillStableSmallBoxDatatable");
        List<ModelParameter> parameters = new ArrayList<>();
        
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        calendar.add(Calendar.DAY_OF_YEAR, 1);
        startDate = calendar.getTime();

        Calendar calendarF = Calendar.getInstance();
        calendarF.setTime(endDate);
        calendarF.add(Calendar.DAY_OF_YEAR, 1);
        endDate = calendarF.getTime();
        
        parameters.add(new ModelParameter(StableSmallBoxCfg.FIELD_OFFICE, new Office(officeId)));
        //parameters.add(new ModelParameter(StableSmallBoxCfg.FIELD_ACTIVE_STATUS, ActiveStatus.ENEBLED));
        parameters.add(new ModelParameter(StableSmallBoxCfg.PARAM_START_DATE, startDate));
        parameters.add(new ModelParameter(StableSmallBoxCfg.PARAM_END_DATE, endDate));

        return genericEntityRepository.xmlQueryAPCEntities(StableSmallBox.class, StableSmallBoxCfg.QUERY_FIND_ALL_STABLE_SMALL_BOX_BY_OFFICE_BETWEEN_DATES, parameters);
    }

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

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

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

        return genericEntityRepository.xmlUpdateOrDeleteAPCEntity(StableSmallBoxCfg.QUERY_UPDATE_STABLE_SMALL_BOX_BY_STATUS, parameters);
    }

    /**
     *
     * @param stableSmallBox
     * @return boolean
     */
    public boolean saveStableSmallBox(StableSmallBox stableSmallBox) {
        logger.debug("saveStableSmallBox");
        boolean success = genericEntityRepository.insertAPCEntity(stableSmallBox);

        return success;
    }

    /**
     *
     * Searching the stable small box by date and office
     *
     * @param createdOn
     * @param officeid
     * @return
     */
    public Long getCountStableSmallBoxByOfficeAndDate(Date createdOn, String officeid) {
        logger.debug("getCountStableSmallBoxByOfficeAndDate");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(StableSmallBoxCfg.FIELD_CREATEDON, createdOn));
        parameters.add(new ModelParameter(StableSmallBoxCfg.FIELD_OFFICE, new Office(officeid)));

        return (Long) genericEntityRepository.xmlQueryAPCEntityUniqueResult(Long.class, StableSmallBoxCfg.QUERY_COUNT_STABLE_SMALL_BOX_BY_OFFICE_AND_DATE, parameters);
    }

    /**
     *
     * Searching the stable small box by date and office
     *
     * @param officeid
     * @return
     */
    public BigDecimal getPendingByClosingDay(String officeid) {
        logger.debug("getPendingByClosingDay");
        List<ModelParameter> parameters = new ArrayList<>();

        parameters.add(new ModelParameter(StableSmallBoxCfg.FIELD_OFFICE_VIEW, officeid));

        return (BigDecimal) genericEntityRepository.xmlQueryAPCEntityUniqueResult(BigDecimal.class, StableSmallBoxCfg.QUERY_SUM_PENDING_CLOSING_BY_OFFICE, parameters);
    }

    /**
     *
     * @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);
    }

    /**
     *
     * @param date
     * @return
     */
    public boolean existNextPaidStableSmallBoxByCreatedOn(Date date) {
        logger.info("existNextPaidStableSmallBoxByCreatedOn");

        String query = "SELECT ssb.id "
                + "FROM APC_STABLE_SMALL_BOX ssb "
                + "WHERE DATE(ssb.created_on) >= DATE_ADD(DATE(:date), INTERVAL 1 DAY) "
                + "AND ssb.active_status = 'ENEBLED'";

        return genericEntityRepository.existRecordsUsingSQLQueryFindByCreatedOnField(date, query);
    }

    public List<Object> getDataReport(Date fecha) {
        DateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        String dateFormat = formatter.format(fecha);

        String queryReportLocal = queryReport;
        queryReportLocal = queryReportLocal.replace(":dateReport", dateFormat);
        List<Object> rows = new ArrayList<>();
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            //rows = session.createNativeQuery(queryReport).setParameter("dateReport", dateFormat).getResultList();
            rows = session.createNativeQuery(queryReportLocal).getResultList();

            transaction.commit();

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

        return rows;
    }
    
    public List<OtherExpense> fillOtherExpenseDatatable(String officeId, Date startDate, Date endDate) {
        logger.debug("fillOtherExpenseDatatable");
        List<ModelParameter> parameters = new ArrayList<>();
        
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        calendar.add(Calendar.DAY_OF_YEAR, 1);
        startDate = calendar.getTime();

        Calendar calendarF = Calendar.getInstance();
        calendarF.setTime(endDate);
        calendarF.add(Calendar.DAY_OF_YEAR, 1);
        endDate = calendarF.getTime();
        
        parameters.add(new ModelParameter(OtherExpenseCfg.FIELD_OFFICE, new Office(officeId)));
        parameters.add(new ModelParameter(OtherExpenseCfg.PARAM_START_DATE, startDate));
        parameters.add(new ModelParameter(OtherExpenseCfg.PARAM_END_DATE, endDate));

        return genericEntityRepository.xmlQueryAPCEntities(OtherExpense.class, OtherExpenseCfg.QUERY_FIND_ALL_OTHER_EXPENSE_BY_OFFICE_BETWEEN_DATES, parameters);
    }
    
    final Logger logger = LogManager.getLogger(StableSmallBoxController.class);
    private final GenericEntityRepository genericEntityRepository;

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

    private String queryReport
            = "SELECT\n"
            + "CONCAT(hr.first_name, ' ', hr.last_name) as asesor,\n"
            + "rt.route_name as ruta,\n"
            + "cd.amount_expected as monto_esperado,\n"
            + "cd.amount_paid as monto_reportado,\n"
            + "cd.comments as comentarios,\n"
            + "(SELECT total_small_box FROM APC_STABLE_SMALL_BOX WHERE active_status = 'ENEBLED' and DATE(created_on) = DATE(':dateReport')) as total_caja,\n"
            + "(SELECT total_envelope FROM APC_STABLE_SMALL_BOX WHERE active_status = 'ENEBLED' and DATE(created_on) = DATE(':dateReport')) as total_sobre,\n"
            + "(SELECT total_bank_note FROM APC_STABLE_SMALL_BOX WHERE active_status = 'ENEBLED' and DATE(created_on) = DATE(':dateReport')) as total_efectivo,\n"
            + "(SELECT total_coin FROM APC_STABLE_SMALL_BOX WHERE active_status = 'ENEBLED' and DATE(created_on) = DATE(':dateReport')) as total_monedas,\n"
            + "(SELECT total_stable FROM APC_STABLE_SMALL_BOX WHERE active_status = 'ENEBLED' and DATE(created_on) = DATE(':dateReport')) as total_cuadre,\n"
            + "(SELECT description FROM APC_STABLE_SMALL_BOX WHERE active_status = 'ENEBLED' and DATE(created_on) = DATE(':dateReport')) as descripcion_cuadre\n"
            + "FROM APC_CLOSING_DAY cd\n"
            + "INNER JOIN APC_USER u ON cd.id_user = u.id\n"
            + "INNER JOIN APC_HUMAN_RESOURCE hr ON hr.id = u.id_human_resource\n"
            + "INNER JOIN (\n"
            + "	SELECT id_human_resource, id_route, max(created_on) \n"
            + "	FROM APC_HUMAN_RESOURCE_HAS_ROUTE\n"
            + "	GROUP BY id_human_resource\n"
            + ")hrr ON hr.id = hrr.id_human_resource\n"
            + "INNER JOIN APC_ROUTE rt ON hrr.id_route = rt.id\n"
            + "WHERE cd.active_status = 'ENEBLED' and DATE(cd.created_on) = DATE(':dateReport');";

}
