package com.mx.dla.dda.reporte.pagosTransaccion.bos;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.ibatis.executor.result.ResultMapException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mx.dla.dda.catalogos.daos.CatalogosDAO;
import com.mx.dla.dda.catalogos.dtos.CatalogoDTO;
import com.mx.dla.dda.contrato.generales.bos.GeneralesBO;
import com.mx.dla.dda.contrato.generales.dtos.ContratoDTO;
import com.mx.dla.dda.contrato.transaccion.exceptions.dtos.TransaccionException;
import com.mx.dla.dda.reporte.pagosTransaccion.daos.PagoTransacionDAO;
import com.mx.dla.dda.reporte.pagosTransaccion.daos.TransaccionSAPDAO;
import com.mx.dla.dda.reporte.pagosTransaccion.dtos.DTEntradaMercancia;
import com.mx.dla.dda.reporte.pagosTransaccion.dtos.MercanciaI32DTO;
import com.mx.dla.dda.reporte.pagosTransaccion.dtos.PagoTransaccion;
import com.mx.dla.dda.reporte.pagosTransaccion.dtos.PagoTransaccionFiltros;
import com.mx.dla.dda.reporte.pagosTransaccion.dtos.TransaccionSAP;
import com.mx.dla.dda.restClient.bos.DLARestClient;
import com.mx.dla.dda.restClient.bos.DLARestClientFactory;
import com.mx.dla.dda.restClient.constants.DLARestServices;
import com.mx.dla.global.bos.BaseBO;

@Service
public class PagoTransaccionBO extends BaseBO {

	@Autowired
	private CatalogosDAO catalogosDAO;
	@Autowired
	private PagoTransacionDAO pagoTransacionDAO;
	@Autowired
	private GeneralesBO generalesBO;
	@Autowired
	public DLARestClientFactory dlaRestClientFactory;
	@Autowired
	private TransaccionSAPDAO transaccionSAPDAO;
	
	public static final String OK ="OK";
	
	public List<PagoTransaccion> buscarPagos(PagoTransaccionFiltros filtros) {
		filtros = acondicionaFiltros(filtros);
		List<PagoTransaccion> m =  pagoTransacionDAO.buscarPagosTransaccion(filtros);
		return m;
	}

	private PagoTransaccionFiltros acondicionaFiltros(PagoTransaccionFiltros filtros)
	{
		if(filtros.getMes() == null || "".equals(filtros.getMes()))
		{
			Calendar c = Calendar.getInstance();
			c.set(Calendar.MONTH, c.get(Calendar.MONTH )-1);
			Date d = c.getTime();
			SimpleDateFormat sf = new SimpleDateFormat("MM-yyyy");
			filtros.setMes(sf.format(d));
		}
		if("".equals(filtros.getTipoTitulo()))
		{
			filtros.setTipoTitulo(null);
		}
		return filtros;
	}
	
	public List<CatalogoDTO> buscarEstudios() {
		return catalogosDAO.buscarEstudios();
	}
	
	public void notificarTransaccionSAP(PagoTransaccionFiltros filtros )
	{
		List<PagoTransaccion> pagos =  buscarPagos(filtros);
		Set<Long> contratos = new HashSet<Long>(); 

		for(PagoTransaccion p : pagos)
		{
			contratos.add(p.getIdContrato());
		}
		for(Long idContrato:contratos)
		{
			TransaccionSAP transaccion = transaccionSAPDAO.buscarTransaccionSAPPorIDMes(idContrato, filtros.getMes());
			
			if (transaccion == null)
			{
				logger.debug("Genera Transaccion para idContato[{}] del mes[{}]",idContrato,filtros.getMes());
				ContratoDTO c = null;
				try {
					c = generalesBO.obtenContrato(idContrato);
				} catch (ResultMapException e) {
					logger.error("Error. {}", e);
				} catch (SQLException e) {
					logger.error("Error. {}", e);
				} catch (TransaccionException e) {
					logger.error("Error. {}", e);
				}
				Long costoMensual = pagoTransacionDAO.calculaCostoContratoMes(c.getIdContrato(), filtros.getMes());
				MercanciaI32DTO response  = llamaInterfazMercancia(c,costoMensual,filtros.getMes().replace("-", "."));
				if(response!= null)
				{
					generaPagoTransaccion(c,response,filtros);
				}else
				{
					logger.error("No fue posible guardar la transaccion pago de [{}] del mes",c.getIdContrato(),filtros.getMes());
				}
				
			}
		}
		
	}

	private void generaPagoTransaccion(ContratoDTO c, MercanciaI32DTO response,
			PagoTransaccionFiltros filtros) {
		SimpleDateFormat sfBD = new SimpleDateFormat("dd-MM-yyyy");
		if(OK.equals(response.getEstatusDDA()))
		{
			try {
				TransaccionSAP t = new TransaccionSAP();
				t.setIdContrato(c.getIdContrato());
				t.setIdSAP(c.getIdSap());
				t.setMes(sfBD.parse("01-"+filtros.getMes() ) );
				t.setAnnio(response.getrEjerDoc());
				t.setDocMaterial(response.getrDocMaterial());
				transaccionSAPDAO.insertarTransaccionSAP(t);
			} catch (ParseException e) {
				logger.error("No fue posible guardar la transaccion pago de [{}] del mes",c.getIdContrato(),filtros.getMes());
				logger.error("Error",e);
			}
		}
		else
		{
			logger.error("No fue posible guardar la transaccion pago de [{}] del mes",c.getIdContrato(),filtros.getMes());
		}
	}

	private MercanciaI32DTO llamaInterfazMercancia(ContratoDTO c, Long costoMensual , String mes) {
		DLARestClient client = dlaRestClientFactory.getClient(DLARestServices.ENTRADA_MERCANCIA);
		SimpleDateFormat sfRequest = new SimpleDateFormat("dd.MM.yyyy");
		
		DTEntradaMercancia request = new DTEntradaMercancia();
		request.setActividad("01");
		request.setFechaContab("01."+mes);
		request.setFechaDoc(sfRequest.format(new Date()));
		request.setNumeroPO(c.getIdSap());
		request.setTextoCab("Derechos de Autor");
		
		DTEntradaMercancia.Item item = new DTEntradaMercancia.Item();
		item.setCantidad(String.format("%.2f", costoMensual)  ); 
		item.setCentro("NT07");
		item.setClaseMov("101");
		item.setIndicadorMvto("B");
		item.setNumeroPO(c.getIdSap());
		item.setPosicionRefPO("00010");
		request.getItem().add(item);
		
		MercanciaI32DTO response = null;
		try {
			response = client.get(request, MercanciaI32DTO.class);
		} catch (SocketTimeoutException e) {
			logger.error("Error. {}", e);
		} catch (IOException e) {
			logger.error("Error. {}", e);
		} catch (TransaccionException e) {
			logger.error("Error. {}", e);
		}
		return response;
	}
	
	public Boolean tieneTransaccionesSAPPendientes(PagoTransaccionFiltros filtros)
	{
		filtros = acondicionaFiltros(filtros);
		List<TransaccionSAP> tx = transaccionSAPDAO.buscarTransaccionSAPPorEstudioMes(filtros.getIdEstudio(), filtros.getMes());
		
		Long contratosMes = pagoTransacionDAO.cuentaContratosCalculoCostoPorEstudioMes(filtros.getIdEstudio(), filtros.getMes());
		
		return contratosMes > tx.size();
	}

}
