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.apache.ibatis.executor.result.ResultMapException;
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.MoviesDTO;
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.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 TerminosMovie extends BaseBO {

	@Autowired
	private TerminosMinimos minimos;

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

	@Autowired
	private TerminosRevenue revenue;

	@Autowired
	private TerminosTransaccionDAO dao;

	@Autowired
	private TerminosExcepciones excepciones;

	private List<TerminosPaisDTO> paises;
	private List<TerminosPaisDTO> categorias;
	private List<TerminosPaisDTO> formatos;

	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = TransaccionException.class)
	public MoviesDTO obtenerMovies(Long idContrato) throws ResultMapException, SQLException, TransaccionException {
		MoviesDTO movies = new MoviesDTO();

		try {
			MinimoGarantizadoDTO minimo = minimos.obtenerMinimos(idContrato, SeccionesTerminos.VentaMovies.getDesc());
			movies = this.obtenerDatosDTOMovies(movies, idContrato, SeccionesTerminos.VentaMovies.getDesc());
			RevenueBoxGloDTO rev = revenue.obtenerRevenueMovies(idContrato, SeccionesTerminos.VentaMovies.getDesc(),
					movies.getPrecio().getPrecio());
			ExcepcionesSeccionDTO excepcionesDTO = excepciones.obtenerExcepciones(idContrato,
					SeccionesTerminos.VentaMovies.getDesc());

			movies.setMinimos(minimo);
			movies.setRevenue(rev);
			movies.setExcepciones(excepcionesDTO);

		} catch (PersistenceException e) {
            throw new TransaccionException("Error al cargar los datos.", e);
        } catch (DataAccessException e) {
            throw new TransaccionException("Error al cargar los datos", e);
        }
		return movies;
	}

	public MoviesDTO obtenerDatosDTOMovies(MoviesDTO terminos, Long idContrato, String seccion) {
		this.formatos = dao.obtenerFormatos();
		this.categorias = dao.obtenerTiers();

		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.obtenerPrecioMovies(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 guardarPremium(MoviesDTO p, Long idContrato)
			throws JsonParseException, JsonMappingException, IOException, TransaccionException {

		try {
			logger.debug(p.toString());
			revenue.eliminarRevenueBoxMovies(idContrato);
			revenue.elimnarRevenueGlobal(idContrato, SeccionesTerminos.VentaMovies.getDesc());
			precio.eliminarPaisesImpuestoEstatus(idContrato, SeccionesTerminos.VentaMovies.getDesc());
			precio.eliminarPreciosMovies(idContrato);
			excepciones.eliminarExcepcion(idContrato, SeccionesTerminos.VentaMovies.getDesc());

			minimos.guardarMinimos(p.getMinimos().getMinimosCateg(), p.getMinimos().getMinimosAnio(),
					p.getMinimos().getAnios(), p.getMinimos().getTipoMin(), SeccionesTerminos.VentaMovies.getDesc(),
					idContrato);

			precio.actualizarPrecioAplica(idContrato, SeccionesTerminos.VentaMovies.getDesc(),
					p.getPrecio().getAplica());
			precio.actualizarPagoPpe(idContrato, SeccionesTerminos.VentaMovies.getDesc(), p.getPrecio().getPagoPPE());

			boolean aplicaPrecio = p.getPrecio().getAplica().intValue() == 1;
			boolean isGlobalRevenue = p.getRevenue().isRevenueGlobal();
			boolean isBoxOfficeRevenue = p.getRevenue().isRevenueBox();

			if (aplicaPrecio)
				this.guardarDatosPreciosMovies(p.getPrecio(), idContrato, this.categorias, this.formatos, this.paises,
						SeccionesTerminos.VentaMovies.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.guardarRevenueMovies(idContrato, SeccionesTerminos.VentaMovies.getDesc(), this.categorias,
						p.getRevenue());

			excepciones.guardarExcepciones(idContrato, SeccionesTerminos.VentaMovies.getDesc(), p.getExcepciones());

		} catch (PersistenceException e) {
            throw new TransaccionException("Error al cargar los datos.", e);
        } catch (DataAccessException e) {
            throw new TransaccionException("Error al cargar los datos", e);
        } catch (SQLException e) {
        	throw new TransaccionException("Error al cargar los datos", e);
		}

	}

	public void guardarDatosPreciosMovies(PrecioRentaDTO precioMovies, Long idContrato,
			List<TerminosPaisDTO> categorias, List<TerminosPaisDTO> formatos, List<TerminosPaisDTO> paises,
			String seccion) throws ResultMapException, SQLException, TransaccionException {
		try {
			List<TerminosPrecioDTO> precios = new ArrayList<TerminosPrecioDTO>();
			String datos[][] = precioMovies.getPrecio();

			Long idSeccion = dao.obtenerIdSeccion(idContrato, seccion);

			precios = precio.generarDatosMoviesSeries(datos, idContrato, categorias, formatos, paises);
			dao.guardarValoresPrecioMovies(precios, idContrato);

			for (TerminosPaisDTO pais : precioMovies.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("Error al cargar los datos.", e);
        } catch (DataAccessException e) {
            throw new TransaccionException("Error al cargar los datos", e);
        }
	}

}
