package com.dla.dda.services;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.type.IntegerType;
import org.hibernate.type.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.dla.dda.bussines.EmailBussines;
import com.dla.dda.domain.constants.ErrorCodes;
import com.dla.dda.domain.constants.Operacion;
import com.dla.dda.domain.exceptions.DLAIntegrationException;
import com.dla.dda.domain.exceptions.utils.ErrorUtils;
import com.dla.dda.domain.model.email.DetalleCorreoVO;
import com.dla.dda.domain.model.request.EmailRequest;
import com.dla.dda.domain.model.response.EmailResponse;
import com.dla.dda.persistence.dao.BaseDAO;
import com.dla.dda.persistence.model.DdaTContrato;
import com.dla.dda.persistence.model.DdaTWfSeguimiento;
import com.dla.dda.utils.json.JsonConverter;

@Repository
public class SeguimientoEmailService {
	
	@Autowired
	private BaseDAO dao;
	
	@Autowired
	private EmailBussines emailService;

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

	/**
	 * @see Servicio que envia los correos de recordatorio 
	 * @param
	 * @return boolean
	 * @throws DLAIntegrationException 
	 */
	@Transactional
	public String seguimientoDeCorreosPendientes() throws DLAIntegrationException {
		
		List<DdaTWfSeguimiento> seguimientos = null;
		DdaTContrato contrato;
		Object[] idAreaSeguimiento;
		List<Object[]> registrosCorreos;
		Type[] types = {IntegerType.INSTANCE};
		BigDecimal idArea;
		BigDecimal idAreaAux;
		Map<String, String> destinatarios;
		EmailRequest request = null;
		EmailResponse response = null;
		Date fechaActual = null;
		Long horas = 0L;
		Integer numeroCorreo = 1;
		boolean notificar = false;
		Calendar calFecha1 = Calendar.getInstance();
		String respuesta = "";
		int enviados = 0;
		
		
		
		try {
			
			seguimientos = dao.findListByQuery("findWfSeguiminetoByEstaAutorizado", new Object[] { new Integer(0) }, types, DdaTWfSeguimiento.class);
			fechaActual = new Date();
			
			for(DdaTWfSeguimiento seguimiento : seguimientos) {
				
				numeroCorreo = seguimiento.getFecha2() == null ? 2 : 3;
				horas = (fechaActual.getTime() - seguimiento.getFecha1().getTime()) / (1000 * 60 * 60);
				
				calFecha1.setTime(seguimiento.getFecha1());
				
				if(calFecha1.get(Calendar.DAY_OF_WEEK) == 6) {
					horas -= 48;
				}
				
				if(numeroCorreo == 2) {
					notificar = horas >= 24 ? true : false;
				}else {
					notificar = horas >= 48 ? true : false;
				}
				
				logger.info(" idContrato: [{}] -- horas transcurridas : [{}]", seguimiento.getIdContrato(), horas);
				
				if(notificar) {
					
					contrato = dao.read(seguimiento.getIdContrato(), DdaTContrato.class);
					idAreaSeguimiento = dao.findObjectByQuery("obtenerAreaSeguimiento", new Object[] { seguimiento.getIdPasoWf() }, types, Object[].class);
					idArea = (BigDecimal) idAreaSeguimiento[0];
					registrosCorreos = dao.findListByQuery("userInformation", new Object[] { new Integer(65) }, types, Object[].class);
					destinatarios = new HashMap<String, String>();//se solicito no repetir correos aunque en base esten repetidos
					
					for(Object[] registro : registrosCorreos) {
						idAreaAux = (BigDecimal)registro[0];
						if(numeroCorreo == 2) {
							if(idArea.equals(idAreaAux)) {
								destinatarios.put((String)registro[5], (String)registro[5]);
							}
						}else {
							destinatarios.put((String)registro[5], (String)registro[5]);
						}
						
					}
					
					request = obtenPeticionCorreo(numeroCorreo, contrato.getNumeroContrato(), fechaActual, destinatarios.values().toArray(new String[0]), ((String)idAreaSeguimiento[1]));
							
					logger.info("request : [{}]", request);
					
					response = emailService.enviaCorreo(request);
					
					logger.info("response : [{}]", response);
					
					if(response.getRespuesta().equals("true")) {
						
						if(numeroCorreo == 2) {
							seguimiento.setFecha2(fechaActual);
						}else {
							seguimiento.setFecha3(fechaActual);
							seguimiento.setEstaAutorizado(1);
						}
						dao.update(seguimiento, DdaTWfSeguimiento.class);
						enviados++;
					}
				}
				
			}
			
			respuesta = "Se notificaron " + enviados + " de " + seguimientos.size() + " seguimientos.";
			
		} catch (Exception e) {
			respuesta = "Ocurrio un problema en el seguimiento de correos.";
			logger.error("Error : [{}]", e);
			ErrorCodes error = ErrorCodes.FAIL;
			ErrorUtils.setMessage(error, e.getMessage());
			throw new DLAIntegrationException(error);
		}
		
		return respuesta;
		
	}
	
	private EmailRequest obtenPeticionCorreo(int numeroCorreo, String numeroContrato, Date fechaActual, String[] destinatarios, String areaSeguimiento) {
		String subject = "DDA - Seguimiento de contrato: ";
		String etiqueta = numeroCorreo == 2 ? "Se le informa que tiene <b>pendiente de autorizaci&oacute;n</b> el contrato: <b>nctoremp</b>. " : 
			"Se le informa que el responsable del &aacute;rea: sarea, <b>no ha realizado</b> la <br/> autorizaci&oacute;n asociada al contrato: <b>nctoremp</b>.";
		
		EmailRequest request = new EmailRequest();
		
		try {
			etiqueta = etiqueta.replace("nctoremp",numeroContrato);
			etiqueta = etiqueta.replace("sarea", areaSeguimiento);
			
			request.setDate(fechaActual.toString());
			request.setName("administrador");
			request.setToCompany("Derechos de Autor");
			request.setUserName("administrador@dladda.com");
			request.setDestinatarios(destinatarios);
			request.setSubject(subject + numeroContrato);
			request.setOperacion(Operacion.RECORDATORIO);
			request.setEtiqueta(etiqueta);
			request.setBody(JsonConverter.toJson(obtenDetalleCorreo(numeroCorreo, numeroContrato)));
			
		} catch (IOException e) {
			logger.error("Error : [{}]", e);
		}
		
		return request;
	}
	
	private DetalleCorreoVO obtenDetalleCorreo(int numeroCorreo, String numeroContrato){
		DetalleCorreoVO detalleCorreo = new DetalleCorreoVO();
		detalleCorreo.setNumeroContrato(numeroContrato);
		
		if(numeroCorreo == 2)
			detalleCorreo.setLineaFinal("Para revisar y autorizar haga ");
		else
			detalleCorreo.setLineaFinal("Para revisar haga ");
		
		return detalleCorreo;
	}
	
	

}
