package mx.com.amx.mx.dda.crn;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.stream.Collectors;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import mx.com.amx.mx.dda.crn.bo.DDAExhibicionBO;
import mx.com.amx.mx.dda.crn.dto.ContratoDTO;
import mx.com.amx.mx.dda.crn.dto.ContratoTituloDTO;
import mx.com.amx.mx.dda.crn.dto.DatosCntTituloExhibicionDTO;
import mx.com.amx.mx.dda.crn.dto.RespSAPNotificaAFijoDTO;
import mx.com.amx.mx.dda.crn.dto.ResponseOrdenCompraDTO;
import mx.com.amx.mx.dda.crn.dto.ResultadoNotificacionDTO;

import org.apache.log4j.Logger;

public class DDAExhibicion implements ApplicationContextAware {

    private ApplicationContext context;
    private final String ARCHIVO_PROPIEDADES = "/general.properties";
    private final Logger LOG = Logger.getLogger(this.getClass().getSimpleName());
    Properties env = new Properties();
    private DDAExhibicionBO bo;

    public DDAExhibicion() {
        super();
        try {
            env.load(this.getClass().getResourceAsStream(ARCHIVO_PROPIEDADES));
        } catch (Exception e) {
            LOG.error(">Constructor[" + this.getClass().getSimpleName() + "] Ocurrio un error : " + e.getMessage());
        }
    }
    
    public void ejecuta() {
        ejecutaProceso(null);
    }

    public String ejecutaProceso(String contratosId) {

        LOG.info("  ");
        LOG.info("<< :::::::::::::::: Inicia Proceso Notifica Exhibicion DDA :::::::::::::::: >>");
        String mensaje = "OK";
        try {
            //-- 1. Verifica que no se este ejecutando ya un proceso de Notificacion
            LOG.info("    [INI]. Paso 1.- Verifica bandera de ejecucion de proceso de Notificacion.");
            boolean boEjecutandoseProceso = bo.existeProcesoNotificacionEjecutandose();
            LOG.info("    [INI]. Paso 1.- Verifica bandera de ejecucion de proceso de Notificacion. Esta ejecutando?: _" + boEjecutandoseProceso + "_");
            List<ContratoDTO> contratos = bo.contratosCandidatos(contratosId);

            if (!boEjecutandoseProceso) {
                //-- 2. Verificar si se puede iniciar el proceso
                LOG.info("    [INI]. Paso 2.- Verifica si se puede iniciar el proceso de Notificar Exhibicion.");
                boolean boIniciar = bo.verificaPuedeIniciar();
                LOG.info("    [FIN]. Paso 2.- Verifica si se puede iniciar el proceso de Notificar Exhibicion. Resultado: _" + boIniciar + "_");

                if (boIniciar) {
                    //-- 3. Actualiza bandera indicando que inicia el proceso general de Notificacion
                    LOG.info("    [INI]. Paso 3.- Prendiendo Bandera Inicio Proceso General Notificacion.");
                    boolean boActualizarBanderaIniciaProceso = bo.actualizarEjecutandoProcesoNotificacion("1");
                    LOG.info("    [FIN]. Paso 3.- Prendiendo Bandera Inicio Proceso General Notificacion. Resultado: _" + boActualizarBanderaIniciaProceso + "_");

                    if (boActualizarBanderaIniciaProceso) {
                        //-- 4. Consulta valor de referencia para Notificacion de Exhibicion
                        //-- Se quito el obtener el valor de referencia, ya que la ideologia es que siempre tome el dia "actual"
                        //-- Se deja comentado para fines de "rollback".
                        LOG.info("    [INI]. Paso 4.- Consulta valor de referencia.");
                        //String lstValorDiaNotificacion = bo.getValorDiaNotificacion();
                        String lstValorDiaNotificacion = "1";
                        LOG.info("    [FIN]. Paso 4.- Consulta de valor de referencia. Resultado: _" + lstValorDiaNotificacion + "_");

                        //-- Verifica que haya encontrado el valor
                        if (!lstValorDiaNotificacion.equals("-1")) {
                            //-- 5. Obtener la fecha de referencia con base en el Valor de Referencia obtenido
                            LOG.info("    [INI]. Paso 5.- Obtener fecha de referencia.");
                            String lstFechaReferencia = bo.obtenerFechaReferencia(lstValorDiaNotificacion);
                            LOG.info("    [FIN]. Paso 5.- Obtener fecha de referencia. Resultado: _" + lstFechaReferencia + "_");

                            if (!lstFechaReferencia.trim().isEmpty()) {

                                //-- 8. Llamado a la interfaz 10. Creacion de orden de Compra en SAP.
                                LOG.info("    [INI]. Paso 6.- Creacion en SAP de Titulos Recien exhibidos. (Creacion de Orden de Compra)");
                                ResponseOrdenCompraDTO resCOrdenCompra = bo.creacionTitulosSAP(lstFechaReferencia, contratosId);
                                LOG.info("    [FIN]. Paso 6.- Creacion en SAP de Titulos Recien exhibidos. Resultado: [" + resCOrdenCompra.getMensaje() + "]");
                                
                                //-- 7. Obtener los titulos recien exhibidos para notificarlos a SAP
                                LOG.info("    [INI]. Paso 7.- Obtener Titulos recien exhibidos con base a fecha referencia.");
                                List<DatosCntTituloExhibicionDTO> lobTitulos = bo.obtenerTitulosRecienExhibidos(lstFechaReferencia, contratosId);
                                List<DatosCntTituloExhibicionDTO> lobTitulosTC = bo.obtenerContratosRecienExhibidos(lstFechaReferencia, contratosId);
                                LOG.info("    [FIN]. Paso 7.- Obtener Titulos recien exhibidos con base a fecha referencia. Titulos:_" + lobTitulos.size() + "_");
                                
                                LOG.info("    [INI]. Paso 8.- Envío de terminos comerciales de los contratos. (Creacion de Terminos Comerciales)");
                                Map<String,String> respuestaTC = bo.ejecutarTerminosComerciales(lobTitulosTC, contratosId);
                                LOG.info("    [FIN]. Paso 8.- Envío de terminos comerciales de los contratos.");
                                if (Objects.nonNull(lobTitulos) && !lobTitulos.isEmpty()) {
                                    //-- 8. LLamado a WS para notificar Activo Fijo (Titulos recien exhibidos)
                                    LOG.info("    [INI]. Paso 9.- Llamado a WS SAP. Interfaz 12.");
                                    ResultadoNotificacionDTO rWS_Notifica = bo.notificarAFijoWS(lobTitulos, respuestaTC);
                                    LOG.info("    [FIN]. Paso 9.- Llamado a WS SAP. Interfaz 12. Resultado: _" + rWS_Notifica.getResultado() + "_");

                                    if (Objects.nonNull(rWS_Notifica.getNotificaciones()) && rWS_Notifica.getResultado()) {
                                        //-- Verifica que los enviados sean igual a los procesados(notificados) por parte de SAP
                                        //-- Si se enviaron 3, mismos 3 que debería regresar
                                        if (rWS_Notifica.getNotificaciones().size() == rWS_Notifica.getTitulosEnviados()) {
                                            //-- Recorrer la respuesta en busqueda de los titulos notificados en SAP correctamente
                                            int lnuTitulosNotificados = rWS_Notifica.getNotificaciones().size();
                                            int lnuNotificadosSAP_OK = 0;
                                            int lnuNotificadosSAP_NOOK = 0;
                                            int lnuUpdFechaNotifica_OK = 0;
                                            int lnuUpdFechaNotifica_NOOK = 0;
                                            int lnuInsSubNum_OK = 0;
                                            int lnuInsSubNum_NOOK = 0;

                                            //-- 9. Proceso de la respuesta de SAP y actualiza fecha de notificacion para aquellos que se notificaron correctamente en SAP
                                            LOG.info("    [INI]. Paso 10.- Revision de la respuesta de SAP para actualizar fecha notificacion SAP a los titulos notificados correctamente.");
                                            for (RespSAPNotificaAFijoDTO  notificacion : rWS_Notifica.getNotificaciones() ) {
                                                if (notificacion.getStatus().equalsIgnoreCase("OK")) {
                                                    lnuNotificadosSAP_OK++;

                                                    //-- Actualiza fecha de notificacion en los registros notificados correctamente en SAP
                                                    ContratoTituloDTO cntTitulo = new ContratoTituloDTO();
                                                    cntTitulo.setID_TITULO_CNTORIG(notificacion.getCodigoDDA());
                                                    boolean lboActFechaNotifica = bo.actualizaFechaNotificacion(cntTitulo);
                                                    LOG.info("        Actualiza fecha notificacion SAP. Titulo CNT con ID [" + notificacion.getCodigoDDA() + "]. Resultado: _" + lboActFechaNotifica + "_");

                                                    if (lboActFechaNotifica) {
                                                        lnuUpdFechaNotifica_OK++;

                                                        //--Insercion de registro en tabla de Aumentos/Disminucion y Subnumero
                                                        boolean lboRegistroSubNum = bo.insertarRegistroSubNumero(notificacion.getCodigoDDA());
                                                        if (lboRegistroSubNum) {
                                                            lnuInsSubNum_OK++;
                                                        } else {
                                                            lnuInsSubNum_NOOK++;
                                                        }

                                                    }//Ends if(lboActFechaNotifica)
                                                    else {
                                                        lnuUpdFechaNotifica_NOOK++;
                                                    }
                                                } else {
                                                    lnuNotificadosSAP_NOOK++;
                                                }

                                            }
                                            LOG.info("    [FIN]. Paso 10.- Revision de la respuesta de SAP para actualizar fecha notificacion SAP a los titulos notificados correctamente.");

                                            LOG.info("------------------------------------------------------------------------- ");
                                            LOG.info("- Resumen de proceso: ");
                                            LOG.info("------------------------------------------------------------------------- ");
                                            LOG.info("CREACION ORDEN DE COMPRA(i10) ");
                                            LOG.info("============================= ");
                                            LOG.info("  ");
                                            LOG.info("Total de registros enviados para Orden de Compra:[" + resCOrdenCompra.getLnuTotalRegOCSAP_Envio() + "]");
                                            LOG.info("Total de registros retornados por SAP de Orden de Compra:[" + resCOrdenCompra.getLnuTotalRegOCSAP_Regreso() + "]");
                                            LOG.info("  ");
                                            LOG.info("Total de registrados Orden de Compra correctamente:[" + resCOrdenCompra.getLnuTotalRegOCSAP_OK() + "]");
                                            LOG.info("Total de registrados Orden de Compra incorrectamente:[" + resCOrdenCompra.getLnuTotalRegOCSAP_NOOK() + "]");
                                            LOG.info("  ");
                                            LOG.info("Total de registros actualizados Id SAP:[" + resCOrdenCompra.getLnuTotalUpdIdSAP_OK() + "]");
                                            LOG.info("Total de registros no se pudo actualizar Id SAP :[" + resCOrdenCompra.getLnuTotalUpdIdSAP_NOOK() + "]");
                                            LOG.info("  ");
                                            LOG.info("NOTIFICACION TITULOS SAP(i12) ");
                                            LOG.info("============================= ");
                                            LOG.info("Total de registros enviados: [" + lobTitulos.size() + "]");
                                            LOG.info("Total de registros retornados por SAP: [" + lnuTitulosNotificados + "]");
                                            LOG.info("  ");
                                            LOG.info("Total de registros notificados satisfactoriamente en SAP: [" + lnuNotificadosSAP_OK + "] *");
                                            LOG.info("Total de registros notificados incorrectamente en SAP: [" + lnuNotificadosSAP_NOOK + "]");
                                            LOG.info("  ");
                                            LOG.info("* Total de registros actualizados en fecha notificacion: [" + lnuUpdFechaNotifica_OK + "]");
                                            LOG.info("* Total de registros no se pudo actualizar fecha notificacion: [" + lnuUpdFechaNotifica_NOOK + "]");
                                            LOG.info("  ");
                                            LOG.info("* Total de registros subnumero insertados correctamente: [" + lnuInsSubNum_OK + "]");
                                            LOG.info("* Total de registros subnumero no se pudo insertar: [" + lnuInsSubNum_NOOK + "]");
                                            LOG.info("------------------------------------------------------------------------- ");

                                            bo.actualizarEjecutandoProcesoNotificacion("0");
                                            LOG.info("Apaga bandera de proceso Notifica.[Caso Revision respuesta SAP y Actualizacion Fecha.]");

                                        }//Ends if(rWS_Notifica.getNotificaciones().size() == lobTitulos.size())
                                        else {
                                            LOG.error("DDA-NOT-011: El numero de titulos procesados fueron distintos al numero de titulos enviado.");
                                            mensaje = "Error: DDA-NOT-011";
                                            bo.actualizarEjecutandoProcesoNotificacion("0");
                                            LOG.info("Apaga bandera de proceso Notifica.[Caso Enviados y procesados distinto total.]");
                                        }
                                    }// Ends if(rWS_Notifica.getNotificaciones() != null && rWS_Notifica.getResultado())
                                    else if (Objects.nonNull(rWS_Notifica.getTransFault()) && !rWS_Notifica.getResultado()) {
                                        //-- Tracking
                                        LOG.error("Error al llamar el WS Notifica Activo Fijo: " + rWS_Notifica.getTransFault().toString());
                                        mensaje = "Error: DDA-NOT-012";
                                        LOG.error("Datos recibidos de la interfaz 12: " + rWS_Notifica.getNotificaciones().size() + " Datos enviados a la interfaz 12  " + lobTitulos.size());
                                        bo.actualizarEjecutandoProcesoNotificacion("0");
                                        LOG.info("Apaga bandera de proceso Notifica.[Caso TransFault]");
                                    }
                                }//Ends if(lobTitulos != null && lobTitulos.size() > 0)
                                else {
                                    LOG.error("DDA-NOT-006: No se encontraron registros de titulos recien exhibidos.");
                                    mensaje = "Error: DDA-NOT-006";
                                    bo.actualizarEjecutandoProcesoNotificacion("0");
                                    LOG.info("Apaga bandera de proceso Notifica.[Else_lobTitulos_null]");
                                }

                                //-- 9. Sos 22Ago17 Generación de la amortización real de los titulos
                                LOG.info("    [INI]. Paso 10.- Llamado a SP Amortizacion  Real.");
                                boolean lboResultadoSP = bo.ejecutarSPAmortizacionReal(contratosId);
                                LOG.info("    [FIN]. Paso 10.- Llamado a SP Amortizacion  Real. Resultado:_" + lboResultadoSP + "_");

                            }//Ends if(lstFechaReferencia.trim().length() > 0)
                            else {
                                LOG.error("DDA-NOT-005: No se pudo obtener la fecha de referencia");
                                mensaje = "Error: DDA-NOT-005";
                                updateTitulos(contratos, "NO SE LOGRO OBTENER LA FECHA DE REFERENCIA");
                                bo.actualizarEjecutandoProcesoNotificacion("0");
                                LOG.info("Apaga bandera de proceso Notifica.[Else_lstFechaReferencia_trim()_length()]");
                            }
                        }// Ends if(!lstValorDiaNotificacion.equals("-1"))
                        else {
                            LOG.error("DDA-NOT-004: No se pudo obtener el valor de referencia");
                            updateTitulos(contratos, "NO SE LOGRO OBTENER VALOR DE REFERENCIA");
                            mensaje = "Error: DDA-NOT-004";
                            bo.actualizarEjecutandoProcesoNotificacion("0");
                            LOG.info("Apaga bandera de proceso Notifica.[Else_boActualizarBanderaIniciaProceso]");
                        }
                    }//Ends if(boActualizarBanderaIniciaProceso)
                    else {
                        LOG.error("DDA-NOT-003: No se pudo actualizar la bandera de inicio de proceso.");
                        updateTitulos(contratos, "NO SE LOGRO ACTUALIZAR LA BANDERA DE INICIO");
                        mensaje = "Error: DDA-NOT-003";
                        bo.actualizarEjecutandoProcesoNotificacion("0");
                        LOG.info("Apaga bandera de proceso Notifica.[Else_boActualizarBanderaIniciaProceso]");

                    }
                }//Ends if(boIniciar)
                else {
                    LOG.error("DDA-NOT-002: No se han otorgado los permisos para poder iniciar el proceso.");
                    updateTitulos(contratos, "SIN PERMISOS PARA INICIAR PROCESOS A SAP");
                    mensaje = "Error: DDA-NOT-002";
                    bo.actualizarEjecutandoProcesoNotificacion("0");
                }
            }//Ends if(!boEjecutandoseProceso)
            else {
                LOG.error("DDA-NOT-001: Es probable que se haya iniciado este proceso previamente.");
                mensaje = "Error: DDA-NOT-001";
                updateTitulos(contratos, "PROCESO DE SAP INICIADO PREVIAMENTE");
                bo.actualizarEjecutandoProcesoNotificacion("0");
            }

        } catch (Exception e) {
            LOG.error("Ocurrio un error en ejecutaProceso::DDAExhibicion: " + e.getMessage());
            mensaje = "Error: DDA-NOT-013";
        }

        LOG.info("<< :::::::::::::::: Finaliza Proceso Notifica Exhibicion DDA :::::::::::::::: >>");
        LOG.info("  ");
        return mensaje;
    }
    
    private void updateTitulos(List<ContratoDTO> contratos, String mensaje){
        for (ContratoDTO contrato : contratos){
            bo.actualizarEstatusSapTitulosContrato(mensaje, contrato.getIdcontratoDDA());
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext arg0) throws BeansException {
        LOG.info("Entering to the application Context...");
        this.context = context;
    }

    public DDAExhibicionBO getBo() {
        return bo;
    }

    public void setBo(DDAExhibicionBO bo) {
        this.bo = bo;
    }
    
}