package com.ejie.ad74a.jms.service;

import java.util.HashMap;
import java.util.Map;

import javax.jms.Message;
import javax.jms.TextMessage;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ejie.ad74a.constantes.Constantes;
import com.ejie.ad74a.dao.BandejaPapel0Dao;
import com.ejie.ad74a.dao.DocumentoPapel0Dao;
import com.ejie.ad74a.dao.ErrorJmsDao;
import com.ejie.ad74a.exceptions.Ad74aException;
import com.ejie.ad74a.exceptions.ConstantesCodeError;
import com.ejie.ad74a.exceptions.ManagerErrors;
import com.ejie.ad74a.jms.util.JMSHelper;
import com.ejie.ad74a.jms.util.MessageParser;
import com.ejie.ad74a.jms.util.ModelApplicationParser;
import com.ejie.ad74a.model.BandejaPapel0;
import com.ejie.ad74a.model.DocumentoPapel0;
import com.ejie.ad74a.model.ErrorJms;
import com.ejie.ad74a.scheduler.JobSchedulerService;
import com.ejie.ad74a.scheduler.SchedulerJobType;
import com.ejie.ad74a.service.BandejaPapel0Service;
import com.ejie.ad74a.util.comun.Utilidades;
import com.ejie.ad74a.util.constantes.ProcedimientosEnum;
import com.ejie.ad74a.ws.client.documentum.X97DistributionWebServiceImpl;
import com.ejie.ad74a.ws.client.libroRegistro.model.ejgvDocument.DocumentType;
import com.ejie.ad74a.ws.client.libroRegistro.model.ejgvDocument.InputRegisterType;
import com.ejie.ad74a.ws.client.libroRegistro.model.notification.NotificationBody;

/**
 * EntidadesServiceImpl generated by UDA, 21-jul-2021 10:42:45.
 * 
 * @author UDA
 */

@Service(value = "libroRegistroJMSService")
public class LibroRegistroJMSServiceImpl implements LibroRegistroJMSService {

	private static final Logger logger = LoggerFactory.getLogger(LibroRegistroJMSServiceImpl.class);

	private static final int TRANSACTION_TIMEOUT = 60;

	@Autowired
	private BandejaPapel0Dao bandejaPapel0Dao;

	@Autowired
	private DocumentoPapel0Dao documentoPapel0Dao;

	@Autowired
	private ParserJMSRequest parserRequest;

	@Autowired
	private ErrorJmsDao errorJmsDao;

	@Autowired
	private JobSchedulerService jobSchedulerService;

	@Autowired
	X97DistributionWebServiceImpl x97DistributionWebServiceImpl;

	@Override
	public synchronized void tratarMessage(Message inMessage) throws Throwable {
		LibroRegistroJMSServiceImpl.logger.debug("LibroRegistroJMSServiceImpl tratarMessage - Inicio");

		TextMessage msg = null;

		String idMensaje = "";
		if (inMessage instanceof TextMessage) {
			msg = (TextMessage) inMessage;
			LibroRegistroJMSServiceImpl.logger.debug("LibroRegistroJMSServiceImpl tratarMessage - msg: " + msg);
			// Recuperamos el NotificationBody
			NotificationBody notificationBody = null;
			boolean error = false;
			try {
				MessageParser<NotificationBody> parserTarea = new MessageParser<NotificationBody>(
						NotificationBody.class.getPackage().getName());
				notificationBody = parserTarea.parse(msg.getText());
			} catch (Exception e) {
				LibroRegistroJMSServiceImpl.logger.error(
						"LibroRegistroJMSServiceImpl.tratarMessage - Error al parsear el mensaje de la cola " + e);
				error = true;
			}
			if (!error) {
				Map<String, Object> mapaMensaje = JMSHelper.parsearMensajeJms(msg.getText());
				try {
					mapaMensaje.put("jmsid", inMessage.getStringProperty("messageIdPropagado"));
				} catch (Exception e) {
					LibroRegistroJMSServiceImpl.logger
							.error("LibroRegistroJMSServiceImpl.tratarMessage - Error al recuperar el jmsid");
				}

				try {
					// Ad74aInputRegister inputRegister = this.getInputRegister(notificationBody);
					this.proccesCDAREvent(notificationBody, mapaMensaje);
					LibroRegistroJMSServiceImpl.logger.debug("LibroRegistroJMSServiceImpl - Tratamos el msg ");
				} catch (Throwable e) {
					LibroRegistroJMSServiceImpl.logger.error("Error al tratar el message libro de registro: ");
					// guardamos el mensaje de error
					ErrorJms mensajeJms = ModelApplicationParser.getMensajeJmsToError(mapaMensaje);
					if (e instanceof Ad74aException) {
						Ad74aException ex = (Ad74aException) e;
						mensajeJms.setErrormsg50(getErrorMessage(ex.getMessage()));
						mensajeJms.setError50(ex.getCodeError());
						LibroRegistroJMSServiceImpl.logger.error("Error procesar evento: " + ex.getMessage());
					} else {
						mensajeJms.setErrormsg50(getErrorMessage(ExceptionUtils.getStackTrace(e)));
						LibroRegistroJMSServiceImpl.logger
								.error("Error procesar evento: " + ExceptionUtils.getStackTrace(e));
					}
					mensajeJms.setMensaje50(msg.getText());
					mensajeJms = errorJmsDao.add(mensajeJms);

					try {
						// ** Programar RE-Ejecución en diferido ** //
						HashMap<String, String> params = new HashMap<String, String>();
						params.put("id", mensajeJms.getId50().toString());
						this.jobSchedulerService.programarEjecucion(SchedulerJobType.ERROR, params);
					} catch (Exception e2) {
						// Solo para que no haga rollback
						LibroRegistroJMSServiceImpl.logger
								.error("Error programando re-ejecución: " + ExceptionUtils.getStackTrace(e2));
					}
				}
			}

		}

		inMessage.acknowledge();

		LibroRegistroJMSServiceImpl.logger.debug("LibroRegistroJMSServiceImpl.onMessage - Fin " + idMensaje);
	}

	private InputRegisterType getInputRegister(NotificationBody notificationBody) throws Throwable {
		LibroRegistroJMSServiceImpl.logger
				.debug("LibroRegistroJMSServiceImpl.getInputRegister - xmlValue: " + notificationBody.getXmlValue());
		// recogemos el contextSubmission

		MessageParser<InputRegisterType> parserInputRegister = new MessageParser<InputRegisterType>(
				InputRegisterType.class.getPackage().getName());
		InputRegisterType inputRegister = parserInputRegister.parse(notificationBody.getXmlValue().get(0));
//		
//		MessageParser<InputRegisterType> parserContext = new MessageParser<InputRegisterType>(
//				ContextSubmissionEvent.class.getPackage().getName());
//		InputRegisterType inputRegister = (InputRegisterType) UtilidadesXML
//				.unmarshallerObject(notificationBody.getXmlValue().get(0), InputRegisterType.class);
		LibroRegistroJMSServiceImpl.logger.debug("LibroRegistroJMSServiceImpl.getInputRegister - Fin ");
		return inputRegister;

	}

	/**
	 * Se procesa la entrada de papel0
	 * 
	 * - El segundo valor dentro del QRCode especifica el tipo de solicitud recibida
	 * 
	 * @param notificationBody
	 * @param mapaMensaje
	 * @throws Throwable
	 */
	@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class, timeout = LibroRegistroJMSServiceImpl.TRANSACTION_TIMEOUT)
	public void proccesCDAREvent(NotificationBody notificationBody, Map<String, Object> mapaMensaje) throws Throwable {
		LibroRegistroJMSServiceImpl.logger.info("LibroRegistroJMSServiceImpl.proccesCDAREvent - Inicio");

		InputRegisterType inputRegister = this.getInputRegister(notificationBody);
		String idJms = (String) mapaMensaje.get("jmsid");
		inputRegister.setIdJms(idJms);

		this.tratamientoBandejaPapel0(inputRegister);
		LibroRegistroJMSServiceImpl.logger.info("LibroRegistroJMSServiceImpl.R - Fin");
	}

	private void tratamientoBandejaPapel0(InputRegisterType inputRegister) throws Throwable {
		LibroRegistroJMSServiceImpl.logger.info("LibroRegistroJMSServiceImpl.tratamientoBandejaPapel0 - Inicio");
		try {
			BandejaPapel0 bandeja = this.parserRequest.getBandejaPapelo0(inputRegister);

			boolean existeMsgID = false;
			if (bandeja.getIdjms12() != null && !"".equals(bandeja.getIdjms12().trim())) {
				existeMsgID = this.bandejaPapel0Dao.existeMsgIDPapelCero(bandeja.getIdjms12());
			} else {
				existeMsgID = this.bandejaPapel0Dao.existeNumRegPapelCero(bandeja.getNumRegistro12());
			}

			// Si ya existe el idJms o el numRegistro en la BBDD no la tratamos
			if (!existeMsgID) {
				if (bandeja.getProcedureid12() == null || bandeja.getProcedureid12().equals("")) {

					// 10/01/2025: si no corresponde con uno de nuestros procedimientos, puede que
					// sea de las que estaban pendientes de escanear de la x87
					if (inputRegister.getQRCode() != null && inputRegister.getQRCode().indexOf("00870") >= 0) {

						bandeja.setTipo12("01"); // Solicitud por defecto
						bandeja.setProcedureid12(ProcedimientosEnum.ALTA.getId()); // Por defecto alta
						bandeja = this.bandejaPapel0Dao.add(bandeja);

						// Guardar los documentos en la BBDD
						DocumentoPapel0 docEntrada;
						for (DocumentType documento : inputRegister.getDocuments().getDocumentOid()) {
							if (!Utilidades.esBlancoNulo(documento.getId())) {
								docEntrada = this.parserRequest.getDocumentoBandejaPapel0(documento, bandeja);
								docEntrada.setUsuAlta13(Constantes.COD_APLICACION);
								this.documentoPapel0Dao.add(docEntrada);
							}
						}

					} else {
						// No es uno de nuestros procedimientos ni de la X87. Rechazar
						// Registrarla rechazada
						// this.bandejaPapel0Service.rechazarEntrada(bandeja, false);
					}

				} else {
					bandeja = this.bandejaPapel0Dao.add(bandeja);

					// Guardar los documentos en la BBDD
					DocumentoPapel0 docEntrada;
					for (DocumentType documento : inputRegister.getDocuments().getDocumentOid()) {
						if (!Utilidades.esBlancoNulo(documento.getId())) {
							docEntrada = this.parserRequest.getDocumentoBandejaPapel0(documento, bandeja);
							docEntrada.setUsuAlta13(Constantes.COD_APLICACION);
							this.documentoPapel0Dao.add(docEntrada);
						}
					}
				}
			}

		} catch (Exception e) {
			LibroRegistroJMSServiceImpl.logger.error("Error al grabar la bandeja de papel 0");
			ManagerErrors.manageException(e, ConstantesCodeError.MENSAJE_ERROR_GRABAR_BANDEJA_PAPEL0, null,
					ConstantesCodeError.CODE_ERROR_GRABAR_BANDEJA_PAPEL0, null);
		}

		LibroRegistroJMSServiceImpl.logger.info("LibroRegistroJMSServiceImpl.tratamientoBandejaPapel0 - Fin");

	}

	private String getErrorMessage(String error) {
		if (null != error && error.length() > 800) {
			error = error.substring(0, 799);
		}
		return error;
	}
}
