package com.mx.dla.dda.contrato.titulo.rules;

import java.lang.reflect.InvocationTargetException;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.ibatis.exceptions.PersistenceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;

import com.mx.dla.dda.catalogos.daos.CatalogosDAO;
import com.mx.dla.dda.contrato.generales.daos.GeneralesDAO;
import com.mx.dla.dda.contrato.generales.dtos.ContratoDTO;
import com.mx.dla.dda.contrato.generales.dtos.FechasDTO;
import com.mx.dla.dda.contrato.titulo.daos.TituloDAO;
import com.mx.dla.dda.contrato.titulo.daos.TituloDmDAO;
import com.mx.dla.dda.contrato.titulo.dtos.Titulo;
import com.mx.dla.dda.contrato.titulo.exception.TituloException;
import com.mx.dla.global.bos.BaseBO;

@Component
public class TituloRules extends BaseBO{
	
	@Autowired
	private TituloDmDAO tituloDmDAO;
	@Autowired
	protected TituloDAO tituloDAO;
	@Autowired
	protected CatalogosDAO catalogosDAO;
	@Autowired
	protected GeneralesDAO generalesDAO;

	
	public void validaEntrada(Titulo titulo, ContratoDTO contrato) throws TituloException {
		validaTituloDuplicado(titulo.getIdTituloCnt(),  titulo.getIdLista(),titulo);
		ContratoDTO contratoValidacion = calculaFechasInicioFinValidacion(contrato);
		
		if( titulo.getPrecioAnual() == null  || "".equals(titulo.getPrecioAnual()))
		{
			if(titulo.getPagoCateg() == null )
				throw new TituloException("El título debe tener Precio o Categoría");
			if(titulo.getPagoCateg() != null && titulo.getPagoCateg().getValue() == null)
				throw new TituloException("El título debe tener Precio o Categoría");
		}
		if(  titulo.getPrecioAnual() != null && !"".equals(titulo.getPrecioAnual()))
		{
			if(titulo.getPagoCateg() != null && titulo.getPagoCateg().getValue() != null)
				throw new TituloException("El título no debe tener Precio y Categoría");
		}
		if(titulo.getFechaInicio() != null && titulo.getFechaFin() != null && titulo.getFechaFin().before(titulo.getFechaInicio()))
		{
			throw new TituloException("Fecha fin no puede ser anterior a Fecha inicio");
		}
		if(titulo.getFechaInicio() != null && 
				(contratoValidacion.getFechaInicio().after(titulo.getFechaInicio())  || contratoValidacion.getFechaFin().before(titulo.getFechaInicio()) )){
			     	throw new TituloException("Fecha de exhibición fuera de rango");
		}
		if(titulo.getNombreUnico() == null )
		{
			throw new TituloException("El título no cuenta con nombre único");
		}
		
		if(titulo.getIdBv() != null)
		   cuentaOcurrenciasEnOtrosContratos(titulo, contrato);		
	}
		
	public void cuentaOcurrenciasEnOtrosContratos(Titulo t, ContratoDTO contrato) throws TituloException
	{		
		logger.info("IBV {}", t.getIdBv());
		
		Long ocurrences = tituloDAO.buscarTitulosOtrosContratosXBV(t.getFechaInicio(), t.getFechaFin(), t.getIdBv(), t.getIdLista());
		
		if(ocurrences != null && ocurrences != 0)
		   throw new TituloException("El título ya se encuentra en otro contrato en el mismo id BroadView");
		
		logger.info("ocurrencias {}", ocurrences);
		
		ocurrences = 0l;
		ocurrences = tituloDAO.buscarTitulosListaXBV(t.getFechaInicio(), t.getFechaFin(), t.getIdBv(), t.getIdLista(), t.getIdTituloCnt());
		if(ocurrences != null && ocurrences != 0)
			throw new TituloException("El título ya se encuentra en la misma lista con el mismo id BroadView");
		
		logger.info("ocurrencias {}", ocurrences);				
	}
	
	protected void validaTituloDuplicado(Long idTitulo,Long idLista, Titulo titulo) throws TituloException
	{
		Titulo t = null;
		logger.debug("valido L:[{}] D:[{}] T:[{}] E:[{}]", new Object []{idLista, titulo.getDescTitulo(), titulo.getTemporada(),titulo.getEpisodio() });
		try{
			t  =  tituloDmDAO.buscarTitulosPorDescripcionEnLista(idLista, titulo.getDescTitulo(), titulo.getTemporada(),titulo.getEpisodio()  );
		} catch (PersistenceException e) {
			logger.info("Error" , e);
			throw new  TituloException("El título ya se encuentra en la lista"); 
        } catch (DataAccessException e) {
        	logger.info("Error" , e);
			throw new  TituloException("El título ya se encuentra en la lista"); 
        }
		if(t != null && idTitulo == null)
			throw new  TituloException("El título ya se encuentra en la lista"); 
		if(t!= null && Long.compare(t.getIdTituloCnt(), idTitulo) !=0)
			throw new  TituloException("El título ya se encuentra en la lista");
		
	}		
			
	protected ContratoDTO calculaFechasInicioFinValidacion(ContratoDTO contrato)
	{
		ContratoDTO cv=null;
		try {
			cv = (ContratoDTO) BeanUtils.cloneBean(contrato);
			FechasDTO fechas = generalesDAO.obtenerFechasMaximaMinimaDeContratosPorContratoOriginal(contrato.getIdContratoOriginal());
			cv.setFechaInicio(fechas.getInicio());
			cv.setFechaFin(fechas.getFin());
		} catch (IllegalAccessException | InstantiationException
				| InvocationTargetException | NoSuchMethodException e) {
			logger.error("Error ",e);
		}
		return cv;
	}
	
	public boolean verificarSerieNueva(Titulo titulo){
		   boolean valido = true;		   		   

		   if(tituloDAO.findCategoria(Long.parseLong(titulo.getCategoriaTit().getValue())) != 1)
			   valido = false;
		   logger.debug("serie categoria {}",valido);
		   if(valido && (!isNumeric(titulo.getEpisodio()) || Integer.parseInt(titulo.getEpisodio()) < 1))
			   valido = false;		   		  
		   logger.debug("serie episodio {}",valido);
		   if(valido && tituloDAO.findSerieSeason(titulo.getNombreUnico(), titulo.getTemporada()) > 1)
			   valido = false;
		   logger.debug("serie existe {}",valido);
		   return valido;
	}
	
	private static boolean isNumeric(String cadena){
		try {
			Integer.parseInt(cadena);
			return true;
		} catch (NumberFormatException nfe){
			return false;
		}
	}

}
