package com.mx.dla.dda.reporte.cpview.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.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.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.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 ReporteCostoPerViewBO extends BaseBO {

    @Autowired
    private ReporteCostPerViewDAO reporteCostPerViewDAO;

    @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[][] obtenReporteMensualTabla(Long anio, Long mes, Long idEstudio,String nombreUnico, String temporada, Boolean consulta) throws IllegalArgumentException, IllegalAccessException {

        String[][] tabla = null;
        // int tamanio = (3 * (mes.intValue() + 1)) + 2;
        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 = reporteCostPerViewDAO.obtenerCostPerViewMensualDatosEstudioNivel(mes, anio);
                diciembre = reporteCostPerViewDAO.obtenerCostPerViewDiciembreDatosEstudioNivel(anio - 1);
            } else {
                datos = reporteCostPerViewDAO.obtenerCostPerViewMensualDatosTituloNivel(mes, anio, idEstudio,nombreUnico, temporada);
                diciembre = reporteCostPerViewDAO.obtenerCostPerViewDiciembreDatosTituloNivel(anio - 1, idEstudio,nombreUnico, temporada);
            }
        } else {
            datos = reporteCostPerViewDAO.obtenerCostPerViewMensualDatosTituloNivel(mes, anio, idEstudio,nombreUnico, temporada);
            diciembre = reporteCostPerViewDAO.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);
            }

            // logger.info("{}", datos.size());
            for (CostPerViewEstudioMensualDatosDTO item : datos) {

                // logger.info("item: {}", item);
                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);

                // logger.info("fila: {}", logStringArray(fila));
                // logger.info("tfila: {}", logStringArray(tfila));
                // logger.info("sfila: {}", logStringArray(sfila));
                // logger.info("afila: {}", logStringArray(afila));
                if (dicFlag) {

                    // logger.info("sorted");
                    int i = Collections.binarySearch(diciembre, item, comparator);

                    // logger.info("index {}", i);
                    if (i >= 0) {
                        CostPerViewEstudioMensualDatosDTO found = diciembre.get(i);

                        // logger.info("found {}" , found);
                        String[] arowDic = found.getFieldsAsRow();

                        // logger.info("arowDic {}" , arowDic);
                        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();
                            }
                        }
                    }
                }

                // logger.info("sfila: {}", logStringArray(sfila));
                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] = "";
                }

                // logger.info("sumatoriaAmor: {}, sumatoriaVis: {}", sumatoriaAmor, sumatoriaVis);
                String[] row = ArrayUtils.addAll(ArrayUtils.addAll(tfila, sfila), afila);

                // logger.info("row {}", logStringArray(row));
                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[][] obtenReporteAnualTabla(Long anio, Long mes, Long idEstudio,String nombreUnico, String 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 = reporteCostPerViewDAO.obtenerCostPerViewAnualDatosEstudioNivel(anio - 4, anio, mes, pivot_date.substring(0, pivot_date.length() - 1));
            } else {
                datos = reporteCostPerViewDAO.obtenerCostPerViewAnualDatosTituloNivel(anio - 4, anio, mes, pivot_date.substring(0, pivot_date.length() - 1), idEstudio,nombreUnico, temporada);
            }
        } else {
            datos = reporteCostPerViewDAO.obtenerCostPerViewAnualDatosTituloNivel(anio - 4, anio, mes, pivot_date.substring(0, pivot_date.length() - 1), idEstudio,nombreUnico, temporada);
        }

        /*		String[] arow = item.getFieldsAsRow(new String[] { "nivel" });
				String[] row = new String[tamanio + 4];
				Long nivel = item.getNivel();
         */
        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] = "";
                }

                // logger.info("sumatoriaAmor: {}, sumatoriaVis: {}", sumatoriaAmor, sumatoriaVis);
                String[] row = ArrayUtils.addAll(ArrayUtils.addAll(tfila, sfila), afila);

                // logger.info("row {}", logStringArray(row));
                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 tamanio) {
        List<String> rubros = new ArrayList<String>();

        for (int i = 0; i < tamanio + 1; i++) {
            rubros.add("Amortización");
            rubros.add("Visualizaciones");
            rubros.add("CPV");
        }

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

    public ReporteCostPerViewVistaDTO obtenerReporteMensualVista(String fecha, Long idEstudio, String nombreUnico, String 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(obtenReporteMensualTabla(anio, mes, idEstudio,nombreUnico, Temporada, consulta));
        reporte.setPheader(obtenerMesesTabla(anio, mes));
        reporte.setRheader(obtenerHeaderRubro(mes));

        return reporte;
    }

    public ReporteCostPerViewVistaDTO obtenerReporteAnualVista(String fecha, Long idEstudio,String nombreUnico, String 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));
        reporte.setRheader(obtenerHeaderRubro(5L));
        return reporte;
    }

    public InputStream obtenerStreamReporte(String tipoReporte, String fecha, Long idEstudio,String nombreUnico, String Temporada)
            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;

        if (tipoReporte.equals("mensual")) {
            reporte = obtenerReporteMensualVista(fecha, idEstudio,nombreUnico,Temporada, false);
        }
        if (tipoReporte.equals("anual")) {
            reporte = obtenerReporteAnualVista(fecha, idEstudio,nombreUnico,Temporada, false);
        }
        String[][] tabla = reporte.getTabla();
        String[] rheader = reporte.getRheader();
        String[] pheader = reporte.getPheader();
        String[] apheader = new String[rheader.length + 1];
        String[] arheader = new String[rheader.length + 1];
        int j = 0;
        for (int i = 0; i < rheader.length; i++) {
            if (i == 0) {
                apheader[i] = "Estudio";
            } else if ((i - 1) % 3 == 0) {
                apheader[i] = pheader[j];
                j++;
            } else {
                apheader[i] = "";
            }
        }

        for (int i = 0; i < arheader.length; i++) {
            if (i == 0) {
                arheader[i] = "";
            } else {
                arheader[i] = rheader[i - 1];
            }
        }

        // atabla[0] = Arrays.copyOf(arheader, arheader.length);
        // for (int i = 0; i < tabla.length; i++)
        // atabla[i + 1] = Arrays.copyOf(tabla[i], tabla[i].length);
        mapper.setClassName(ReporteCostPerViewVistaDTO.class.getName());
        mapper.setFirstRow(2);
        mapper.setId("reporteCostPerView");
        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));
            headers.add(apheader[i]);
            headers.add(arheader[i]);
            // rule.setHeader(apheader[i]);
            rule.setHeaders(headers);

            if (i > 0) {
                rule.setType(ExcelMapperDataType.numeric);
            }

            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_" + index + "|Visualizaciones_" + index + "|CPV_" + index;
            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_" + index + "|Visualizaciones_" + index + "|CPV_" + index;
            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 (Exception e) {
                logger.debug(e.toString());
            }
        }

        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);

        response = client.get(request, ResponseCargaTitulosVSDTO.class);

        logger.debug("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 = reporteCostPerViewDAO.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 = reporteCostPerViewDAO.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 = reporteCostPerViewDAO.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 {

        // List<CargaVisualizacionesDetalleDTO> reporte = new
        // ArrayList<CargaVisualizacionesDetalleDTO>();
        InputStream stream = null;
        byte[] info = null;

        /*
		 * ExcelMapper mapper = excelMapperContext.getExcelMapper(
		 * "plantillaVisualizacionesCostPerView");
		 * 
		 * CargaVisualizacionesDetalleDTO dummyItem = new
		 * CargaVisualizacionesDetalleDTO();
		 * dummyItem.setIdBroadview("900001054"); dummyItem.setTitulo("Cars 3");
		 * dummyItem.setVisualizaciones("750"); dummyItem.setMes("Ene-17");
		 * 
		 * reporte.add(dummyItem);
		 * 
		 * info = excelMapperTransform.transformObjectToExcel(reporte, mapper,
		 * CargaVisualizacionesDetalleDTO.class); stream = new
		 * ByteArrayInputStream(info);
         */
        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;
    }

}
