/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.arrebol.taxiservicios.controller.admin;

import com.arrebol.taxiservicios.controller.util.HibernateUtil;
import com.arrebol.taxiservicios.model.catalog.Location;
import com.arrebol.taxiservicios.model.core.Person;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.enums.PaymentType;
import com.arrebol.taxiservicios.model.enums.PersonType;
import com.arrebol.taxiservicios.model.view.PersonListView;
import com.crov.prase.model.catalog.Despacho;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate;
import javax.persistence.criteria.Path;
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;

/**
 *
 * @author Picasso
 */
public class EmployeeController extends GenericPersonController implements Serializable {

    /**
     * Save Employee details.
     *
     * @param firstName
     * @param secondName
     * @param lastName
     * @param middleName
     * @param birthdate
     * @param admissionDate
     * @param personId
     * @param userName
     * @param despacho
     *
     * @return
     */
    public boolean updatePersonById(String firstName, String secondName,
            String lastName, String middleName, Date birthdate,
            Date admissionDate, String personId, String userName,
            String locationId, double salary, double imss, double saving,
            Despacho despacho) {
        logger.info("updateEmployeeById");

        boolean success = false;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            /**
             * Taxi Servicios goes for user details.
             */
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<User> criteria = builder.createQuery(User.class);
            Root<User> root = criteria.from(User.class);
            Path<String> idPath = root.get("id");
            Path<String> userNamePath = root.get("userName");

            criteria.select(builder.construct(User.class, idPath, userNamePath));
            criteria.where(builder.equal(root.get("userName"), userName));

            User user = session.createQuery(criteria).uniqueResult();

            builder = session.getCriteriaBuilder();
            CriteriaUpdate<Person> update = builder.createCriteriaUpdate(Person.class);
            Root<Person> rootPerson = update.from(Person.class);

            update.set("firstName", firstName);
            update.set("secondName", secondName);
            update.set("lastName", lastName);
            update.set("middleName", middleName);
            update.set("birthdate", birthdate);
            update.set("admissionDate", admissionDate);
            update.set("lastUpdatedBy", user);
            update.set("lastUpdatedOn", new Date());
            update.set("location", new Location(locationId));
            update.set("salary", salary);
            update.set("imss", imss);
            update.set("savingWeek", saving);
            if(despacho!=null){
                update.set("despacho", despacho);
            }
            
            update.where(builder.equal(rootPerson.get("id"), personId));

            int total = session.createQuery(update).executeUpdate();

            if (1 == total) {
                logger.info("Person updated employe_id: " + personId);
                transaction.commit();

                success = true;
            } else {
                logger.error("Person can not be updated " + personId);
                transaction.rollback();
            }
        } catch (HibernateException e) {
            logger.error("Person cannot be updated " + personId, e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method updatePersonById(" + personId + ") ", e);
            rollback(transaction);
        }
        return success;
    }

    /**
     * Update payment details from employee.
     *
     * @param employee
     * @param userName User to load and use to set createBy/updateBy user in the
     * record.
     * @return True if update payment details otherwise false.
     */
    public boolean addPayment(Person employee, String userName) {
        logger.info("addPayment");

        boolean success = false;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            /**
             * Taxi Servicios goes for user details.
             */
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<User> criteria = builder.createQuery(User.class);
            Root<User> root = criteria.from(User.class);
            Path<String> idPath = root.get("id");
            Path<String> userNamePath = root.get("userName");

            criteria.select(builder.construct(User.class, idPath, userNamePath));
            criteria.where(builder.equal(root.get("userName"), userName));

            User user = session.createQuery(criteria).uniqueResult();

            builder = session.getCriteriaBuilder();
            CriteriaUpdate<Person> update = builder.createCriteriaUpdate(Person.class);
            Root<Person> rootUpdate = update.from(Person.class);

            update.set("payment", employee.getPayment());
            update.set("paymentType", employee.getPaymentType());
            update.set("lastUpdatedBy", user);
            update.set("lastUpdatedOn", employee.getLastUpdatedOn());

            update.where(builder.equal(rootUpdate.get("id"), employee.getId()));

            int total = session.createQuery(update).executeUpdate();

            if (1 == total) {
                logger.info("Payment details updated");
                transaction.commit();

                success = true;
            } else {
                logger.error("Payment details can not be updated " + employee);
                transaction.rollback();
            }
        } catch (HibernateException e) {
            logger.error("Payment details can not be saved ", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method addPayment() ", e);
            rollback(transaction);
        }
        return success;
    }

    /**
     *
     * @param payment
     * @param paymentType
     * @param employeeId
     * @param userName
     * @return
     */
    public boolean updateEmployeePaymentDetailsById(Float payment,
            PaymentType paymentType, String employeeId, String userName) {
        logger.info("updateEmployeePaymentDetailsById");

        boolean success = false;
        Transaction transaction = null;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            transaction = session.beginTransaction();

            /**
             * Taxi Servicios goes for user details.
             */
            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaQuery<User> criteria = builder.createQuery(User.class);
            Root<User> root = criteria.from(User.class);
            Path<String> idPath = root.get("id");
            Path<String> userNamePath = root.get("userName");

            criteria.select(builder.construct(User.class, idPath, userNamePath));
            criteria.where(builder.equal(root.get("userName"), userName));

            User user = session.createQuery(criteria).uniqueResult();

            builder = session.getCriteriaBuilder();
            CriteriaUpdate<Person> update = builder.createCriteriaUpdate(Person.class);
            Root<Person> rootUpdate = update.from(Person.class);

            update.set("payment", payment);
            update.set("paymentType", paymentType);
            update.set("lastUpdatedBy", user);
            update.set("lastUpdatedOn", new Date());

            update.where(builder.equal(rootUpdate.get("id"), employeeId));

            int total = session.createQuery(update).executeUpdate();

            if (1 == total) {
                logger.info("Employee payment updated employe_id: " + employeeId);
                transaction.commit();

                success = true;
            } else {
                logger.error("Payment details can not be updated " + employeeId);
                transaction.rollback();
            }
        } catch (HibernateException e) {
            logger.error("Employee payment cannot be updated employee_id: " + employeeId, e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method updateEmployeePaymentDetailsById(" + employeeId + ") ", e);
            rollback(transaction);
        }
        return success;
    }

    public List<PersonListView> findListOfPersonsByType(PersonType type, String idLocation) {
        List<PersonListView> results = null;
        Transaction transaction = null;

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

            String hql = "FROM PersonListView WHERE type = :type AND location.id = :idLocation";

            results = session.createQuery(hql)
                    .setParameter("type", type)
                    .setParameter("idLocation", idLocation)
                    .getResultList();

            transaction.commit();
        } catch (HibernateException e) {
            logger.error("Can not list of persons", e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method findListOfPersonsByType() ", e);
            rollback(transaction);
        }
        return results;
    }

    public boolean editAdeudo(String id, Float adeudo, User lastUpdatedBy) {
        boolean success = false;
        Transaction transaction = null;

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

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaUpdate<Person> update = builder.createCriteriaUpdate(Person.class);
            Root<Person> rootPerson = update.from(Person.class);

            update.set("adeudo", adeudo);
            update.set("lastUpdatedBy", lastUpdatedBy);

            update.where(builder.equal(rootPerson.get("id"), id));

            int total = session.createQuery(update).executeUpdate();

            if (1 == total) {
                logger.info("Person updated employe_id: " + id);
                transaction.commit();

                success = true;
            } else {
                logger.error("Person can not be updated " + id);
                transaction.rollback();
            }
        } catch (HibernateException e) {
            logger.error("Person cannot be updated " + id, e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method editAdeudo(" + id + ") ", e);
            rollback(transaction);
        }
        return success;
    }

    public boolean editSaving(String id, double saving, User lastUpdatedBy) {
        boolean success = false;
        Transaction transaction = null;

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

            CriteriaBuilder builder = session.getCriteriaBuilder();
            CriteriaUpdate<Person> update = builder.createCriteriaUpdate(Person.class);
            Root<Person> rootPerson = update.from(Person.class);

            update.set("saving", saving);
            update.set("lastUpdatedBy", lastUpdatedBy);

            update.where(builder.equal(rootPerson.get("id"), id));

            int total = session.createQuery(update).executeUpdate();

            if (1 == total) {
                logger.info("Person updated employe_id: " + id);
                transaction.commit();

                success = true;
            } else {
                logger.error("Person can not be updated " + id);
                transaction.rollback();
            }
        } catch (HibernateException e) {
            logger.error("Person cannot be updated " + id, e);
            rollback(transaction);
        } catch (Exception e) {
            logger.error("Method editSaving(" + id + ") ", e);
            rollback(transaction);
        }
        return success;
    }

    private static final long serialVersionUID = -3117146006480333110L;

    final Logger logger = LogManager.getLogger(EmployeeController.class);

}
