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

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
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.contrato.transaccion.exceptions.dtos.TransaccionException;
import com.mx.dla.dda.contrato.transaccion.terminos.daos.TerminosTransaccionDAO;
import com.mx.dla.dda.contrato.transaccion.terminos.dtos.PrecioRentaDTO;
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 TerminosPrecio extends BaseBO {

	@Autowired
	private TerminosTransaccionDAO dao;

	private List<TerminosPaisDTO> paises;
	private List<TerminosPaisDTO> formatos;
	private String[] releases;

	public PrecioRentaDTO obtenerPrecio(String[][] release, Long idContrato, String seccion) {
		PrecioRentaDTO precio = new PrecioRentaDTO();

		this.releases = new String[release.length];
		this.obtenerCatalogos(idContrato, seccion);

		precio.setPaises(this.paises);

		String[][] datos = null;

		for (int i = 0; i < release.length; i++)
			this.releases[i] = release[i][2];

		String formatosS[] = new String[formatos.size()];

		for (int i = 0; i < formatos.size(); i++)
			formatosS[i] = formatos.get(i).getDescripcion();

		Integer aplica = this.obtenerAplicaPrecios(idContrato, seccion);
		Integer pagoPpe = this.obtenerPagoPpe(idContrato, seccion);

		precio.setPagoPPE(pagoPpe == null ? 0 : pagoPpe);

		if (aplica != null && aplica.intValue() == 1) {
			List<TerminoPrecioDTO> precios = dao.obtenerPrecioPremier(idContrato, seccion);
			datos = this.obtenerDatosPrecio(formatosS, this.paises, this.releases, precios);
			precio.setAplica(1);
		} else {
			precio.setAplica(0);
			datos = this.obtenerDatosPrecio(formatosS, this.paises, this.releases, null);

		}
		precio.setPrecio(datos);

		return precio;
	}

	public String[][] obtenerDatosPrecio(String[] formatos, List<TerminosPaisDTO> paises, String[] variable,
			List<TerminoPrecioDTO> precios) {

		String[][] datos = new String[variable.length * formatos.length][(paises.size() * 2) + 2];
		int indFilaPais = 0;

		for (int i = 0; i < variable.length; i++) {
			for (int j = 0; j < formatos.length; j++) {
				datos[indFilaPais][0] = variable[i];
				datos[indFilaPais][1] = formatos[j];
				for (int k = 0; k < paises.size(); k++) {
					for (int x = 0; x < ListaUtilerias.safeList(precios).size(); x++) {
						TerminoPrecioDTO item = precios.get(x);
						if (item.getFormato().equals(formatos[j]) && item.getRelease().equals(variable[i])
								&& item.getIdPais().equals(paises.get(k).getIdPais())) {
							datos[indFilaPais][(k * 2) + 2] = item.getMoneda();
							datos[indFilaPais][(k * 2) + 3] = item.getDolar();
							break;
						}

					}
				}
				indFilaPais++;
			}

		}
		return datos;
	}

	public Integer obtenerAplicaPrecios(Long idContrato, String seccion) {
		return dao.obtenerAplicaPrecios(idContrato, seccion);
	}

	public Integer obtenerPagoPpe(Long idContrato, String seccion) {
		return dao.obtenerPagoPpe(idContrato, seccion);
	}

	public String[][] obtenerDatosPrecioMovSer(String[] formatos, List<TerminosPaisDTO> paises, String[] variable,
			Integer numeroReg, List<TerminoPrecioDTO> precios) {

		String[][] datosTemp = new String[variable.length * formatos.length][(paises.size() * 2) + 2];
		int indFilaPais = 0;

		for (int i = 0; i < variable.length; i++) {
			for (int j = 0; j < formatos.length; j++) {
				for (int k = 0; k < paises.size(); k++) {
					for (int x = 0; x < ListaUtilerias.safeList(precios).size(); x++) {
						TerminoPrecioDTO item = precios.get(x);
						if (item.getFormato().equals(formatos[j]) && item.getRelease().equals(variable[i])
								&& item.getIdPais().equals(paises.get(k).getIdPais())) {
							datosTemp[indFilaPais][0] = variable[i];
							datosTemp[indFilaPais][1] = formatos[j];
							datosTemp[indFilaPais][(k * 2) + 2] = item.getMoneda();
							datosTemp[indFilaPais][(k * 2) + 3] = item.getDolar();
							break;
						}

					}
				}
				indFilaPais++;
			}

		}

		List<String[]> lista = new ArrayList<String[]>(Arrays.asList(datosTemp));
		Iterator<String[]> it = lista.iterator();

		while (it.hasNext()) {
			int z = 0;
			String item[] = it.next();
			for (int y = 0; y < item.length; y++)
				if (item[y] == null || item[y].trim().equals(""))
					z++;

			if (item.length == z)
				it.remove();
		}

		String[][] datos = lista.toArray(new String[][] {});
		return datos;
	}

	public void guardarDatosPrecios(PrecioRentaDTO precioRenta, Long[] idRealeses, Long idContrato, String seccion)
			throws ResultMapException, SQLException, TransaccionException {
		try {

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

			List<TerminosPrecioDTO> precios = new ArrayList<TerminosPrecioDTO>();
			String datos[][] = precioRenta.getPrecio();

			logger.info("datos: {}", java.util.Arrays.deepToString(datos));
			logger.info("idRealeses: {}", java.util.Arrays.toString(idRealeses));
			logger.info("paises: {}", paises);
			logger.info("formatos: {}", formatos);
			logger.info("seccion: {} {}", seccion, idSeccion);

			int indiceFila = 0;
			for (int i = 0; i < idRealeses.length; i++) {
				for (int j = 0; j < this.formatos.size(); j++) {
					for (int k = 0; k < this.paises.size(); k++) {
						TerminosPrecioDTO precio = new TerminosPrecioDTO();

						String moneda = datos[indiceFila][(k * 2) + 2] == null ? null
								: datos[indiceFila][(k * 2) + 2].trim();
						String dolar = datos[indiceFila][(k * 2) + 3] == null ? null
								: datos[indiceFila][(k * 2) + 3].trim();
						precio = this.generarPrecioDTO(idRealeses[i], this.formatos.get(j).getIdPais(),
								this.paises.get(k).getIdPais(), moneda, dolar);
						precios.add(precio);
					}

					indiceFila++;
				}
			}

			dao.guardarValoresPrecio(precios, idContrato, seccion);

			for (TerminosPaisDTO pais : precioRenta.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);
		}
	}

	public PrecioRentaDTO obtenerDatosPreciosLibreria(Long idContrato, String seccion) {
		List<TerminoPrecioDTO> precios = dao.obtenerPrecioLibreria(idContrato);
		PrecioRentaDTO precio = new PrecioRentaDTO();

		this.formatos = dao.obtenerFormatos();

		Integer aplica = dao.obtenerAplicaPrecios(idContrato, seccion);
		Integer pagoPpe = dao.obtenerPagoPpe(idContrato, seccion);

		this.obtenerCatalogos(idContrato, seccion);

		precio.setPaises(this.paises);

		String[][] datos = new String[formatos.size()][(paises.size() * 2) + 1];

		if (precios == null || precios.isEmpty()) {
			for (int j = 0; j < formatos.size(); j++)
				datos[j][0] = formatos.get(j).getDescripcion();
		} 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++;
			}

		}

		precio.setAplica(aplica == null ? 1 : aplica);
		precio.setPagoPPE(pagoPpe == null ? 0 : pagoPpe);

		precio.setPrecio(datos);
		return precio;
	}

	public void guardarDatosPreciosLibreria(PrecioRentaDTO precioLibreria, Long idContrato, String seccion)
			throws ResultMapException, SQLException, TransaccionException {
		try {
			List<TerminosPrecioDTO> precios = new ArrayList<TerminosPrecioDTO>();

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

			String[][] datos = precioLibreria.getPrecio();

			int indiceColumna = 1;
			for (int k = 0; k < this.paises.size(); k++) {
				for (int j = 0; j < this.formatos.size(); j++) {
					TerminosPrecioDTO precio = new TerminosPrecioDTO();
					String moneda = datos[j][indiceColumna] == null ? null : datos[j][indiceColumna];
					String dolar = datos[j][indiceColumna + 1] == null ? null : datos[j][indiceColumna + 1];
					precio = this.generarPrecioDTO(null, this.formatos.get(j).getIdPais(),
							this.paises.get(k).getIdPais(), moneda, dolar);
					precios.add(precio);
				}
				indiceColumna = indiceColumna + 2;
			}
			dao.guardarValoresPrecioLibreria(precios, idContrato);

			for (TerminosPaisDTO pais : precioLibreria.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);
		}
	}

	public List<TerminosPrecioDTO> generarDatosMoviesSeries(String datos[][], Long idContrato,
			List<TerminosPaisDTO> categorias, List<TerminosPaisDTO> formatos, List<TerminosPaisDTO> paises)
			throws ResultMapException, SQLException, TransaccionException {
		List<TerminosPrecioDTO> precios = new ArrayList<TerminosPrecioDTO>();
		logger.debug(datos.toString());
		try {
			for (int i = 0; i < datos.length; i++) {
				int indiceColumna = 2;
				for (int k = 0; k < paises.size(); k++) //
				{
					TerminosPrecioDTO precio = new TerminosPrecioDTO();

					String moneda = datos[i][indiceColumna] == null ? null : datos[i][indiceColumna];
					String dolar = datos[i][indiceColumna + 1] == null ? null : datos[i][indiceColumna + 1];
					long idRelease = this.obtenerId(categorias, datos[i][0]);
					long idFormato = this.obtenerId(formatos, datos[i][1]);
					precio = this.generarPrecioDTO(idRelease, idFormato, paises.get(k).getIdPais(), moneda, dolar);
					precios.add(precio);
					indiceColumna = indiceColumna + 2;
				}
			}

		} 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 precios;
	}

	public Long obtenerId(List<TerminosPaisDTO> catalogo, String buscar) {
		Long id = null;
		for (int i = 0; i < catalogo.size(); i++) {
			if (catalogo.get(i).getDescripcion().equals(buscar))
				id = catalogo.get(i).getIdPais();
		}
		return id;
	}

	public TerminosPrecioDTO generarPrecioDTO(Long idRelease, Long idFormato, Long idPais, String moneda,
			String dolar) {
		TerminosPrecioDTO precio = new TerminosPrecioDTO();
		precio.setIdRelease(idRelease);
		precio.setIdFormato(idFormato);
		precio.setIdPais(idPais);
		precio.setDolar(dolar);
		precio.setMoneda(moneda);
		return precio;
	}

	public void obtenerCatalogos(Long idContrato, String 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.formatos = dao.obtenerFormatos();
		this.paises = paises;
	}

	public void eliminarPreciosPremium(Long idContrato, String seccion) {
		dao.eliminarValoresPrecio(idContrato, seccion);
	}

	public void eliminarPreciosLibreria(Long idContrato) {
		dao.eliminarValoresPrecioLibreria(idContrato);
	}

	public void eliminarPreciosMovies(Long idContrato) {
		dao.eliminarPrecioMovies(idContrato);
	}

	public void eliminarPreciosSeries(Long idContrato) {
		dao.eliminarPrecioSeries(idContrato);
	}

	public void eliminarPaisesImpuestoEstatus(Long idContrato, String seccion) {
		dao.eliminarPaisesImpuestoEstatus(idContrato, seccion);
	}

	public void actualizarPrecioAplica(Long idContrato, String seccion, Integer aplica) {
		dao.actualizarAplicaPrecios(idContrato, seccion, aplica);
	}

	public List<TerminosPaisDTO> getFormatos() {
		return formatos;
	}

	public List<TerminosPaisDTO> getPaises() {
		return paises;
	}

	public void actualizarPagoPpe(Long idContrato, String seccion, Integer pagoPpe) {
		dao.actualizarPagoPpe(idContrato, seccion, pagoPpe);
	}

}
