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

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

import org.apache.ibatis.exceptions.PersistenceException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.mx.dla.dda.contrato.transaccion.exceptions.dtos.TransaccionException;
import com.mx.dla.dda.contrato.transaccion.terminos.daos.TerminosTransaccionDAO;
import com.mx.dla.dda.contrato.transaccion.terminos.dtos.ExcepcionesSeccionDTO;
import com.mx.dla.dda.contrato.transaccion.terminos.dtos.MinimoGarantizadoDTO;
import com.mx.dla.dda.contrato.transaccion.terminos.dtos.PrecioRentaDTO;
import com.mx.dla.dda.contrato.transaccion.terminos.dtos.RevenueBoxGloDTO;
import com.mx.dla.dda.contrato.transaccion.terminos.dtos.SeccionesTerminos;
import com.mx.dla.dda.contrato.transaccion.terminos.dtos.SeriesDTO;
import com.mx.dla.dda.contrato.transaccion.terminos.dtos.TerminoPrecioDTO;
import com.mx.dla.dda.contrato.transaccion.terminos.dtos.TerminosAuxiliarDTO;
import com.mx.dla.dda.contrato.transaccion.terminos.dtos.TerminosPaisDTO;
import com.mx.dla.dda.contrato.transaccion.terminos.dtos.TerminosPrecioDTO;
import com.mx.dla.dda.general.utilerias.ListaUtilerias;
import com.mx.dla.global.bos.BaseBO;

@Service
public class TerminosSerie extends BaseBO{

	
	@Autowired
	private TerminosMinimos minimos;
		
	@Autowired
	private TerminosRevenue revenue;
	
	@Autowired
	private TerminosTransaccionDAO dao;

	@Autowired
	@Qualifier("precioMovies")
	private TerminosPrecio precio;

	private List<TerminosPaisDTO>   paises;
	private List<TerminosPaisDTO>   categorias;
	private List<TerminosPaisDTO>   formatos;
	
	@Autowired
	private TerminosExcepciones excepciones;

	
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public SeriesDTO obtenerSerie(Long idContrato)throws TransaccionException{
		SeriesDTO movies = new SeriesDTO();
		
		try
		{		           
			MinimoGarantizadoDTO minimo = minimos.obtenerMinimos(idContrato, SeccionesTerminos.VentaSeries.getDesc());			
                                 movies = this.obtenerDatosDTOSeries(movies, idContrato, SeccionesTerminos.VentaSeries.getDesc());           
            RevenueBoxGloDTO        rev = revenue.obtenerRevenueSeries(idContrato, SeccionesTerminos.VentaSeries.getDesc(), movies.getPrecio().getPrecio());
			ExcepcionesSeccionDTO excepcionesDTO = excepciones.obtenerExcepciones(idContrato, SeccionesTerminos.VentaSeries.getDesc());

            
            movies.setMinimos(minimo);
            movies.setRevenue(rev);
			movies.setExcepciones(excepcionesDTO);
	
								
		} catch (PersistenceException e) {
			new TransaccionException("Error al obtener terminos movies.", e);
		} catch (DataAccessException e) {
			new TransaccionException("Error al obtener terminos movies.", e);
		}							
		return movies;		
	}	
	
	public SeriesDTO obtenerDatosDTOSeries(SeriesDTO terminos, Long idContrato, String seccion){												
		this.formatos   = dao.obtenerFormatos();											
		this.categorias = dao.obtenerCatSeries();
		
		Integer aplica = dao.obtenerAplicaPrecios(idContrato, seccion);
		Integer pagoPpe = dao.obtenerPagoPpe(idContrato, seccion);
		
		List<TerminosPaisDTO> paises = dao.obtenerPaises(idContrato);
		List<TerminosPaisDTO> impuestoEstatus = dao.obtenerPaisesImpuestoEstatus(idContrato, seccion);

		for (TerminosPaisDTO pais : paises) {
			if (pais.getAplicaImpuesto() == null)
				pais.setAplicaImpuesto(0);
			for (TerminosPaisDTO impuesto : impuestoEstatus)
				if (pais.getIdPais().equals(impuesto.getIdPais()))
					pais.setAplicaImpuesto(impuesto.getAplicaImpuesto());
		}
		
		this.paises   = paises;	
		
		PrecioRentaDTO price = new PrecioRentaDTO();
		String [][] datos = ListaUtilerias.safeArray(null, String.class, 1, (paises.size() * 2) + 2);

				
		String formatosS[] = new String[this.formatos.size()];
		for(int i=0; i<this.formatos.size(); i++)
			formatosS[i] = this.formatos.get(i).getDescripcion();
				
		String categoriasS[] = new String[this.categorias.size()];
		for(int i=0; i<this.categorias.size(); i++)
			categoriasS[i] = this.categorias.get(i).getDescripcion();
		
		List<TerminoPrecioDTO> precios = dao.obtenerPrecioSeries(idContrato);
		
		if(precios != null && !precios.isEmpty())
		   datos = precio.obtenerDatosPrecioMovSer(formatosS, this.paises, categoriasS, null, precios);
		
		price.setPrecio(datos);
		
		price.setAplica(aplica == null ? 1 : aplica);
		price.setPagoPPE(pagoPpe == null ? 0 : pagoPpe);
		
		price.setPaises(this.paises);
		
		
		terminos.setPrecio(price);
						
		terminos.setCategorias(categoriasS);
		return terminos;
	}
	
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = TransaccionException.class)
	public void guardarSerie(SeriesDTO p, Long idContrato) throws JsonParseException, JsonMappingException, IOException, TransaccionException{
		
		try
		{
			logger.debug(p.toString());
			revenue.eliminarRevenueBoxSeries(idContrato);			
			revenue.elimnarRevenueGlobal(idContrato, SeccionesTerminos.VentaSeries.getDesc());
			precio.eliminarPaisesImpuestoEstatus(idContrato, SeccionesTerminos.VentaSeries.getDesc());
			precio.eliminarPreciosSeries(idContrato); 
			excepciones.eliminarExcepcion(idContrato, SeccionesTerminos.VentaSeries.getDesc());
						
			minimos.guardarMinimos(p.getMinimos().getMinimosCateg(), p.getMinimos().getMinimosAnio(), p.getMinimos().getAnios(), p.getMinimos().getTipoMin(), SeccionesTerminos.VentaSeries.getDesc(), idContrato);											
			
			precio.actualizarPrecioAplica(idContrato, SeccionesTerminos.VentaSeries.getDesc(), p.getPrecio().getAplica());
			precio.actualizarPagoPpe(idContrato, SeccionesTerminos.VentaSeries.getDesc(), p.getPrecio().getPagoPPE());

			boolean aplicaPrecio = p.getPrecio().getAplica().intValue() == 1;
			boolean isGlobalRevenue = p.getRevenue().isRevenueGlobal();
			boolean isBoxOfficeRevenue = p.getRevenue().isRevenueBox();
			
			if(aplicaPrecio)
			   this.guardarDatosPreciosSeries(p.getPrecio(), idContrato, this.categorias, this.formatos, this.paises, SeccionesTerminos.VentaSeries.getDesc());						
			
			Long categoriasS[] = new Long[this.categorias.size()];
			for(int i=0; i<this.categorias.size(); i++)
				categoriasS[i] = this.categorias.get(i).getIdPais();
			
			if((isBoxOfficeRevenue && aplicaPrecio) || isGlobalRevenue)
			   revenue.guardarRevenueSeries(idContrato, SeccionesTerminos.VentaSeries.getDesc(), this.categorias, p.getRevenue());
			
			excepciones.guardarExcepciones(idContrato, SeccionesTerminos.VentaSeries.getDesc(), p.getExcepciones());
							
		} catch (PersistenceException e) {
			new TransaccionException("Error al obtener terminos premium.", e);
		} catch (DataAccessException e) {
			new TransaccionException("Error al obtener terminos premium.", e);
		}
		
	}
	
	public void guardarDatosPreciosSeries(PrecioRentaDTO precioSeries, Long idContrato, List<TerminosPaisDTO> categorias, List<TerminosPaisDTO> formatos, List<TerminosPaisDTO> paises, String seccion) throws TransaccionException{							
		try
		{																	

			List<TerminosPrecioDTO> precios = new ArrayList<TerminosPrecioDTO>();
			
			String datos [][] = precioSeries.getPrecio();
			Long idSeccion = dao.obtenerIdSeccion(idContrato, seccion);

			
			precios = precio.generarDatosMoviesSeries(datos, idContrato, categorias, formatos, paises);							    
		    dao.guardarValoresPrecioSeries(precios, idContrato);
		    
			for (TerminosPaisDTO pais : precioSeries.getPaises()) {
				TerminosAuxiliarDTO impuesto = new TerminosAuxiliarDTO();
				impuesto.setIdOpcionalA(idContrato);
				impuesto.setIdOpcionalB(pais.getIdPais());
				impuesto.setIdOpcionalC(idSeccion);
				impuesto.setValorA(pais.getAplicaImpuesto());
				dao.guardaPaisesImpuestoEstatus(impuesto);
			}
		} 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);
		} catch (SQLException e) {
			throw new TransaccionException("Se genero un error al guardar los datos.", e);
		} 				
	}

}
