package com.mx.dla.dda.contrato.transaccion.fees.bos;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

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

import com.mx.dla.dda.catalogos.dtos.FormatoDTO;
import com.mx.dla.dda.contrato.transaccion.exceptions.dtos.TransaccionException;
import com.mx.dla.dda.contrato.transaccion.fees.daos.FeesTransaccionDAO;
import com.mx.dla.dda.contrato.transaccion.fees.dtos.FeesLibreriaDTO;
import com.mx.dla.dda.contrato.transaccion.fees.dtos.FeesTImpuestoDTO;
import com.mx.dla.dda.contrato.transaccion.fees.dtos.FeesTMinValoresDTO;
import com.mx.dla.dda.contrato.transaccion.fees.dtos.FeesTMinimoDTO;
import com.mx.dla.dda.contrato.transaccion.fees.dtos.FeesTPrecioDTO;
import com.mx.dla.dda.contrato.transaccion.fees.dtos.FeesTRevenueDTO;
import com.mx.dla.global.bos.BaseBO;

@Service
public class FeesLibreriaTransaccioBO extends BaseBO{

	@Autowired
	private FeesTransaccionDAO dao;
	
	@Autowired
	private FeesGuardarTransaccioBO comun;
	
	private List<FormatoDTO>       formatos;	
	private List<FeesTImpuestoDTO> paises;
	
	public FeesLibreriaDTO obtenerFeesLibreria(Long idContrato, String fechaInicio, String fechaFin) throws ResultMapException, SQLException, TransaccionException{
		FeesLibreriaDTO fees = new FeesLibreriaDTO();		
		try
		{
			fees =  this.obtenerCatalogos    (fees, idContrato);
			fees =  this.obtenerCatalogos    (fees, idContrato);
			fees =  this.obtenerDatosMinimos (fees, idContrato, fechaInicio, fechaFin);		
			fees =  this.obtenerDatosImpuesto(fees, idContrato);				
			fees =  this.obtenerDatosPrecios (fees,  idContrato);				
			fees =  this.obtenerDatosRevenue (fees,  idContrato);		
		} catch (PersistenceException e) {
			throw new TransaccionException("Se genero un error al guardar los datos.", e);
        } catch (DataAccessException e) {
        	throw new TransaccionException("Se genero un error al guardar los datos.", e);
        }								
		return fees;
	}
	
	public FeesLibreriaDTO obtenerDatosMinimos(FeesLibreriaDTO fees, Long idContrato, String fechaInicio, String fechaFin){									
		List<FeesTMinValoresDTO> valoresAnio = dao.obtenerMinimosAnioValoresLibreria(idContrato);
		List<FeesTMinimoDTO>     valoresCat  = dao.obtenerMinimosLibreria(idContrato);
		
		String [][] datos = FeesTransaccionUtileria.obtenerDatosMinimos(valoresAnio, valoresCat);
		String []   anios = FeesTransaccionUtileria.anios;
										
		if(valoresAnio != null && !valoresAnio.isEmpty())
		{		
			fees.setDatosMinAnio(datos);
			fees.setAniosMin(anios);			
		}
		else if(valoresCat != null  && !valoresCat.isEmpty())
		{						
			Long [] idsCategorias = new Long[valoresCat.size()];
			for(int i=0; i< valoresCat.size(); i++)
				idsCategorias[i] = valoresCat.get(i).getIdCategoria();
			
			fees.setIdCatMin(idsCategorias);	
			fees.setDatosMin(datos);
			fees.setAniosMin(anios);				
		}
		else
		{			
			int numAnios = comun.obtenerNumAnios(fechaInicio, fechaFin).intValue();
			
			String [][] datosMin  = new String[1][numAnios+3];
		    String [][] datosAnio = new String[1][numAnios];
            String anios1[]  = new String[numAnios]; 
            
            datosMin [0][0] = null;
            datosMin [0][1] = null;
            datosMin [0][2] = "MFTV/MFV";
            for(int i=0; i< numAnios; i++)
            {
            	anios1[i] = fechaInicio+"-"+fechaFin;
            	datosAnio[0][i] = null;
            	datosMin [0][i+3] = null;
            }
            	            	
			fees.setDatosMin(datosMin);
			fees.setDatosMinAnio(datosAnio);
			fees.setAniosMin(anios1);			
		}											
		return fees;		
	}
	
	public FeesLibreriaDTO obtenerDatosImpuesto(FeesLibreriaDTO fees, Long idContrato){								
		List<FeesTImpuestoDTO> impuestos = dao.obtenerImpuestosLibreria(idContrato);		
		String [][] datos  = FeesTransaccionUtileria.obtenerDatosImpuesto(impuestos, this.paises);							
		fees.setDatosImpuestos(datos);				
		return fees;					
	}
	
	public FeesLibreriaDTO obtenerDatosPrecios(FeesLibreriaDTO fees, Long idContrato){						
		List<FeesTPrecioDTO> precios = dao.obtenerPrecioLibreria(idContrato);
		String [][] datos = new String[fees.getFormatos().length][(paises.size()*2)+1];
		
		if(precios == null || precios.isEmpty())
		{															
			for(int j=0; j<fees.getFormatos().length; j++)														
				datos[j][0] = fees.getFormatos()[j];												
			fees.setDatosPrecio(datos);
		}
		else
		{														
			Long pais = 0l;
			int indFilaPais = 0;
			int indColPais  = 0;
			
			for(int i=0; i<precios.size(); i++)
			{
				if(pais.longValue() != precios.get(i).getIdPais().longValue())
				{
					for(int j=0; j<paises.size(); j++)
					{
						if(precios.get(i).getIdPais().longValue() == paises.get(j).getIdPais().longValue())
						{
							pais = paises.get(j).getIdPais();
							indColPais = j;
							break;
						}						  
					}	
					indFilaPais = 0;
				}
								
				datos[indFilaPais][0] = precios.get(i).getFormato();
				datos[indFilaPais][(indColPais*2)+1] = precios.get(i).getMoneda();
				datos[indFilaPais][(indColPais*2)+2] = precios.get(i).getDolar();
				indFilaPais++;
			}
			fees.setDatosPrecio(datos);			
		}						        				
		return fees;
	}
	
	public FeesLibreriaDTO obtenerDatosRevenue(FeesLibreriaDTO fees, Long idContrato){
						
		List<FeesTRevenueDTO> box = dao.obtenerRevenueBoxLibreria(idContrato);
		logger.debug(box.toString());
		FeesTRevenueDTO global    = dao.obtenerRevenueGlobalLiberia(idContrato);
		
		String [][]  datos = {{null, null}};
		String [][] datosB = { {null, null, null, null, null} };
		
		if(global == null && (box == null || box.isEmpty()) )
		{
			fees.setDatosRevenue(datos);
			fees.setDatosRevenueBox(datosB);			
			fees.setRevenueBox(false);
			fees.setRevenueGlobal(false);
		} 
		else if(global != null)
		{
			datos[0][0] = global.getDdaPto();
			datos[0][1] = global.getEstudioPto();
			fees.setDatosRevenue(datos);
			fees.setDatosRevenueBox(datosB);			
			fees.setRevenueBox(false);
			fees.setRevenueGlobal(true);
		}
		else if(box != null && !box.isEmpty())
		{
			datosB = new String [box.size()][5];
			
			for(int i=0; i<box.size(); i++)
			{
				datosB[i][0] = box.get(i).getDesde();
				datosB[i][1] = box.get(i).getHasta();
				datosB[i][2] = box.get(i).getRelease();
				datosB[i][3] = box.get(i).getDdaPto();
				datosB[i][4] = box.get(i).getEstudioPto();
			}
			
			fees.setDatosRevenue(datos);
			fees.setDatosRevenueBox(datosB);		
			fees.setRevenueBox(true);
			fees.setRevenueGlobal(false);	
		}
				
		return fees;
	}
	
	public void guardarFeesLibreria(Long idContrato, String fechaInicio, String fechaFin, FeesLibreriaDTO fees) throws ResultMapException, SQLException, TransaccionException{		
		
		try
		{								
			//Se borra datos de revenue box, por dependencia con minimos
			dao.eliminarRevBoxLibreria(idContrato);
			dao.eliminarRevenueGlobal(idContrato);
			
			//se borran los datos eliminados en pantalla minimos
			if(fees.getIdCatEli() != null && fees.getIdCatEli().length > 0)			
			   this.eliminarCategoriasMinimos(fees.getIdCatEli());
			
			String datosMin[][] = fees.getIdCatMin() != null && fees.getDatosMin() != null ? fees.getDatosMin() : fees.getDatosMinAnio();
			boolean anio        = fees.getDatosMin() == null && fees.getDatosMinAnio() != null ? true: false;
			boolean categoria   = fees.getDatosMin() != null && fees.getDatosMinAnio() == null ? true: false;			
															
			this.guardarDatosMinimos (datosMin, fees.getAniosMin(), fees.getIdCatMin(), categoria, anio, idContrato);						
			this.guardarDatosImpuesto(fees.getDatosImpuestos(), idContrato);
			this.guardarDatosPrecios (fees.getDatosPrecio()   , idContrato);
			this.guardarDatosRevenue (fees, idContrato);
												
		} catch (PersistenceException e) {
			throw new TransaccionException("Se genero un error al guardar los datos.", e);
        } catch (DataAccessException e) {
        	throw new TransaccionException("Se genero un error al guardar los datos.", e);
        }							
	}

	public void eliminarCategoriasMinimos(Long[] ids){		
		 dao.eliminarCategValMinimos(ids);
		 dao.eliminarCategMinimos   (ids);		 
	}
	
	public boolean verificarCategoriasMinimos(Long id){
		   return true;
	}
	public void guardarDatosMinimos(String datos[][], String anios[], Long [] idCat, Boolean isCategoria, Boolean isAnnio, Long idContrato) throws ResultMapException, SQLException, TransaccionException, ResultMapException, SQLException{							
	    comun.guardarDatosMinimos(datos, anios, idCat, isCategoria, isAnnio, idContrato, "RL");
	}
	
	public void guardarDatosImpuesto(String datos[][], Long idContrato) throws TransaccionException, ResultMapException, SQLException{							
	    comun.guardarDatosImpuesto(datos, idContrato, "RL", this.paises);
	}
	
	public void guardarDatosPrecios(String datos[][], Long idContrato) throws ResultMapException, SQLException, TransaccionException{							
		try
		{	
			List<FeesTPrecioDTO> precios = new ArrayList<FeesTPrecioDTO>();
			
			dao.eliminarValoresPrecioLibreria(idContrato);						
			this.formatos = dao.getFormatos();			
			
		    int indiceColumna = 1;		    	    
		    for(int k=0; k< this.paises.size(); k++) 
		    {		    				    	
			   	for(int j=0; j< this.formatos.size(); j++)
			   	{		
			   		FeesTPrecioDTO precio = new FeesTPrecioDTO();			    					    		
			   		String moneda =  datos[j][indiceColumna   ] == null ? null : datos[j][indiceColumna   ]; 
			   		String dolar  =  datos[j][indiceColumna +1] == null ? null : datos[j][indiceColumna +1];
			   		precio = FeesTransaccionUtileria.generearFeesTPrecioDTO(null, this.formatos.get(j).getIdFormato(), this.paises.get(k).getIdPais(), moneda, dolar);			    		
			   		precios.add(precio);			   		
			   	}
			   	indiceColumna = indiceColumna +2;			   	
		    }		    								    
		    dao.guardarValoresPrecioLibreria(precios, idContrato);
		} catch (PersistenceException e) {
			throw new TransaccionException("Se genero un error al guardar los datos.", e);
        } catch (DataAccessException e) {
        	throw new TransaccionException("Se genero un error al guardar los datos.", e);
        }	 				
	}
	
	public void guardarDatosRevenue(FeesLibreriaDTO fees, Long idContrato) throws ResultMapException, SQLException, TransaccionException{							
		try
		{
			String datos[][]    = null;
			boolean anio        = fees.getDatosMin() == null && fees.getDatosMinAnio() != null ? true: false;
			boolean categoria   = fees.getDatosMin() != null && fees.getDatosMinAnio() == null ? true: false;
			List<FeesTMinimoDTO>  categorias  = dao.obtenerMinimosLibreriaRevenue(idContrato);
			
			if(fees.isRevenueBox())
			{
				List<FeesTRevenueDTO> valores = new ArrayList<FeesTRevenueDTO>();
				datos = fees.getDatosRevenueBox();
					
				if(categoria)
				{
					for(int i=0; i< datos.length; i++)
					{		
						boolean  encontrado = false;
						for(int j=0; j< categorias.size(); j++)
						{   
							if( datos[i][2].compareTo(categorias.get(j).getCategoria()) == 0)
							{
								//Se inserta los valores en revenue
								encontrado = true;
								valores.add(FeesTransaccionUtileria.generearFeesTRevenueDTO(categorias.get(j).getIdCategoria(), datos[i][3], datos[i][4]));
							}							
						}
					
						if(!encontrado)
						{
							//Se inserta la categoria en minimos con revenue 1 y los valores en revenue
							FeesTMinimoDTO catMin = FeesTransaccionUtileria.generearMinimoDTO(datos[i][0], datos[i][1], datos[i][2], "RL", 1, null);	    			
			    			dao.guardarCatMinTrans(catMin, idContrato);
			    			valores.add(FeesTransaccionUtileria.generearFeesTRevenueDTO(catMin.getIdCategoria(), datos[i][3], datos[i][4]));
						}
					}						
				}				
				else if(anio)				
				{					
					//Se inserta la categoria en minimos con revenue 1 y los valores en revenue
					for(int i=0; i< datos.length; i++)
					{		
						FeesTMinimoDTO catMin = FeesTransaccionUtileria.generearMinimoDTO(datos[i][0], datos[i][1], datos[i][2], "RL", 1, null);	    			
		    			dao.guardarCatMinTrans(catMin, idContrato);
		    			valores.add(FeesTransaccionUtileria.generearFeesTRevenueDTO(catMin.getIdCategoria(), datos[i][3], datos[i][4]));
					}												
				}
				
				dao.guardarRevenueBox(valores);
			}
			else if(fees.isRevenueGlobal())
			{
				datos = fees.getDatosRevenue();				
				dao.guardarRevenueGlobal(idContrato, FeesTransaccionUtileria.generearFeesTRevenueDTO(null, datos[0][0], datos[0][1]));
			}
			
		} catch (PersistenceException e) {
			throw new TransaccionException("Se genero un error al guardar los datos.", e);
        } catch (DataAccessException e) {
        	throw new TransaccionException("Se genero un error al guardar los datos.", e);
        }	 				
	}
	
	public FeesLibreriaDTO obtenerCatalogos(FeesLibreriaDTO fees, Long idContrato){
		
		List<String> formatosL = dao.obtenerFormatos();
		String formatos [] = new String[formatosL.size()];
		
		for(int i=0; i<formatosL.size(); i++)
			formatos[i] = formatosL.get(i);
			
		fees.setFormatos(formatos);				
		
		paises = dao.obtenerPaisesPremier(idContrato);		
		String paisesStr[] = new String[paises.size()];		
									
		for(int i=0; i< paises.size();i++)
			paisesStr[i] = paises.get(i).getPais();		
		fees.setPaises(paisesStr);
		
		return fees;
	}	
}