package com.mx.dla.dda.reporte.DatosContrato.bos;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.SocketTimeoutException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;

import com.mx.dla.dda.contrato.transaccion.exceptions.dtos.TransaccionException;
import com.mx.dla.dda.excelMapper.bos.ExcelMapperTransform;
import com.mx.dla.dda.excelMapper.constants.ExcelMapperDataType;
import com.mx.dla.dda.excelMapper.context.ExcelMapperContext;
import com.mx.dla.dda.excelMapper.dtos.ExcelMapper;
import com.mx.dla.dda.excelMapper.dtos.ExcelRule;
import com.mx.dla.dda.excelMapper.exceptions.ExcelMapperException;
import com.mx.dla.dda.general.constants.MesesAnio;
import com.mx.dla.dda.general.utilerias.FechaUtilerias;
import com.mx.dla.dda.reporte.amortizacion.baseActivos.bos.BaseActivosBO;
import com.mx.dla.dda.reporte.cpview.daos.ReporteCostPerViewDAO;
import com.mx.dla.dda.reporte.cpview.dtos.CargaVisualizacionesDetalleDTO;
import com.mx.dla.dda.reporte.cpview.dtos.CargaVisualizacionesPrincipalDTO;
import com.mx.dla.dda.reporte.cpview.dtos.CostPerViewEstudioAnualDatosDTO;
import com.mx.dla.dda.reporte.cpview.dtos.CostPerViewEstudioMensualDatosDTO;
import com.mx.dla.dda.reporte.cpview.dtos.ParamCargaTitulosVSDTO;
import com.mx.dla.dda.reporte.cpview.dtos.ReporteCostPerViewVistaDTO;
import com.mx.dla.dda.reporte.cpview.dtos.ResponseCargaTitulosVSDTO;
import com.mx.dla.dda.reporte.cpview.dtos.VisualizacionesCostPerViewVistaDTO;
import com.mx.dla.dda.reporte.cpview.exception.ReportCostPerViewException;
import com.mx.dla.dda.reporte.datosContrato.daos.ReporteDatosContratoDAO;
import com.mx.dla.dda.reporte.datosContrato.dtos.DatosContratoDTO;
import com.mx.dla.dda.reporte.ws.dtos.ResponseGeneraReporteDTO;
import com.mx.dla.dda.restClient.bos.DLARestClient;
import com.mx.dla.dda.restClient.bos.DLARestClientFactory;
import com.mx.dla.dda.restClient.constants.DLARestServices;
import com.mx.dla.global.bos.BaseBO;
import com.mx.dla.global.bos.CustomResourceLoader;

@Service
public class ReporteDatosContratosBO extends BaseBO {

	@Autowired
	private ReporteDatosContratoDAO reporteDatosContratoDAO;

	@Autowired
	protected ExcelMapperTransform excelMapperTransform;

	@Autowired
	private ExcelMapperContext excelMapperContext;

	@Autowired
	private DLARestClientFactory dlaRestClientFactory;

	@Value("${uri.file.carga.visualizaciones}")
	private String uriCarga;

	@Autowired
	private CustomResourceLoader customResourceLoader;

	@Autowired
	private BaseActivosBO baseActivosBO;

	@Value("${uri.file.reporte.baseActivosSQL}")
	protected String uriSQL;

	@Value("${uri.file.reporte.txtcpv}")
	protected String uriTXT;

	public String[][] obtenReporteMensualTablaOrigial(Long anio, Long mes, Long idEstudio, String nombreUnico,
			String temporada, Boolean consulta) throws IllegalArgumentException, IllegalAccessException {

		String[][] tabla = null;
		int tamanio = (3 * (mes.intValue())) + 1;

		Comparator<CostPerViewEstudioMensualDatosDTO> comparator = new Comparator<CostPerViewEstudioMensualDatosDTO>() {
			public int compare(CostPerViewEstudioMensualDatosDTO o1, CostPerViewEstudioMensualDatosDTO o2) {
				return o1.getEstudio().compareTo(o2.getEstudio());
			}
		};

		List<CostPerViewEstudioMensualDatosDTO> datos = null;
		List<CostPerViewEstudioMensualDatosDTO> diciembre = null;

		if (idEstudio == null) {

			if (consulta) {
				datos = reporteDatosContratoDAO.obtenerCostPerViewMensualDatosEstudioNivel(mes, anio);
				diciembre = reporteDatosContratoDAO.obtenerCostPerViewDiciembreDatosEstudioNivel(anio - 1);
			} else {
				diciembre = reporteDatosContratoDAO.obtenerCostPerViewDiciembreDatosTituloNivel(anio - 1, idEstudio,
						nombreUnico, temporada);
			}
		} else {
			diciembre = reporteDatosContratoDAO.obtenerCostPerViewDiciembreDatosTituloNivel(anio - 1, idEstudio,
					nombreUnico, temporada);
		}

		boolean dicFlag = diciembre != null && !diciembre.isEmpty();

		Integer amorIdxEnero = 0;
		Integer visIdxEnero = 1;
		Integer cpvIdxEnero = 2;
		Integer amorIdxDiciembre = 34;

		if (datos != null && !datos.isEmpty()) {

			if (dicFlag) {
				Collections.sort(diciembre, comparator);
			}
			for (CostPerViewEstudioMensualDatosDTO item : datos) {
				String[] fila = item.getFieldsAsRow();
				String[] tfila = Arrays.copyOfRange(fila, 0, 1);
				String[] sfila = Arrays.copyOfRange(fila, 1, tamanio);
				String[] afila = Arrays.copyOfRange(fila, fila.length - 4, fila.length);
				if (dicFlag) {
					int i = Collections.binarySearch(diciembre, item, comparator);
					if (i >= 0) {
						CostPerViewEstudioMensualDatosDTO found = diciembre.get(i);
						String[] arowDic = found.getFieldsAsRow();
						if (sfila[visIdxEnero] == null || new Double(sfila[visIdxEnero]) == 0) {
							sfila[cpvIdxEnero] = "0.0";
						} else if (sfila[amorIdxEnero] == null || new Double(sfila[amorIdxEnero]) == 0) {
							if (arowDic[amorIdxDiciembre] != null) {
								sfila[cpvIdxEnero] = new Double(
										new Double(arowDic[amorIdxDiciembre]) / new Double(sfila[visIdxEnero]))
										.toString();
							}
						}
					}
				}
				Double sumatoriaAmor = 0.0;
				Double sumatoriaVis = 0.0;

				for (int i = 0; i < sfila.length; i++) {
					if (i % 3 == 0) {
						sumatoriaAmor = sumatoriaAmor + new Double(sfila[i]);
					}
					if (i % 3 == 1) {
						sumatoriaVis = sumatoriaVis + new Double(sfila[i]);
					}
				}

				afila[0] = String.format("%.2f", sumatoriaAmor);
				afila[1] = String.format("%.2f", sumatoriaVis);

				Double cpv = sumatoriaAmor / sumatoriaVis;

				if (!cpv.isInfinite()) {
					afila[2] = String.format("%.2f", cpv);
				} else {
					afila[2] = "";
				}
				String[] row = ArrayUtils.addAll(ArrayUtils.addAll(tfila, sfila), afila);
				if (tabla == null) {
					tabla = new String[1][row.length];
				} else {
					tabla = Arrays.copyOf(tabla, tabla.length + 1);
				}

				tabla[tabla.length - 1] = row;
			}
		}
		return tabla;
	}

	public String[][] obtenReporteMensualTabla(Long anio, Long mes, Long idEstudio, Long contrato, Long nombreUnico,
			Long temporada, Boolean consulta, String titulos, String amortizacion, String dgenerales,
			String tcomerciales) throws IllegalArgumentException, IllegalAccessException {

		String[][] tabla = null;
		List<DatosContratoDTO> datos2 = null;
		String pivot_date = "";
		String smes = "";

		if (amortizacion.equals("YES")) {
			Long fanio = anio - 1;

			for (int i = 1; i <= 12; i++) {
				if (i > 1 && mes == 1) {
					fanio = anio;
				}
				if (mes < 10) {
					smes = "0" + mes;
				} else {
					smes = mes.toString();
				}
				if (i == 12) {
					pivot_date = pivot_date + "'" + smes + "/" + fanio + "' AS mes_" + i;
				} else {
					pivot_date = pivot_date + "'" + smes + "/" + fanio + "' AS mes_" + i + ",";
				}
				mes = mes + 1;
				if (mes == 13) {
					mes = 1L;
				}
			}
		}

		if (idEstudio != null) {
			datos2 = reporteDatosContratoDAO.obtenerDatos(smes + "/" + anio, idEstudio, contrato, nombreUnico,
					temporada, titulos, amortizacion, dgenerales, tcomerciales, pivot_date);
		}

		if (datos2 != null && !datos2.isEmpty()) {

			for (DatosContratoDTO item : datos2) {
				String[] fila = item.getFieldsAsRow(dgenerales, tcomerciales, titulos, amortizacion);
				if (tabla == null) {
					tabla = new String[1][fila.length];
				} else {
					tabla = Arrays.copyOf(tabla, tabla.length + 1);
				}

				tabla[tabla.length - 1] = fila;
			}
		}
		return tabla;
	}

	public String[][] obtenReporteAnualTabla(Long anio, Long mes, Long idEstudio, Long nombreUnico, Long temporada,
			Boolean consulta) throws IllegalArgumentException, IllegalAccessException {

		String[][] tabla = null;
		String pivot_date = "";
		Integer fanio = anio.intValue();

		for (int anios = (fanio - 4), i = 0; anios <= fanio; anios++, i++) {
			pivot_date = pivot_date + anios + " AS ANIO_" + i + ",";
		}

		List<CostPerViewEstudioAnualDatosDTO> datos = null;

		if (idEstudio == null) {
			if (consulta) {
				datos = reporteDatosContratoDAO.obtenerCostPerViewAnualDatosEstudioNivel(anio - 4, anio, mes,
						pivot_date.substring(0, pivot_date.length() - 1));
			} else {
				datos = reporteDatosContratoDAO.obtenerCostPerViewAnualDatosTituloNivel(anio - 4, anio, mes,
						pivot_date.substring(0, pivot_date.length() - 1), idEstudio, nombreUnico, temporada);
			}
		} else {
			datos = reporteDatosContratoDAO.obtenerCostPerViewAnualDatosTituloNivel(anio - 4, anio, mes,
					pivot_date.substring(0, pivot_date.length() - 1), idEstudio, nombreUnico, temporada);
		}
		if (datos != null && !datos.isEmpty()) {
			for (CostPerViewEstudioAnualDatosDTO item : datos) {

				String[] fila = item.getFieldsAsRow();
				String[] tfila = Arrays.copyOfRange(fila, 0, 1);
				String[] sfila = Arrays.copyOfRange(fila, 1, fila.length - 4);
				String[] afila = Arrays.copyOfRange(fila, fila.length - 4, fila.length);

				Double sumatoriaAmor = 0.0;
				Double sumatoriaVis = 0.0;

				for (int i = 0; i < sfila.length; i++) {
					if (i % 3 == 0) {
						sumatoriaAmor = sumatoriaAmor + new Double(sfila[i]);
					}
					if (i % 3 == 1) {
						sumatoriaVis = sumatoriaVis + new Double(sfila[i]);
					}
				}

				afila[0] = String.format("%.2f", sumatoriaAmor);
				afila[1] = String.format("%.2f", sumatoriaVis);

				Double cpv = sumatoriaAmor / sumatoriaVis;

				if (!cpv.isInfinite()) {
					afila[2] = String.format("%.2f", cpv);
				} else {
					afila[2] = "";
				}
				String[] row = ArrayUtils.addAll(ArrayUtils.addAll(tfila, sfila), afila);
				if (tabla == null) {
					tabla = new String[1][row.length];
				} else {
					tabla = Arrays.copyOf(tabla, tabla.length + 1);
				}

				tabla[tabla.length - 1] = row;
			}
		}
		return tabla;
	}

	public String[] obtenerMesesTabla(Long anio, Long mes) {
		List<String> meses = new ArrayList<String>();

		for (int i = 1; i <= mes.intValue(); i++) {
			MesesAnio ames = MesesAnio.parse("" + i);
			meses.add(ames.getDesc() + " - " + anio);
		}

		meses.add("ACUMULADO");

		String[] mesesArr = new String[meses.size()];
		mesesArr = meses.toArray(mesesArr);
		return mesesArr;
	}

	public String[] obtenerAniosTabla(Long anio) {
		List<String> anios = new ArrayList<String>();

		for (int i = anio.intValue() - 4; i <= anio.intValue(); i++) {
			anios.add("" + i);
		}

		anios.add("ACUMULADO");

		String[] aniosArr = new String[anios.size()];
		aniosArr = anios.toArray(aniosArr);
		return aniosArr;
	}

	public String[] obtenerHeaderRubro(Long anio, Long mes, String titulos, String amortizacion, String dGenerales,
			String tComerciales) {
		List<String> rubros = new ArrayList<String>();

		if (dGenerales.equals("YES")) {
			rubros.add("Estudio");
			rubros.add("N. contrato DDA");
			rubros.add("N. contrato BV");
			rubros.add("Vigencia Inicio");
			rubros.add("Vigencia Fin");
			rubros.add("Apartado");
			rubros.add("% Impuesto");
			rubros.add("Categorias");
			rubros.add("Servicios");
			rubros.add("Territorios");
			rubros.add("Atributos");
			rubros.add("Filiales");
		}

		if (tComerciales.equals("YES")) {
			rubros.add("Costo Contrato");
			rubros.add("Monto Programado ");
			rubros.add("Anticipo");
			rubros.add("Pagos Mensuales/Predefinidos");
		}

		if (titulos.equals("YES")) {
			rubros.add("Id broadview");
			rubros.add("Nombre");
			rubros.add("Nombre Episodio");
			rubros.add("Temporada");
			rubros.add("Episodio");
			rubros.add("Inicio Exhibición");
			rubros.add("Fin Exhibición");
			rubros.add("VU");
			rubros.add("Categoria");
			rubros.add("Costo Título");
			rubros.add("Precio Anual");
		}

		if (amortizacion.equals("YES")) {

			if (!dGenerales.equals("YES") && !titulos.equals("YES") && !tComerciales.equals("YES")) {
				rubros.add("Estudio");
				rubros.add("N. contrato DDA");
				rubros.add("Nombre Episodio");
				rubros.add("Temporada");
			}

			String smes = "";
			Long fanio = anio - 1;

			for (int i = 1; i <= 12; i++) {
				if (i > 1 && mes == 1) {
					fanio = anio;
				}
				if (mes < 10) {
					smes = "0" + mes;
				} else {
					smes = mes.toString();
				}

				MesesAnio ames = MesesAnio.parse("" + mes);
				rubros.add(ames.getDesc() + " - " + fanio);

				mes = mes + 1;
				if (mes == 13) {
					mes = 1L;
				}
			}
		}

		String[] rubrosArr = new String[rubros.size()];
		rubrosArr = rubros.toArray(rubrosArr);
		return rubrosArr;
	}

	public ReporteCostPerViewVistaDTO obtenerReporteMensualVista(String fecha, Long idEstudio, Long contrato,
			Long nombreUnico, Long Temporada, Boolean consulta, String titulos, String amortizacion, String dgenerales,
			String tcomerciales) throws ParseException, IllegalArgumentException, IllegalAccessException {
		ReporteCostPerViewVistaDTO reporte = new ReporteCostPerViewVistaDTO();

		HashMap<String, Long> fechaSplit = FechaUtilerias.getFechaValores(fecha, "MM/yyyy");
		Long mes = fechaSplit.get("Month");
		Long anio = fechaSplit.get("Year");

		reporte.setTabla(obtenReporteMensualTabla(anio, mes, idEstudio, contrato, nombreUnico, Temporada, consulta,
				titulos, amortizacion, dgenerales, tcomerciales));
		reporte.setRheader(obtenerHeaderRubro(anio, mes, titulos, amortizacion, dgenerales, tcomerciales));

		return reporte;
	}

	public ReporteCostPerViewVistaDTO obtenerReporteAnualVista(String fecha, Long idEstudio, Long nombreUnico,
			Long Temporada, Boolean consulta) throws ParseException, IllegalArgumentException, IllegalAccessException {
		ReporteCostPerViewVistaDTO reporte = new ReporteCostPerViewVistaDTO();
		HashMap<String, Long> fechaSplit = FechaUtilerias.getFechaValores(fecha, "MM/yyyy");
		Long mes = fechaSplit.get("Month");
		Long anio = fechaSplit.get("Year");
		reporte.setTabla(obtenReporteAnualTabla(anio, mes, idEstudio, nombreUnico, Temporada, consulta));
		reporte.setPheader(obtenerAniosTabla(anio));
		return reporte;
	}

	public InputStream obtenerStreamReporte(String tipoReporte, String fecha, Long idEstudio, Long contrato,
			Long nombreUnico, Long Temporada, String titulos, String amortizacion, String dgenerales,
			String tcomerciales) throws IllegalArgumentException, IllegalAccessException, ParseException,
			ExcelMapperException, IOException, ReportCostPerViewException {
		ReporteCostPerViewVistaDTO reporte = null;
		ExcelMapper mapper = new ExcelMapper();
		List<ExcelRule> rules = new ArrayList<ExcelRule>();
		InputStream stream = null;
		byte[] info = null;

		reporte = obtenerReporteMensualVista(fecha, idEstudio, contrato, nombreUnico, Temporada, false, titulos,
				amortizacion, dgenerales, tcomerciales);

		String[][] tabla = reporte.getTabla();

		String[] rheader = reporte.getRheader();
		mapper.setClassName(ReporteCostPerViewVistaDTO.class.getName());
		mapper.setFirstRow(1);
		mapper.setId("reporteDatosContrato");
		mapper.setParent(null);
		mapper.setSkipErrors(true);
		mapper.setStartRowIndex(0);

		for (int i = 0; i < tabla[0].length - 1; i++) {
			ExcelRule rule = new ExcelRule();
			List<String> headers = new ArrayList<String>();
			rule.setColumn(getExcelColumnName(i + 1));
			if (tabla[0][i] != null) {
				headers.add(rheader[i]);

				rule.setHeaders(headers);

				rules.add(rule);
			}
		}

		mapper.setRules(rules);

		info = excelMapperTransform.transformObjectToExcel(tabla, mapper, String.class);
		stream = new ByteArrayInputStream(info);

		return stream;
	}

	public HashMap<String, HashMap<String, String>> obtenerDataQueryDetalleMensual(String fecha)
			throws IOException, ParseException, InvalidFormatException {

		String header_1 = "SELECT '|||";
		String header_2 = "SELECT 'IdBroadview|Estudio|Temporada/Episodio";
		String detalleMensual = "SELECT ID_BV||'|'||ESTUDIO||'|'||T_E";
		String amortizaciones = "";
		String visualizaciones = "";

		HashMap<String, Long> fechaSplit = FechaUtilerias.getFechaValores(fecha, "MM/yyyy");
		Long mes = fechaSplit.get("Month");
		Long anio = fechaSplit.get("Year");

		logger.info("{}", mes);
		logger.info("{}", anio);

		SimpleDateFormat formater = new SimpleDateFormat("MM/yyyy");

		Calendar beginCalendar = Calendar.getInstance();
		Calendar finishCalendar = Calendar.getInstance();

		beginCalendar.setTime(formater.parse("1" + "/" + anio));
		finishCalendar.setTime(formater.parse(mes + "/" + anio));

		Integer index = 1;
		while (beginCalendar.before(finishCalendar) || beginCalendar.equals(finishCalendar)) {
			MesesAnio ames = MesesAnio.parse("" + index);

			header_1 = header_1 + ames.getDesc() + "|||";
			header_2 = header_2 + "|Amortizacion|Visualizaciones|CPV";
			detalleMensual = detalleMensual + "||'|'||AMOR_" + index + "||'|'||VIS_" + index + "||'|'||CPV_" + index;
			amortizaciones = amortizaciones + "AMOR_" + index + "+";
			visualizaciones = visualizaciones + "VIS_" + index + "+";

			beginCalendar.add(Calendar.MONTH, 1);
			index++;
		}

		header_1 = header_1 + "ACUMULADO|||' as X from dual;";
		header_2 = header_2 + "|AmortizacionT|VisualizacionesT|CPVT|' as X from dual;";
		amortizaciones = amortizaciones.substring(0, amortizaciones.length() - 1);
		visualizaciones = visualizaciones.substring(0, visualizaciones.length() - 1);

		detalleMensual = detalleMensual + "|| '|' || (" + amortizaciones + ") || '|' || (" + visualizaciones
				+ ") || '|' || ROUND((" + amortizaciones + ")/(" + visualizaciones + "), 2) FROM (";

		logger.info("{}", header_1);
		logger.info("{}", header_2);
		logger.info("{}", amortizaciones);
		logger.info("{}", visualizaciones);
		logger.info("{}", detalleMensual);

		HashMap<String, String> headers = new HashMap<String, String>();
		headers.put("header_0", header_1);
		headers.put("header_1", header_2);

		HashMap<String, String> bheaders = new HashMap<String, String>();
		bheaders.put("bheader_0", detalleMensual);

		HashMap<String, String> parameters = new HashMap<String, String>();
		parameters.put("anio", anio.toString());
		parameters.put("mes", mes.toString());

		HashMap<String, HashMap<String, String>> customData = new HashMap<String, HashMap<String, String>>();
		customData.put("HEADERS", headers);
		customData.put("BHEADERS", bheaders);
		customData.put("PARAMETERS", parameters);

		return customData;
	}

	public HashMap<String, HashMap<String, String>> obtenerDataQueryDetalleAnual(String fecha)
			throws IOException, ParseException, InvalidFormatException {

		String header_1 = "SELECT '|||";
		String header_2 = "SELECT 'IdBroadview|Estudio|Temporada/Episodio";
		String detalleMensual = "SELECT ID_BV||'|'||ESTUDIO||'|'||T_E";
		String amortizaciones = "";
		String visualizaciones = "";
		String pivot_data = "";

		HashMap<String, Long> fechaSplit = FechaUtilerias.getFechaValores(fecha, "MM/yyyy");
		Long mes = fechaSplit.get("Month");
		Long anio = fechaSplit.get("Year");

		logger.info("{}", mes);
		logger.info("{}", anio);

		SimpleDateFormat formater = new SimpleDateFormat("MM/yyyy");

		Calendar beginCalendar = Calendar.getInstance();
		Calendar finishCalendar = Calendar.getInstance();

		beginCalendar.setTime(formater.parse("1" + "/" + anio));
		finishCalendar.setTime(formater.parse(mes + "/" + anio));

		Integer fanio = anio.intValue();

		Integer index = 1;
		for (int anios = (fanio - 4), i = 0; anios <= fanio; anios++, i++) {

			header_1 = header_1 + anios + "|||";
			header_2 = header_2 + "|Amortizacion|Visualizaciones|CPV";
			detalleMensual = detalleMensual + "||'|'||AMOR_ANIO_" + index + "||'|'||VIS_ANIO_" + index
					+ "||'|'||CPV_ANIO_" + index;
			amortizaciones = amortizaciones + "AMOR_ANIO_" + index + "+";
			visualizaciones = visualizaciones + "VIS_ANIO_" + index + "+";
			pivot_data = pivot_data + anios + " AS ANIO_" + i + ",";

			beginCalendar.add(Calendar.MONTH, 1);
			index++;
		}

		header_1 = header_1 + "ACUMULADO|||' as X from dual;";
		header_2 = header_2 + "|AmortizacionT|VisualizacionesT|CPVT|' as X from dual;";
		amortizaciones = amortizaciones.substring(0, amortizaciones.length() - 1);
		visualizaciones = visualizaciones.substring(0, visualizaciones.length() - 1);
		pivot_data = pivot_data.substring(0, pivot_data.length() - 1);

		detalleMensual = detalleMensual + "|| '|' || (" + amortizaciones + ") || '|' || (" + visualizaciones
				+ ") || '|' || ROUND((" + amortizaciones + ")/(" + visualizaciones + "), 2) FROM (";

		logger.info("{}", header_1);
		logger.info("{}", header_2);
		logger.info("{}", amortizaciones);
		logger.info("{}", visualizaciones);
		logger.info("{}", detalleMensual);

		HashMap<String, String> headers = new HashMap<String, String>();
		headers.put("header_0", header_1);
		headers.put("header_1", header_2);

		HashMap<String, String> bheaders = new HashMap<String, String>();
		bheaders.put("bheader_0", detalleMensual);

		HashMap<String, String> parameters = new HashMap<String, String>();
		parameters.put("anio_final", anio.toString());
		parameters.put("anio_inicial", new Long(fanio - 4).toString());
		parameters.put("mes", mes.toString());
		parameters.put("pivot_data", pivot_data);

		HashMap<String, HashMap<String, String>> customData = new HashMap<String, HashMap<String, String>>();
		customData.put("HEADERS", headers);
		customData.put("BHEADERS", bheaders);
		customData.put("PARAMETERS", parameters);

		return customData;
	}

	public InputStream obtenerStreamZipReporte(String tipoReporte, String fecha)
			throws InvalidFormatException, IOException, ParseException {

		String finalQueryNameFile = "cpvDetalle";
		String baseQueryNameFile = "";

		HashMap<String, HashMap<String, String>> customData = obtenerDataQueryDetalleMensual(fecha);

		if (tipoReporte.equals("mensual")) {
			baseQueryNameFile = "queryCpvDetalleMensual.txt";
			customData = obtenerDataQueryDetalleMensual(fecha);
		}

		if (tipoReporte.equals("anual")) {
			baseQueryNameFile = "queryCpvDetalleAnual.txt";
			customData = obtenerDataQueryDetalleAnual(fecha);
		}

		if (creaQueryDetalleCpv(customData, baseQueryNameFile, finalQueryNameFile)) {
			return creaStreamZipFileCpv(finalQueryNameFile);
		} else {
			return null;
		}

	}

	private Boolean creaQueryDetalleCpv(HashMap<String, HashMap<String, String>> customData, String baseQueryNameFile,
			String finalQueryNameFile) {

		try {

			InputStream queryStream;
			queryStream = customResourceLoader.getFile2ItputStream("classpath:templateFees/" + baseQueryNameFile);

			FileWriter fw = new FileWriter(uriSQL + finalQueryNameFile + ".sql");
			String lineSeparador = System.getProperty("line.separator");

			fw.write("SET trimspool ON;");
			fw.write(lineSeparador);
			fw.write("SET heading OFF;");
			fw.write(lineSeparador);
			fw.write("SET headsep OFF;");
			fw.write(lineSeparador);
			fw.write("SET linesize 20000;");
			fw.write(lineSeparador);
			fw.write("SET pagesize 0;");
			fw.write(lineSeparador);
			fw.write("SET TERMOUT OFF;");
			fw.write(lineSeparador);
			fw.write("SET NEWPAGE 0;");
			fw.write(lineSeparador);
			fw.write("SET SPACE 0;");
			fw.write(lineSeparador);
			fw.write("SET ECHO OFF;");
			fw.write(lineSeparador);
			fw.write("SET FEEDBACK OFF;");
			fw.write(lineSeparador);
			fw.write("SET MARKUP HTML OFF SPOOL OFF;");
			fw.write(lineSeparador);
			fw.write("SET VERIFY OFF;");
			fw.write(lineSeparador);
			fw.write("SET DEFINE OFF;");
			fw.write(lineSeparador);
			fw.write("SET serveroutput on size 1000000;");
			fw.write(lineSeparador);
			fw.write("spool " + uriTXT + finalQueryNameFile + ".txt;");
			fw.write(lineSeparador);

			fw.write("--[BEGIN]");
			fw.write(lineSeparador);

			HashMap<String, String> headers = customData.get("HEADERS");
			for (int i = 0; i < headers.size(); i++) {
				fw.write(headers.get("header_" + i));
				fw.write(lineSeparador);
			}

			fw.write("--[END_HEADER]");
			fw.write(lineSeparador);

			HashMap<String, String> bheaders = customData.get("BHEADERS");
			for (int i = 0; i < bheaders.size(); i++) {
				fw.write(bheaders.get("bheader_" + i));
				fw.write(lineSeparador);
			}

			BufferedReader in = new BufferedReader(new InputStreamReader(queryStream));
			String line = null;

			HashMap<String, String> parameters = customData.get("PARAMETERS");

			while ((line = in.readLine()) != null) {
				if (line != null) {
					for (Map.Entry<String, String> entry : parameters.entrySet()) {
						line = line.replace("#{" + entry.getKey() + "}", entry.getValue());
					}
					fw.write(line);
					fw.write(lineSeparador);
				}
			}

			if (bheaders.size() > 0) {
				for (int i = 0; i < bheaders.size(); i++) {
					fw.write(")");
				}
				fw.write(";");
				fw.write(lineSeparador);
			}

			fw.write("--[END]");
			fw.write(lineSeparador);
			fw.write("spool off;");
			fw.write(lineSeparador);
			fw.write("quit");
			fw.close();

		} catch (InvalidFormatException | IOException e) {
			return false;
		}

		return true;
	}

	private InputStream creaStreamZipFileCpv(String finalQueryNameFile) {

		File file = new File(uriSQL + finalQueryNameFile + ".sql");
		InputStream zipStream = null;
		ResponseGeneraReporteDTO responseDTO = new ResponseGeneraReporteDTO();

		if (file.exists()) {
			try {
				responseDTO = baseActivosBO.generaReporteWS(finalQueryNameFile);
				if (responseDTO != null && responseDTO.getMensaje().contains("OK") && responseDTO.getRuta() != null) {
					File zipFile = new File(responseDTO.getRuta());
					if (zipFile != null && zipFile.exists()) {
						zipStream = new FileInputStream(zipFile);
					}
				}
			} catch (IOException e) {
				logger.error("Error. {}", e);
			} catch (TransaccionException e) {
				logger.error("Error. {}", e);
			}
		}

		return zipStream;

	}

	public void procesarStreamArchivoCarga(File archivo, String nombreArchivo, String fecha, String expediente)
			throws ParseException, IOException, ReportCostPerViewException {

		logger.info("Procesando ...");
		logger.info("{}", archivo);
		logger.info("{}", nombreArchivo);

		HashMap<String, Long> fechaSplit = FechaUtilerias.getFechaValores(fecha, "MM/yyyy");
		Long mes = fechaSplit.get("Month");
		Long anio = fechaSplit.get("Year");

		ParamCargaTitulosVSDTO request = new ParamCargaTitulosVSDTO();
		ResponseCargaTitulosVSDTO response = null;
		DLARestClient client = null;

		String fileName = StringUtils.leftPad(String.valueOf(mes), 2, "0")
				+ StringUtils.leftPad(String.valueOf(anio), 4, "0") + expediente + nombreArchivo;
		String absoluteFileName = uriCarga + fileName;

		byte[] file = FileUtils.readFileToByteArray(archivo);

		File d = new File(absoluteFileName);
		d.setExecutable(true, false);
		d.setReadable(true, false);
		d.setWritable(true, false);

		FileUtils.writeByteArrayToFile(d, file);

		logger.info("Archivo: [{}]", absoluteFileName);
		String separador = "/";

		client = dlaRestClientFactory.getClient(DLARestServices.WS_CARGA_ARCHIVO_VISUALIZACIONES);
		request.setNombreArchivo(fileName);
		request.setExpediente(expediente);
		request.setMesCarga("01" + separador + StringUtils.leftPad(String.valueOf(mes), 2, "0") + separador
				+ StringUtils.leftPad(String.valueOf(anio), 4, "0"));

		logger.debug("request : [{}]", request);
		logger.debug("client!!! : [{}]", client);

		try {
			response = client.get(request, ResponseCargaTitulosVSDTO.class);
		} catch (SocketTimeoutException e) {
			logger.error("Error. {}", e);
		} catch (IOException e) {
			logger.error("Error. {}", e);
		} catch (TransaccionException e) {
			logger.error("Error. {}", e);
		}

		logger.info("response : [{}]", response);

		if (response != null && !response.isResultado()) {
			throw new ReportCostPerViewException("Error servicio carga: " + response.getMensaje());
		}

	}

	public static String getExcelColumnName(int number) {
		final StringBuilder sb = new StringBuilder();

		int num = number - 1;
		while (num >= 0) {
			int numChar = (num % 26) + 65;
			sb.append((char) numChar);
			num = (num / 26) - 1;
		}
		return sb.reverse().toString();
	}

	public VisualizacionesCostPerViewVistaDTO obtenerCargaVisualizacionesMensualVista(String fecha)
			throws ParseException, IllegalArgumentException, IllegalAccessException, ReportCostPerViewException {
		VisualizacionesCostPerViewVistaDTO reporte = new VisualizacionesCostPerViewVistaDTO();
		VisualizacionesCostPerViewVistaDTO response = new VisualizacionesCostPerViewVistaDTO();

		HashMap<String, Long> fechaSplit = FechaUtilerias.getFechaValores(fecha, "MM/yyyy");
		Long mes = fechaSplit.get("Month");
		Long anio = fechaSplit.get("Year");

		DateFormat formatoEntrada = new SimpleDateFormat("MM/yyyy");
		Date date = formatoEntrada.parse(fecha);

		if (FechaUtilerias.monthGreatherThan(date, new Date())) {
			throw new ReportCostPerViewException("Mes elegido es mayor al mes actual");
		}

		response = obtenCargaVisualizacionesPrincipalTabla(fecha);
		reporte.setHeader(obtenerHeaderTablaCargaVisualizaciones());

		if (response != null) {

			reporte.setTabla(obtenCargaVisualizacionesDetalleTabla(anio, mes));
			reporte.setCorrectos(response.getCorrectos());
			reporte.setErroneos(response.getErroneos());
			reporte.setLeidos(response.getLeidos());
		}

		return reporte;
	}

	public String[][] obtenCargaVisualizacionesDetalleTabla(Long anio, Long mes)
			throws IllegalArgumentException, IllegalAccessException {
		String[][] tabla = null;

		List<CargaVisualizacionesDetalleDTO> datos = reporteDatosContratoDAO.obtenerVisualizaciones(mes, anio);
		if (datos != null && !datos.isEmpty()) {

			for (CargaVisualizacionesDetalleDTO item : datos) {
				String[] arow = item.getFieldsAsRow();
				String[] row = { arow[2], arow[3], arow[4] };

				if (tabla == null) {
					tabla = new String[1][row.length];
				} else {
					tabla = Arrays.copyOf(tabla, tabla.length + 1);
				}

				tabla[tabla.length - 1] = row;
			}
		}
		return tabla;
	}

	public VisualizacionesCostPerViewVistaDTO obtenCargaVisualizacionesPrincipalTabla(String fecha)
			throws ParseException, IllegalArgumentException, IllegalAccessException, ReportCostPerViewException {
		VisualizacionesCostPerViewVistaDTO reporte = null;

		HashMap<String, Long> fechaSplit = FechaUtilerias.getFechaValores(fecha, "MM/yyyy");
		Long mes = fechaSplit.get("Month");
		Long anio = fechaSplit.get("Year");

		DateFormat formatoEntrada = new SimpleDateFormat("MM/yyyy");
		Date date = formatoEntrada.parse(fecha);

		if (FechaUtilerias.monthGreatherThan(date, new Date())) {
			throw new ReportCostPerViewException("Mes elegido es mayor al mes actual");
		}

		List<CargaVisualizacionesPrincipalDTO> datos = reporteDatosContratoDAO.obtenerVisualizacionesPrincipal(mes,
				anio);

		if (datos != null && !datos.isEmpty()) {

			reporte = new VisualizacionesCostPerViewVistaDTO();

			LinkedList<CargaVisualizacionesPrincipalDTO> lista = new LinkedList<CargaVisualizacionesPrincipalDTO>(
					datos);

			reporte.setLeidos(lista.getFirst().getTotalRegistros());
			reporte.setCorrectos(lista.getFirst().getTotalCargados());
			reporte.setErroneos(lista.getFirst().getTotalError());

		}

		return reporte;
	}

	public String[] obtenerHeaderTablaCargaVisualizaciones() {
		String[] header = { "Id Broadview", "Nombre del Título", "Visualizaciones" };
		return header;
	}

	public InputStream obtenerStreamVisualizaciones(String fecha)
			throws IllegalArgumentException, IllegalAccessException, ParseException, ExcelMapperException, IOException {
		List<CargaVisualizacionesDetalleDTO> reporte = null;
		ExcelRule newRule = new ExcelRule();
		InputStream stream = null;
		byte[] info = null;

		ExcelMapper mapper = excelMapperContext.getExcelMapper("plantillaVisualizacionesCostPerView");

		newRule.setAttribute("comentarios");
		newRule.setColumn("E");
		newRule.setHeader("Comentarios");

		mapper.getRules().add(newRule);

		HashMap<String, Long> fechaSplit = FechaUtilerias.getFechaValores(fecha, "MM/yyyy");
		Long mes = fechaSplit.get("Month");
		Long anio = fechaSplit.get("Year");

		reporte = reporteDatosContratoDAO.obtenerVisualizacionesDetalle(mes, anio);

		info = excelMapperTransform.transformObjectToExcel(reporte, mapper, CargaVisualizacionesDetalleDTO.class);
		stream = new ByteArrayInputStream(info);

		return stream;
	}

	public InputStream obtenerStreamPlantilla() throws IllegalArgumentException, IllegalAccessException, ParseException,
			ExcelMapperException, IOException, InvalidFormatException {
		InputStream stream = null;
		byte[] info = null;
		info = customResourceLoader.getFile2ByteArray("classpath:templateFees/plantillaCargaVS.xlsx");
		stream = new ByteArrayInputStream(info);
		return stream;
	}

	public String logStringArray(String[] array) {

		String log = "";

		if (array != null && array.length != 0) {
			for (String item : array) {
				log = log + "[" + item + "] ";
			}
		}

		return log;
	}

}
