/*
 * 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.taxiservicios.controller.admin;

import com.arrebol.taxiservicios.controller.connection.ConnectionManager;
import com.arrebol.taxiservicios.controller.util.HibernateUtil;
import com.arrebol.taxiservicios.model.admin.Sale;
import com.arrebol.taxiservicios.model.admin.StableSmallBox;
import com.arrebol.taxiservicios.model.catalog.Location;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.enums.EstatusSolicitud;
import com.arrebol.taxiservicios.model.enums.ExpenseStatusType;
import com.arrebol.taxiservicios.model.view.report.PaymentClient;
import java.io.Serializable;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
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.NativeQuery;

/**
 *
 * @author Oscar Armando Vargas Cardenas <oscar.vargas@arrebol.com.mx>
 */
public class GenericValidationController extends ConnectionManager implements Serializable{
    
    public boolean existCheckStocktakingPending(String idLocation) {
        logger.info("existCheckStocktakingPending");

        boolean success = true;
        Transaction transaction = null;

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

            String query = "SELECT sgb.id "
                    + "FROM check_stocktaking sgb "
                    + "WHERE "
                    + "sgb.check_status = 'PENDING' AND active = 1 AND id_location = '"+ idLocation+"'";

            List<String> records = session.createSQLQuery(query).getResultList();

            if (records.isEmpty()) {
                success = false;
            }

            transaction.commit();

            logger.info("Total of stable general box found: " + records.size());
        } catch (HibernateException e) {
            logger.error("Can not find next stable general box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existNextPaidStableGeneralBoxByCreatedOn()", e);
            rollback(transaction);
        }

        return success;
    }
    
    /**
     * 
     * @param date
     * @param user
     * @return 
     */
    public boolean existClosingDayByCreatedOn(Date date, User user) {
        logger.info("existClosingDayByCreatedOn");

        boolean success = true;
        Transaction transaction = null;

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

            String query = "SELECT COUNT(ssb.id) "
                    + "FROM ClosingDay ssb "
                    + "WHERE DATE(ssb.createdOn) = DATE(:date) "
                    + "AND ssb.activeStatus = 'ENEBLED' "
                    + "AND ssb.user = :user";

            Long count = (Long) session.createQuery(query)
                    .setParameter("date", date)
                    .setParameter("user", user).uniqueResult();

            if (null != count && count == 0) {
                success = false;
            }

            transaction.commit();

            logger.info("Total of closing day found: " + count);
        } catch (HibernateException e) {
            logger.error("Can not find stable small box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existStableSmallBoxByCreatedOn()", e);
            rollback(transaction);
        }

        return success;
    }
    
    public boolean existMutualClosingDayByCreatedOn(Date date, User user) {
        logger.info("existClosingDayByCreatedOn");

        boolean success = true;
        Transaction transaction = null;

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

            String query = "SELECT COUNT(ssb.id) "
                    + "FROM MutualClosingDay ssb "
                    + "WHERE DATE(ssb.createdOn) = DATE(:date) "
                    + "AND ssb.activeStatus = 'ENEBLED' "
                    + "AND ssb.user = :user";

            Long count = (Long) session.createQuery(query)
                    .setParameter("date", date)
                    .setParameter("user", user).uniqueResult();

            if (null != count && count == 0) {
                success = false;
            }

            transaction.commit();

            logger.info("Total of closing day found: " + count);
        } catch (HibernateException e) {
            logger.error("Can not find stable small box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existStableSmallBoxByCreatedOn()", e);
            rollback(transaction);
        }

        return success;
    }
    
    public boolean existStableGeneralBoxByCurdate(User user) {
        logger.info("existStableGeneralBoxByCurdate");

        boolean success = true;
        Transaction transaction = null;

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

            String query = "SELECT COUNT(ssb.id) "
                    + "FROM StableGeneralBox ssb "
                    + "WHERE DATE(ssb.createdOn) = CURDATE() "
                    + "AND ssb.activeStatus = 'ENEBLED' "
                    + "AND ssb.location.id = :locationID";

            Long count = (Long) session.createQuery(query)
                    .setParameter("locationID", user.getLocation().getId()).uniqueResult();

            if (null != count && count == 0) {
                success = false;
            }

            transaction.commit();

            logger.info("Total of StableGeneralBox found: " + count);
        } catch (HibernateException e) {
            logger.error("Can not find StableGeneralBox by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existStableGeneralBoxByCurdate()", e);
            rollback(transaction);
        }

        return success;
    }
    
    public boolean existMutualStableSmallBoxByCurdate(User user) {
        logger.info("existStableGeneralBoxByCurdate");

        boolean success = true;
        Transaction transaction = null;

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

            String query = "SELECT COUNT(ssb.id) "
                    + "FROM MutualStableSmallBox ssb "
                    + "WHERE DATE(ssb.createdOn) = CURDATE() "
                    + "AND ssb.activeStatus = 'ENEBLED' "
                    + "AND ssb.location.id = :locationID";

            Long count = (Long) session.createQuery(query)
                    .setParameter("locationID", user.getLocation().getId()).uniqueResult();

            if (null != count && count == 0) {
                success = false;
            }

            transaction.commit();

            logger.info("Total of StableGeneralBox found: " + count);
        } catch (HibernateException e) {
            logger.error("Can not find StableGeneralBox by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existStableGeneralBoxByCurdate()", e);
            rollback(transaction);
        }

        return success;
    }
    
    public boolean existStableSmallBoxByCurdate(User user) {
        logger.info("existStableSmallBoxByCurdate");

        boolean success = true;
        Transaction transaction = null;

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

            String query = "SELECT COUNT(ssb.id) "
                    + "FROM StableSmallBox ssb "
                    + "WHERE DATE(ssb.createdOn) = CURDATE() "
                    + "AND ssb.activeStatus = 'ENEBLED' "
                    + "AND ssb.location.id = :locationID";

            Long count = (Long) session.createQuery(query)
                    .setParameter("locationID", user.getLocation().getId()).uniqueResult();

            if (null != count && count == 0) {
                success = false;
            }

            transaction.commit();

            logger.info("Total of StableGeneralBox found: " + count);
        } catch (HibernateException e) {
            logger.error("Can not find StableGeneralBox by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existStableSmallBoxByCurdate()", e);
            rollback(transaction);
        }

        return success;
    }
    
    
    public Date lastStableGeneralBoxByDate(User user) {
        logger.info("lastStableGeneralBoxByDate");

        Date success = null;
        Transaction transaction = null;

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

            String query = "SELECT cd.createdOn FROM StableGeneralBox cd "
                    + "WHERE DATE(cd.createdOn) <= CURDATE() AND cd.location.id = :locationID AND cd.activeStatus = 'ENEBLED' "
                    + "order by cd.createdOn DESC";

            success = (Date) session.createQuery(query)
                    .setParameter("locationID", user.getLocation().getId()).setMaxResults(1)
                    .uniqueResult();

            transaction.commit();

            logger.info("Total of closing day found: ");
        } catch (HibernateException e) {
            logger.error("Can not find stable small box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method lastStableGeneralBoxByDate()", e);
            rollback(transaction);
        }

        return success;
    }
    
    public Date lastStableSmallBoxByDate(User user) {
        logger.info("lastStableSmallBoxByDate");

        Date success = null;
        Transaction transaction = null;

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

            String query = "SELECT cd.createdOn FROM StableSmallBox cd "
                    + "WHERE DATE(cd.createdOn) <= CURDATE() AND cd.location.id = :locationID AND cd.activeStatus = 'ENEBLED' "
                    + "order by cd.createdOn DESC";

            success = (Date) session.createQuery(query)
                    .setParameter("locationID", user.getLocation().getId()).setMaxResults(1)
                    .uniqueResult();

            transaction.commit();

            logger.info("Total of closing day found: ");
        } catch (HibernateException e) {
            logger.error("Can not find stable small box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method lastStableSmallBoxByDate()", e);
            rollback(transaction);
        }

        return success;
    }
    
     
    
    public Date lastMutualStableSmallBoxByDate(User user) {
        logger.info("lastMutualStableSmallBoxByDate");

        Date success = null;
        Transaction transaction = null;

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

            String query = "SELECT cd.createdOn FROM MutualStableSmallBox cd "
                    + "WHERE DATE(cd.createdOn) <= CURDATE() AND cd.location.id = :locationID AND cd.activeStatus = 'ENEBLED' "
                    + "order by cd.createdOn DESC";

            success = (Date) session.createQuery(query)
                    .setParameter("locationID", user.getLocation().getId()).setMaxResults(1)
                    .uniqueResult();

            transaction.commit();

            logger.info("Total of closing day found: ");
        } catch (HibernateException e) {
            logger.error("Can not find stable small box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method lastMutualStableSmallBoxByDate()", e);
            rollback(transaction);
        }

        return success;
    }
    
    public boolean isReadyToDoADailyCash(String idLocation) {
        logger.info("isReadyToDoADailyCash");

        boolean ready = false;

        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            String query = "SELECT COUNT(id) AS total_of_users FROM view_daily_cash_by_user WHERE (total_expenses_in+total_expenses_out+total_payment_client+total_transfer_send+total_transfer_receiver) <> 0 AND id_location = '"+idLocation+"'";

            NativeQuery nativeQuery = session.createSQLQuery(query);

            BigInteger total = (BigInteger) (nativeQuery.uniqueResult());

            if (null != total && total.equals(BigInteger.ZERO)) {
                ready = true;
            }

            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Can not ready total of users", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method isReadyToDoADailyCash()", e);
            rollback(transaction);
        }
        return ready;
    }
    
    public boolean existSalesDepositPending(String user) {
        logger.info("existCheckStocktakingPending");

        boolean success = true;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            String query = "SELECT COUNT(ssb.id) "
                    + "FROM Sale ssb "
                    + "WHERE  "
                    + "ssb.status = 'PENDING' "
                    + "AND ssb.createdBy.id = :user";

            Long count = (Long) session.createQuery(query)
                    
                    .setParameter("user", user).uniqueResult();

            if (null != count && count == 0) {
                success = false;
            }
            
            

            transaction.commit();

            logger.info("Total of stable general box found: " + count);
        } catch (HibernateException e) {
            logger.error("Can not find next stable general box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existNextPaidStableGeneralBoxByCreatedOn()", e);
            rollback(transaction);
        }

        return success;
    }
    
    public boolean existSanctionDepositPending(String user) {
        logger.info("existCheckStocktakingPending");

        boolean success = true;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            String query = "SELECT COUNT(ssb.id) "
                    + "FROM Sanction ssb "
                    + "WHERE  "
                    + "ssb.depositStatus = 'PENDING' "
                    + "AND ssb.createdBy.id = :user";

            Long count = (Long) session.createQuery(query)
                    
                    .setParameter("user", user).uniqueResult();

            if (null != count && count == 0) {
                success = false;
            }
            
            

            transaction.commit();

            logger.info("Total of stable general box found: " + count);
        } catch (HibernateException e) {
            logger.error("Can not find next stable general box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existNextPaidStableGeneralBoxByCreatedOn()", e);
            rollback(transaction);
        }

        return success;
    }
    
    public boolean existExpenseDepositPending(String user) {
        logger.info("existCheckStocktakingPending");

        boolean success = true;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            String query = "SELECT COUNT(ssb.id) "
                    + "FROM Expense ssb "
                    + "WHERE  "
                    + "ssb.depositStatus = 'PENDING' "
                    + "AND ssb.createdBy.id = :user";

            Long count = (Long) session.createQuery(query)
                    
                    .setParameter("user", user).uniqueResult();

            if (null != count && count == 0) {
                success = false;
            }
            
            

            transaction.commit();

            logger.info("Total of stable general box found: " + count);
        } catch (HibernateException e) {
            logger.error("Can not find next stable general box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existNextPaidStableGeneralBoxByCreatedOn()", e);
            rollback(transaction);
        }

        return success;
    }    

    public boolean existPaymentClientDepositPending(String user) {
        logger.info("existCheckStocktakingPending");

        boolean success = true;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            String query = "SELECT COUNT(ssb.id) "
                    + "FROM PaymentClient ssb "
                    + "WHERE  "
                    + "ssb.depositStatus = 'PENDING' "
                    + "AND ssb.createdBy.id = :user";

            Long count = (Long) session.createQuery(query)
                    
                    .setParameter("user", user).uniqueResult();

            if (null != count && count == 0) {
                success = false;
            }
            
            

            transaction.commit();

            logger.info("Total of stable general box found: " + count);
        } catch (HibernateException e) {
            logger.error("Can not find next stable general box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existNextPaidStableGeneralBoxByCreatedOn()", e);
            rollback(transaction);
        }

        return success;
    }
    
    public boolean existInvoiceDepositPending(String user) {
        logger.info("existCheckStocktakingPending");

        boolean success = true;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            String query = "SELECT COUNT(ssb.id) "
                    + "FROM Invoice ssb "
                    + "WHERE  "
                    + "ssb.depositStatus = 'PENDING' "
                    + "AND ssb.createdBy.id = :user";

            Long count = (Long) session.createQuery(query)
                    
                    .setParameter("user", user).uniqueResult();

            if (null != count && count == 0) {
                success = false;
            }
            
            

            transaction.commit();

            logger.info("Total of stable general box found: " + count);
        } catch (HibernateException e) {
            logger.error("Can not find next stable general box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existNextPaidStableGeneralBoxByCreatedOn()", e);
            rollback(transaction);
        }

        return success;
    }
    
    public boolean existServiceOrdeDepositPending(String user) {
        logger.info("existCheckStocktakingPending");

        boolean success = true;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            String query = "SELECT COUNT(ssb.id) "
                    + "FROM ServiceOrder ssb "
                    + "WHERE  "
                    + "ssb.depositStatus = 'PENDING' "
                    + "AND ssb.createdBy.id = :user";

            Long count = (Long) session.createQuery(query)
                    
                    .setParameter("user", user).uniqueResult();

            if (null != count && count == 0) {
                success = false;
            }
            
            

            transaction.commit();

            logger.info("Total of stable general box found: " + count);
        } catch (HibernateException e) {
            logger.error("Can not find next stable general box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existNextPaidStableGeneralBoxByCreatedOn()", e);
            rollback(transaction);
        }

        return success;
    }
    
    public boolean existExpenseCompanyInDepositPending(String user) {
        logger.info("existCheckStocktakingPending");

        boolean success = true;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            String query = "SELECT COUNT(ssb.id) "
                    + "FROM ExpenseCompany ssb "
                    + "WHERE  "
                    + "ssb.depositStatus = 'PENDING' AND ssb.expenseCompanyType = 'PAYMENT_IN'"
                    + "AND ssb.location.id = :user";

            Long count = (Long) session.createQuery(query)
                    
                    .setParameter("user", user).uniqueResult();

            if (null != count && count == 0) {
                success = false;
            }
            
            

            transaction.commit();

            logger.info("Total of stable general box found: " + count);
        } catch (HibernateException e) {
            logger.error("Can not find next stable general box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existNextPaidStableGeneralBoxByCreatedOn()", e);
            rollback(transaction);
        }

        return success;
    }
    
    public boolean existExpenseCompanyOutDepositPending(String user) {
        logger.info("existCheckStocktakingPending");

        boolean success = true;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            String query = "SELECT COUNT(ssb.id) "
                    + "FROM ExpenseCompany ssb "
                    + "WHERE  "
                    + "ssb.depositStatus = 'PENDING' AND ssb.expenseCompanyType = 'PAYMENT_OUT'"
                    + "AND ssb.location.id = :user";

            Long count = (Long) session.createQuery(query)
                    
                    .setParameter("user", user).uniqueResult();

            if (null != count && count == 0) {
                success = false;
            }
            
            

            transaction.commit();

            logger.info("Total of stable general box found: " + count);
        } catch (HibernateException e) {
            logger.error("Can not find next stable general box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existNextPaidStableGeneralBoxByCreatedOn()", e);
            rollback(transaction);
        }

        return success;
    }
    
    public boolean existTaxesDepositPending(String user) {
        logger.info("existCheckStocktakingPending");

        boolean success = true;
        Transaction transaction = null;

        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();
            String query = "SELECT COUNT(ssb.id) "
                    + "FROM Taxes ssb "
                    + "WHERE  "
                    + "ssb.depositStatus = 'PENDING' "
                    + "AND ssb.location.id = :user";

            Long count = (Long) session.createQuery(query)
                    
                    .setParameter("user", user).uniqueResult();

            if (null != count && count == 0) {
                success = false;
            }
            
            

            transaction.commit();

            logger.info("Total of stable general box found: " + count);
        } catch (HibernateException e) {
            logger.error("Can not find next stable general box by created on", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method existNextPaidStableGeneralBoxByCreatedOn()", e);
            rollback(transaction);
        }

        return success;
    }
    
    
    
    final Logger logger = LogManager.getLogger(GenericValidationController.class);
    private static final long serialVersionUID = -6732331411572526429L;
    
}
