/*
 * 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.taxiservicios.beans.TaxiGenericBean;
import com.arrebol.taxiservicios.controller.admin.AprobarCancelacionController;
import com.arrebol.taxiservicios.controller.cobranza.CobranzaController;
import com.arrebol.taxiservicios.controller.predio.PredioController;
import com.arrebol.taxiservicios.controller.predio.PreventaController;
import com.arrebol.taxiservicios.model.enums.EstatusLote;
import com.arrebol.taxiservicios.model.enums.EstatusRembolso;
import com.arrebol.taxiservicios.model.enums.EstatusSolicitud;
import com.arrebol.taxiservicios.model.enums.GenericEnumType;
import com.arrebol.taxiservicios.model.predio.AbonoLote;
import com.arrebol.taxiservicios.model.predio.AbonosRembolsoCancelacionCompraLote;
import com.arrebol.taxiservicios.model.predio.RembolsosCancelacionCompraLote;
import com.arrebol.taxiservicios.model.predio.SolicitudesCancelacionCompraLote;
import com.arrebol.taxiservicios.controller.juridicas.DetalleLoteEtapaController;
import com.arrebol.taxiservicios.model.juridicas.DetalleLoteEtapa;
import com.arrebol.taxiservicios.model.predio.AbonoLoteDetalle;
import java.io.IOException;
import java.io.Serializable;
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.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 *
 * @author pc one
 */
@Named("aprobarCancelacionBean")
@ViewScoped
public class AprobarCancelacionBean extends TaxiGenericBean implements Serializable {

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

    private AprobarCancelacionController aprobarCancelacionController;
    private PredioController predioController;
    private PreventaController preventaController;
    private CobranzaController cobranzaController;
    private DetalleLoteEtapaController detalleLoteEtapaController;
    private List<SolicitudesCancelacionCompraLote> solicitudesList;
    private SolicitudesCancelacionCompraLote selectedSolicitud;
    private List<RembolsosCancelacionCompraLote> rembolsosList;
    private RembolsosCancelacionCompraLote selectedRembolso;
    private List<AbonoLote> abonoLoteList;
    private Integer mesesRembolso;
    private Date inicioPagos;
    private Double actualizarPago;
    private List<AbonosRembolsoCancelacionCompraLote> AbonosRembolsoList;
    private AbonosRembolsoCancelacionCompraLote selectedAbono;
    private Double totalPago;

    @PostConstruct
    public void init() {
        logger.info("start  init");
        try {
            setAprobarCancelacionController(new AprobarCancelacionController());
            setSolicitudesList(getAprobarCancelacionController().fillAllSolicitudesByLocation(getLoggedUser().getLocation()));
            setRembolsosList(getAprobarCancelacionController().fillAllRembolsosByLocation(getLoggedUser().getLocation()));
        } catch (Exception e) {
            logger.error("Error init", e);
        }
    }

    public void rechazarCancelacion() {
        logger.info("Rechazando cancelación");
        try {
            //Se devuelve el lote ha comprado 
            getSelectedSolicitud().getLote().setEstatusLote(EstatusLote.VENDIDO);
            setPredioController(new PredioController());
            getPredioController().addLote(getSelectedSolicitud().getLote(), getLoggedUser(), false);
            //Se desactiva la solicitud
            setAprobarCancelacionController(new AprobarCancelacionController());
            getSelectedSolicitud().setEstatusActivo(GenericEnumType.DISABLED);
            getSelectedSolicitud().setEstatusSolicitud(EstatusSolicitud.CANCELADO);
            getAprobarCancelacionController().addSolcitud(getSelectedSolicitud(), getLoggedUser(), false);
            //Se desactiva el rembolso            
            RembolsosCancelacionCompraLote rem = getAprobarCancelacionController().fillRembolsoBySolicitud(getSelectedSolicitud());
            if(rem!=null){
                rem.setEstatusActivo(GenericEnumType.DISABLED);
                getAprobarCancelacionController().addRembolso(rem, getLoggedUser(), false);
            }            
            // se actualiza la lista 
            setSolicitudesList(getAprobarCancelacionController().fillAllSolicitudesByLocation(getLoggedUser().getLocation()));
            setRembolsosList(getAprobarCancelacionController().fillAllRembolsosByLocation(getLoggedUser().getLocation()));
            logger.info("Se a rechazado el rembolso ");
            showMessage(FacesMessage.SEVERITY_INFO, "Rechazado", "La solicitud de cancelación se ha rechazado correctamente");
        } catch (Exception e) {
            logger.error("rechazarCancelacion: " + e);
            showMessage(FacesMessage.SEVERITY_ERROR, "Error", "Error al rechazar la solicitud");
        }
    }

    public void aprobarCancelacion() {
        logger.info("Cancelando compradel lote: " + getSelectedSolicitud().getId());
        try {
            setAprobarCancelacionController(new AprobarCancelacionController());
            setCobranzaController(new CobranzaController());
            setPredioController(new PredioController());
            setDetalleLoteEtapaController(new DetalleLoteEtapaController());
            setAbonoLoteList(getCobranzaController().fillAbonoAndAnticipoLoteByLote(getSelectedSolicitud().getLote()));
            //Desactivando abonos lote
            for (AbonoLote abono : getAbonoLoteList()) {
                abono.setEstatusActivo(GenericEnumType.DISABLED);
                
                // Se desactivan los abonos lote detalle si los hay
                List<AbonoLoteDetalle> abonoLoteDetalle = getCobranzaController().fillAbonoLoteDetalleLoteByAbonoLote(abono);
                if(!abonoLoteDetalle.isEmpty()){
                    for (AbonoLoteDetalle abD : abonoLoteDetalle) {
                        abD.setEstatusActivo(GenericEnumType.DISABLED);
                        getCobranzaController().updateAbonoLoteDetalle(abD, getLoggedUser());
                    }
                }
                
                getCobranzaController().addAbonoLote(abono, getLoggedUser(), false);
            }
            // Se desactiva el lote de jurídico si lo está 
            List<DetalleLoteEtapa> ListDetalleLoteEtapaJuridica = getDetalleLoteEtapaController().fillDetalleLoteEtapaByLote(getSelectedSolicitud().getLote());
            for (DetalleLoteEtapa detalleLoteEtapa : ListDetalleLoteEtapaJuridica) {
                detalleLoteEtapa.setEstatusActivo(GenericEnumType.DISABLED);
                getDetalleLoteEtapaController().addDetalleLoteEtapa(detalleLoteEtapa, getLoggedUser());
            }
            //Actualizacion del estatus de lote
            getSelectedSolicitud().getLote().setEstatusLote(EstatusLote.DISPONIBLE);
            getSelectedSolicitud().getLote().setLastUpdatedOn(new Date());
            getSelectedSolicitud().getLote().setMontoPagado(0.0);
            getPredioController().addLote(getSelectedSolicitud().getLote(), getLoggedUser(), false);
            //Se actualiza él estas de la solicitud
            getSelectedSolicitud().setEstatusSolicitud(EstatusSolicitud.APROBADO);
            getAprobarCancelacionController().addSolcitud(getSelectedSolicitud(), getLoggedUser(), false);
            //Actualizacion de la lista de solicitudes
            setSolicitudesList(getAprobarCancelacionController().fillAllSolicitudesByLocation(getLoggedUser().getLocation()));
            setRembolsosList(getAprobarCancelacionController().fillAllRembolsosByLocation(getLoggedUser().getLocation()));
            logger.info("La compra del lote fue cancelado correctamente: " + getSelectedSolicitud().getId());
            showMessage(FacesMessage.SEVERITY_INFO, "Cancelado", "La compra del lote fue cancelada correctamente");
        } catch (Exception e) {
            logger.error("cancelarCompra: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL, "Error", "Error al cancelar la compra");
        }
    }

    public void liquidarRembolso() {
        logger.info("Liquidando rembolso : " + getSelectedRembolso().getId());
        try {
            setAprobarCancelacionController(new AprobarCancelacionController());
            //Se actualiza él estas de la solicitud y se generan los abonos            
            crearCorrida(getSelectedRembolso());
            //Actualizacion de la lista de solicitudes
            setRembolsosList(getAprobarCancelacionController().fillAllRembolsosByLocation(getLoggedUser().getLocation()));
            logger.info("Se a liquidando el rembolso : " + getSelectedRembolso().getId());
            showMessage(FacesMessage.SEVERITY_INFO, "Liquidado", "La liquidación del rembolso se realizó correctamente");
        } catch (Exception e) {
            logger.error("liquidarRembolso: " + e);
            showMessage(FacesMessage.SEVERITY_FATAL, "Error", "Error al liquidar el rembolso");
        }
    }

    public void crearCorrida(RembolsosCancelacionCompraLote rembolso) throws IOException {
        logger.info("Creación de abonos");
        Double pagoPorMes = rembolso.getRembolso() / getMesesRembolso();
        //actualizasion de los datos de rembolso
        rembolso.setEstatusRembolso(EstatusRembolso.PROCESO);
        rembolso.setPlazosMes(getMesesRembolso());
        rembolso.setDiaAPagar(getInicioPagos());
        rembolso.setPagoMes(pagoPorMes);
        //Definición de la fecha de inicio y numero de pagos
        Calendar fechaInicial = Calendar.getInstance();
        fechaInicial.setTime(getInicioPagos());
        fechaInicial.add(Calendar.DATE, 1);
        // se define la cantidad de abonso a generar
        int numeroPagos = rembolso.getPlazosMes();
        //lista de fechas de pago
        List<Calendar> fechasDePago = new ArrayList<>();
        // Cargado de las fechas de pago por MES
        fechasDePago.add(fechaInicial);
        Calendar fechaActual = (Calendar) fechaInicial.clone();
        //captura el dia de una fecha en caso de que no se encuntre en le mes siguinte 
        boolean detenerFecha = false;
        Calendar fechaDetenida = Calendar.getInstance();
        //genera la lista de fechas
        for (int i = 1; i < numeroPagos; i++) {
            Calendar fechaSiguiente = (Calendar) fechaActual.clone();
            fechaSiguiente.add(Calendar.MONTH, 1);
            if (detenerFecha == false) {
                if (fechaActual.get(Calendar.DAY_OF_MONTH) > fechaSiguiente.getActualMaximum(Calendar.DAY_OF_MONTH)) {
                    detenerFecha = true;
                    fechaDetenida = (Calendar) fechaActual.clone();
                    fechaSiguiente.set(Calendar.DAY_OF_MONTH, fechaSiguiente.getActualMaximum(Calendar.DAY_OF_MONTH));
                }
            } else {
                if (fechaSiguiente.get(Calendar.DAY_OF_MONTH) <= fechaDetenida.get(Calendar.DAY_OF_MONTH)) {
                    detenerFecha = false;
                    fechaSiguiente.set(Calendar.DAY_OF_MONTH, fechaDetenida.get(Calendar.DAY_OF_MONTH));
                } else {
                    fechaSiguiente.set(Calendar.DAY_OF_MONTH, fechaSiguiente.getActualMaximum(Calendar.DAY_OF_MONTH));
                }
            }
            fechasDePago.add(fechaSiguiente);
            fechaActual = fechaSiguiente;
        }

        // Creación de pagos por fecha
        setActualizarPago(rembolso.getRembolso());
        int num = 1;
        for (Calendar fecha : fechasDePago) {
            try {
                AbonosRembolsoCancelacionCompraLote abono = new AbonosRembolsoCancelacionCompraLote();
                abono.setId(UUID.randomUUID().toString());
                abono.setRembolso(rembolso);
                abono.setConsecutivo(num);
                abono.setEstatusActivo(GenericEnumType.ENABLED);
                abono.setPagoEstatus(GenericEnumType.DISABLED);
                abono.setFechaAPagar(fecha.getTime());
                abono.setPago(pagoPorMes);
                abono.setSaldoAnterior(getActualizarPago());
                setActualizarPago(getActualizarPago() - pagoPorMes);
                abono.setSaldoNuevo(getActualizarPago());
                getAprobarCancelacionController().addAbonosRembolso(abono, getLoggedUser(), true);
            } catch (Exception e) {
                logger.error("Error al capturar el abono del dia: (" + fecha + ") " + e);
                showMessage(FacesMessage.SEVERITY_FATAL, "Error", "Error al capturar el abono del dia (" + fecha + ")");
            }
            num++;
        }
        //Se guardan los datos de rembolso
        getAprobarCancelacionController().addRembolso(rembolso, getLoggedUser(), false);
    }

    public void fillAllAbonosByRembolso() {
        setAprobarCancelacionController(new AprobarCancelacionController());
        setAbonosRembolsoList(getAprobarCancelacionController().fillAllAbonosByRembolso(getSelectedRembolso()));
    }

    public void payAbonoCant() {
        try {
            setAprobarCancelacionController(new AprobarCancelacionController());
            getSelectedAbono().setCantidadPagada(getTotalPago());
            getSelectedAbono().setPagoEstatus(GenericEnumType.ENABLED);
            Date fecha = fechaActualMasUno();
            getSelectedAbono().setLastUpdatedOn(fecha);
            // Se valida si el pago dados es le ultimo y cambie el estatus de rembolso a LIQUIDADO
            if (getAbonosRembolsoList().size() == getSelectedAbono().getConsecutivo()) {
                getSelectedRembolso().setEstatusRembolso(EstatusRembolso.LIQUIDADO);
                getAprobarCancelacionController().addRembolso(getSelectedRembolso(), getLoggedUser(), false);
                setRembolsosList(getAprobarCancelacionController().fillAllRembolsosByLocation(getLoggedUser().getLocation()));
            }
            getAprobarCancelacionController().addAbonosRembolso(getSelectedAbono(), getLoggedUser(), false);
            logger.info("El abono se pagó correctamente  : " + getSelectedRembolso().getId());
            showMessage(FacesMessage.SEVERITY_INFO, "Pagado", "El abono se pagó correctamente");
        } catch (Exception e) {
            logger.error("Ocurrió un error al pagar ele abono " + e);
            showMessage(FacesMessage.SEVERITY_FATAL, "Error", "Ocurrió un error al pagar ele abono");
        }
    }

    public void payAbono() {
        try {
            setAprobarCancelacionController(new AprobarCancelacionController());
            getSelectedAbono().setCantidadPagada(getSelectedAbono().getPago());
            getSelectedAbono().setPagoEstatus(GenericEnumType.ENABLED);
            Date fecha = fechaActualMasUno();
            getSelectedAbono().setLastUpdatedOn(fecha);
            // Se valida si el pago dados es le ultimo y cambie el estatus de rembolso a LIQUIDADO
            if (getAbonosRembolsoList().size() == getSelectedAbono().getConsecutivo()) {
                getSelectedRembolso().setEstatusRembolso(EstatusRembolso.LIQUIDADO);
                getAprobarCancelacionController().addRembolso(getSelectedRembolso(), getLoggedUser(), false);
                setRembolsosList(getAprobarCancelacionController().fillAllRembolsosByLocation(getLoggedUser().getLocation()));
            }
            getAprobarCancelacionController().addAbonosRembolso(getSelectedAbono(), getLoggedUser(), false);
            logger.info("El abono se pagó correctamente  : " + getSelectedRembolso().getId());
            showMessage(FacesMessage.SEVERITY_INFO, "Pagado", "El abono se pagó correctamente");
        } catch (Exception e) {
            logger.error("Ocurrió un error al pagar ele abono " + e);
            showMessage(FacesMessage.SEVERITY_FATAL, "Error", "Ocurrió un error al pagar ele abono");
        }
    }

    public Date fechaActualMasUno() {
        Date fechaActual = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(fechaActual);
        calendar.add(Calendar.DAY_OF_YEAR, 1);
        Date fechaNueva = calendar.getTime();
        return fechaNueva;
    }

    public void alertAprobar() {
        showMessage(FacesMessage.SEVERITY_WARN, "Alerta", "Apruebe la solitud de cancelación para generar los abonos");
    }

    public AprobarCancelacionController getAprobarCancelacionController() {
        return aprobarCancelacionController;
    }

    public void setAprobarCancelacionController(AprobarCancelacionController aprobarCancelacionController) {
        this.aprobarCancelacionController = aprobarCancelacionController;
    }

    public SolicitudesCancelacionCompraLote getSelectedSolicitud() {
        return selectedSolicitud;
    }

    public void setSelectedSolicitud(SolicitudesCancelacionCompraLote selectedSolicitud) {
        this.selectedSolicitud = selectedSolicitud;
    }

    public RembolsosCancelacionCompraLote getSelectedRembolso() {
        return selectedRembolso;
    }

    public void setSelectedRembolso(RembolsosCancelacionCompraLote selectedRembolso) {
        this.selectedRembolso = selectedRembolso;
    }

    public PredioController getPredioController() {
        return predioController;
    }

    public void setPredioController(PredioController predioController) {
        this.predioController = predioController;
    }

    public PreventaController getPreventaController() {
        return preventaController;
    }

    public void setPreventaController(PreventaController preventaController) {
        this.preventaController = preventaController;
    }

    public CobranzaController getCobranzaController() {
        return cobranzaController;
    }

    public void setCobranzaController(CobranzaController cobranzaController) {
        this.cobranzaController = cobranzaController;
    }

    public Integer getMesesRembolso() {
        return mesesRembolso;
    }

    public void setMesesRembolso(Integer mesesRembolso) {
        this.mesesRembolso = mesesRembolso;
    }

    public Date getInicioPagos() {
        return inicioPagos;
    }

    public void setInicioPagos(Date inicioPagos) {
        this.inicioPagos = inicioPagos;
    }

    public Double getActualizarPago() {
        return actualizarPago;
    }

    public void setActualizarPago(Double actualizarPago) {
        this.actualizarPago = actualizarPago;
    }

    public List<SolicitudesCancelacionCompraLote> getSolicitudesList() {
        return solicitudesList;
    }

    public void setSolicitudesList(List<SolicitudesCancelacionCompraLote> solicitudesList) {
        this.solicitudesList = solicitudesList;
    }

    public List<RembolsosCancelacionCompraLote> getRembolsosList() {
        return rembolsosList;
    }

    public void setRembolsosList(List<RembolsosCancelacionCompraLote> rembolsosList) {
        this.rembolsosList = rembolsosList;
    }

    public List<AbonoLote> getAbonoLoteList() {
        return abonoLoteList;
    }

    public void setAbonoLoteList(List<AbonoLote> abonoLoteList) {
        this.abonoLoteList = abonoLoteList;
    }

    public List<AbonosRembolsoCancelacionCompraLote> getAbonosRembolsoList() {
        return AbonosRembolsoList;
    }

    public void setAbonosRembolsoList(List<AbonosRembolsoCancelacionCompraLote> AbonosRembolsoList) {
        this.AbonosRembolsoList = AbonosRembolsoList;
    }

    public Double getTotalPago() {
        return totalPago;
    }

    public void setTotalPago(Double totalPago) {
        this.totalPago = totalPago;
    }

    public AbonosRembolsoCancelacionCompraLote getSelectedAbono() {
        return selectedAbono;
    }

    public void setSelectedAbono(AbonosRembolsoCancelacionCompraLote selectedAbono) {
        this.selectedAbono = selectedAbono;
    }

    public DetalleLoteEtapaController getDetalleLoteEtapaController() {
        return detalleLoteEtapaController;
    }

    public void setDetalleLoteEtapaController(DetalleLoteEtapaController detalleLoteEtapaController) {
        this.detalleLoteEtapaController = detalleLoteEtapaController;
    }

}
