/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package com.arrebol.taxiservicios.beans.admin;

import com.arrebol.car.driver.security.CarDriverSecurity;
import com.arrebol.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.controller.admin.CustomerController;
import com.arrebol.taxiservicios.controller.admin.StableGeneralBoxController;
import com.arrebol.taxiservicios.controller.admin.StableSmallBoxController;
import com.arrebol.taxiservicios.controller.catalog.UserLocationController;
import com.arrebol.taxiservicios.controller.system.UserController;
import com.arrebol.taxiservicios.model.admin.ClosingDay;
import com.arrebol.taxiservicios.model.admin.StableGeneralBox;
import com.arrebol.taxiservicios.model.admin.StableSmallBox;
import com.arrebol.taxiservicios.model.catalog.UserLocation;
import com.arrebol.taxiservicios.model.core.Person;
import com.arrebol.taxiservicios.model.core.User;
import com.arrebol.taxiservicios.model.enums.BasicType;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.enums.PersonType;
import com.arrebol.taxiservicios.model.enums.UserStatusType;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.primefaces.model.UploadedFile;

/**
 *
 * @author Crov
 */
@Named("migradorBean")
@ViewScoped
public class MigradorBean extends TaxiGenericBean implements Serializable {

    private static final long serialVersionUID = -2400590341745672164L;
    final Logger logger = LogManager.getLogger(getClass());

    private CustomerController customerController;
    private UserController userController;
    private StableGeneralBoxController generalBoxController;
    private StableSmallBoxController smallBoxController;
    private UserLocationController userLocationController;

    private UploadedFile file;

    @PostConstruct
    public void init() {
        logger.info("init");
        try {

        } catch (Exception e) {
            logger.error(" init", e);
        }
    }

    public void leerExel() {
        logger.info("leerExel");
        int columnaInicio = 1;
        int filaInicio = 3;
        try {
            // Obtén el contenido del archivo subido como un arreglo de bytes
            byte[] contenido = getFile().getContents();

            // Crea un archivo temporal para almacenar los bytes del archivo
            File archivoTemporal = File.createTempFile("tempFile", ".tmp");

            // Escribe los bytes en el archivo temporal
            FileUtils.writeByteArrayToFile(archivoTemporal, contenido);

            // Convierte el archivo temporal a un FileInputStream
            FileInputStream archivo = new FileInputStream(archivoTemporal);
            XSSFWorkbook libro = new XSSFWorkbook(archivo);

            //Listas vacías
            List<Person> listClientes = new ArrayList<>();
            List<Person> listPropietarios = new ArrayList<>();

            int numeroLibro = libro.getNumberOfSheets();
            for (int i = 0; i < numeroLibro; i++) {

                XSSFSheet hoja = libro.getSheetAt(i);
                int numeroFilas = hoja.getLastRowNum();

                for (int j = filaInicio; j <= numeroFilas; j++) {

                    XSSFRow fila = hoja.getRow(j);
                    int numeroColumnas = fila.getLastCellNum();

                    //new 
                    Person person = null;
                    // Se valida la hoja del Excel
                    switch (i) {
                        case 0: // clientes
                        case 1: // propietarios
                            // Nuevo objeto persona
                            person = new Person();
                            break;
                        default:
                            break;
                    }

                    for (int k = columnaInicio; k < numeroColumnas; k++) {

                        XSSFCell celda = fila.getCell(k);

                        // Se recorren las hojas del Excel
                        switch (i) {
                            case 0: // clientes
                            case 1: // propietarios
                                switch (k) {
                                    case 1: //firstName                                        
                                        try {
                                                person.setFirstName(celda.getStringCellValue());
                                            } catch (Exception e) {
                                                person.setFirstName("");
                                            }
                                            break;
                                        case 2: // secondName                                        
                                            try {
                                            person.setSecondName(celda.getStringCellValue());
                                            } catch (Exception e) {
                                                person.setSecondName("");
                                            }
                                            break;
                                        case 3: // lastName                                       
                                            try {
                                                person.setLastName(celda.getStringCellValue());
                                            } catch (Exception e) {
                                                person.setLastName("");
                                            }
                                            break;
                                        case 4: // middleName                                        
                                            try {
                                                person.setMiddleName(celda.getStringCellValue());
                                            } catch (Exception e) {
                                                person.setMiddleName("");
                                            }
                                            break;
                                        case 5: // birthdate
                                            try {
                                                DateUtil.isCellDateFormatted(celda);
                                                person.setBirthdate(celda.getDateCellValue());
                                            } catch (Exception e) {
                                                person.setBirthdate(new Date());
                                            }
                                            break;
                                        case 6: // mail
                                            try {
                                                person.setMail(celda.getStringCellValue());
                                            } catch (Exception e) {
                                                person.setMail("");
                                            }
                                            break;
                                        case 7: // password
                                            try {
                                            String tipo = (celda.getCellType()).toString();
                                            if ("NUMERIC".equals(tipo)) {
                                                // Obtén el valor numérico
                                                double valorNumerico = celda.getNumericCellValue();

                                                // Convierte el valor numérico a entero
                                                int valorEntero = (int) valorNumerico;

                                                // Convierte el entero a cadena
                                                person.setPassword(Integer.toString(valorEntero));
                                            } else {
                                                // Si no es numérico, asume que es una cadena
                                                person.setPassword(celda.getStringCellValue());
                                            }
                                        } catch (Exception e) {
                                            person.setPassword("");
                                        }
                                        break;
                                    default:
                                        break;
                                }
                            default:
                                // No hacer nada
                                break;
                        }

                    }

                    // se valida la hoja del exel
                    switch (i) {
                        case 0: // clientes
                            // Agregar el objeto 'person' a la lista
                            listClientes.add(person);
                            break;
                        case 1: // propietarios
                            // Agregar el objeto 'person' a la lista
                            listPropietarios.add(person);
                            break;
                        default:
                            break;
                    }

                }
            }

            archivo.close();

            // Guardando clientes            
            if (cargarUsuarios(listClientes)) {
                showMessage(FacesMessage.SEVERITY_INFO, "Clientes importados", "Los clientes se importaron correctamente");
            } else {
                showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error durante la importación de los clientes");
            }

            // Guardando propietarios 
            if (cargarUsuarios(listPropietarios)) {
                showMessage(FacesMessage.SEVERITY_INFO, "Propietarios importados", "Los propietarios se importaron correctamente");
            } else {
                showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Ocurrió un error durante la importación de los propietarios");
            }

        } catch (FileNotFoundException e) {
            logger.error("Error: " + e);
        } catch (IOException e) {
            logger.error("Error: " + e);
        } catch (Exception e) {
            logger.error("Error: " + e);
        }
    }

    public Boolean cargarUsuarios(List<Person> listPerson) {
        try {

            setCustomerController(new CustomerController());
            setUserController(new UserController());
            setGeneralBoxController(new StableGeneralBoxController());
            setSmallBoxController(new StableSmallBoxController());
            setUserController(new UserController());

            for (Person pe : listPerson) {
                // nueva persona
                logger.info("Creado persona");
                Person customer = new Person();
                customer.setId(UUID.randomUUID().toString());
                // datos formulario
                customer.setFirstName(pe.getFirstName());
                customer.setSecondName(pe.getSecondName());
                customer.setLastName(pe.getLastName());
                customer.setMiddleName(pe.getMiddleName());
                customer.setBirthdate(pe.getBirthdate());
                //
                customer.setPersonType(PersonType.CUSTOMER);
                customer.setActive(true);
                customer.setRoot(false);
                customer.setCreatedOn(new Date());
                customer.setLocation(getLoggedUser().getLocation());
                customer.setMail(pe.getMail());
                customer.setPassword(new CarDriverSecurity(APP, pe.getPassword()).getPassword());
                getCustomerController().addPerson(customer, getLoggedUser().getUserName(), true);

                // se crea un nuevo usuario 
                logger.info("Creado nuevo usuario");
                User user = new User(UUID.randomUUID().toString(), false, customer.getMail(), customer.getPassword(), Boolean.TRUE, getLoggedUser().getId());
                user.setUserStatusType(UserStatusType.ENABLED);
                user.setCreatedOn(new Date());
                getUserController().createUserByLocationAllPermission(user, customer.getId(), "images/avatar/mask-power/mask-1.png", getLoggedUser().getLocation().getId());

                // Fecha menos un mes para el nuevo corte           
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.MONTH, -1);
                // Se crea un corte en 0
                logger.info("Creando nuevo ClosingDay en 0");
                ClosingDay closingDay = new ClosingDay();
                closingDay.setId(UUID.randomUUID().toString());
                closingDay.setUser(user);
                closingDay.setAmountPaid(new BigDecimal(0));
                closingDay.setAmountExpected(new BigDecimal(0));
                closingDay.setAmountTransfer(new BigDecimal(0));
                closingDay.setActiveStatus(BasicType.ENEBLED);
                closingDay.setComments("Corte 0 agregados por importación de clientes");
                closingDay.setCreatedBy(getLoggedUser());
                closingDay.setCreatedOn(calendar.getTime());
                closingDay.setLocation(getLoggedUser().getLocation());
                getUserController().addClosingDateToNewUser(closingDay);

                // Se crea un corte en 0
                logger.info("Creando nuevo StableGeneralBox en 0");
                StableGeneralBox generalBox = new StableGeneralBox();
                generalBox.setId(UUID.randomUUID().toString());
                generalBox.setTotalGeneralBox(new BigDecimal(0));
                generalBox.setTotalEnvelope(new BigDecimal(0));
                generalBox.setTotalBankNote(new BigDecimal(0));
                generalBox.setTotalCoin(new BigDecimal(0));
                generalBox.setTotalStable(new BigDecimal(0));
                generalBox.setTotalBank(new BigDecimal(0));
                generalBox.setActiveStatus(BasicType.ENEBLED);
                generalBox.setDescription("Corte 0 agregados por importación de clientes");
                generalBox.setCreatedBy(getLoggedUser());
                generalBox.setCreatedOn(calendar.getTime());
                generalBox.setLocation(getLoggedUser().getLocation());
                getGeneralBoxController().saveStableGeneralBox(generalBox);

                // Se crea un corte en 0
                logger.info("Creando nuevo StableSmallBox en 0");
                StableSmallBox smallBox = new StableSmallBox();
                smallBox.setId(UUID.randomUUID().toString());
                smallBox.setTotalSmallBox(new BigDecimal(0));
                smallBox.setTotalEnvelope(new BigDecimal(0));
                smallBox.setTotalBankNote(new BigDecimal(0));
                smallBox.setTotalCoin(new BigDecimal(0));
                smallBox.setTotalStable(new BigDecimal(0));
                smallBox.setTotalTransfer(new BigDecimal(0));
                smallBox.setActiveStatus(BasicType.ENEBLED);
                smallBox.setDescription("Corte 0 agregados por importación de clientes");
                smallBox.setCreatedBy(getLoggedUser());
                smallBox.setCreatedOn(calendar.getTime());
                smallBox.setLocation(getLoggedUser().getLocation());
                getSmallBoxController().saveStableSmallBox(smallBox);

                // se crea un nuevo registro en UserLocation  
                logger.info("Creado un nuevo registro en UserLocation");
                UserLocation usLo = new UserLocation();
                usLo.setLocation(getLoggedUser().getLocation());
                usLo.setUser(user);
                usLo.setPagoAutomatico(0);
                usLo.setEstatusActivo(GenericEnumType.ENABLED);
                getUserLocationController().addUserLocation(usLo, user, true);
            }
            logger.info("Clientes importados");
            return true;
        } catch (Exception e) {
            logger.error("Error al importar los clientes");
            return false;
        }
    }

    public UploadedFile getFile() {
        return file;
    }

    public void setFile(UploadedFile file) {
        this.file = file;
    }

    public CustomerController getCustomerController() {
        return customerController;
    }

    public void setCustomerController(CustomerController customerController) {
        this.customerController = customerController;
    }

    public UserController getUserController() {
        return userController;
    }

    public void setUserController(UserController userController) {
        this.userController = userController;
    }

    public StableGeneralBoxController getGeneralBoxController() {
        return generalBoxController;
    }

    public void setGeneralBoxController(StableGeneralBoxController generalBoxController) {
        this.generalBoxController = generalBoxController;
    }

    public StableSmallBoxController getSmallBoxController() {
        return smallBoxController;
    }

    public void setSmallBoxController(StableSmallBoxController smallBoxController) {
        this.smallBoxController = smallBoxController;
    }

    public UserLocationController getUserLocationController() {
        return userLocationController;
    }

    public void setUserLocationController(UserLocationController userLocationController) {
        this.userLocationController = userLocationController;
    }

}
