package com.dacrt.SBIABackend.controler;

import java.io.PrintWriter;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.dacrt.SBIABackend.dto.AppTypeDto;
import com.dacrt.SBIABackend.dto.ApplicationDto;
import com.dacrt.SBIABackend.dto.ApplicationDto2;
import com.dacrt.SBIABackend.dto.ApplicationDto3;
import com.dacrt.SBIABackend.dto.ApplicationResponseDto2;
import com.dacrt.SBIABackend.dto.AppyesnoDto;
import com.dacrt.SBIABackend.dto.CampaignFormat2Dto;
import com.dacrt.SBIABackend.dto.ChannelsRankingDto;
import com.dacrt.SBIABackend.dto.DrptestedDto3;
import com.dacrt.SBIABackend.dto.FacilityDto2;
import com.dacrt.SBIABackend.dto.OperationlineDto4;
import com.dacrt.SBIABackend.dto.ProcessRankingDto;
import com.dacrt.SBIABackend.dto.ProcessTypeDto3;
import com.dacrt.SBIABackend.dto.RankingAplicacionesRequestDto;
import com.dacrt.SBIABackend.dto.RankingAplicacionesResponseDto;
import com.dacrt.SBIABackend.dto.RankingAplicacionesResponseDto2;
import com.dacrt.SBIABackend.dto.RecordCatalogoResponseDto;
import com.dacrt.SBIABackend.dto.RtoDto;
import com.dacrt.SBIABackend.dto.ServiceOffers6Dto;
import com.dacrt.SBIABackend.dto.StatusDto;
import com.dacrt.SBIABackend.dto.TypeDto;
import com.dacrt.SBIABackend.dto.responseDto.ApplicationResponseDto;
import com.dacrt.SBIABackend.repository.ApplicationsRepository;
import com.dacrt.SBIABackend.repository.FacilitiesRepository;
import com.dacrt.SBIABackend.repository.SuppliersRepository;
import com.dacrt.SBIABackend.security.dto.AuditRequestDto;
import com.dacrt.SBIABackend.security.dto.PrivilegesAllDto;
import com.dacrt.SBIABackend.security.dto.RespuestaDto;
import com.dacrt.SBIABackend.security.dto.RespuestaMsgDto;
import com.dacrt.SBIABackend.security.entity.Roles;
import com.dacrt.SBIABackend.security.entity.Users;
import com.dacrt.SBIABackend.security.repository.AuditRepository;
import com.dacrt.SBIABackend.security.repository.ParamsRepository;
import com.dacrt.SBIABackend.security.repository.UsersRepository;
import com.dacrt.SBIABackend.security.service.MenuService;
import com.dacrt.SBIABackend.security.service.ParamsService;
import com.dacrt.SBIABackend.security.service.SecurityService;
import com.dacrt.SBIABackend.security.service.UsersService;

@RestController
//@RequestMapping("/units")   
@CrossOrigin(origins = "*")
public class RankingAplicacionesController {
	@Autowired
	private ParamsRepository paramsRepository;

	@Autowired
	private UsersRepository usersRepository;

	@Autowired
	private AuditRepository auditRepository;

	@Autowired
	UsersService usersService;

	@Autowired
	ParamsService paramsService;

	@Autowired
	SecurityService securityService;

	@Autowired
	MenuService menuService;

	@PersistenceContext
	private EntityManager entityManager;

	@Autowired
	SuppliersRepository suppliersRepository;

	@Autowired
	ApplicationsRepository applicationsRepository;

	@Autowired
	FacilitiesRepository facilitiesRepository;

	@PostMapping("/reports/appsranking")
	public ResponseEntity<?> applicationsRanking(HttpServletRequest request,
			HttpServletResponse response,
			@RequestBody RankingAplicacionesRequestDto rankingFiltros) throws ParseException {
		RespuestaDto respuesta = new RespuestaDto("", false);
		HttpStatus estatus = HttpStatus.FORBIDDEN;

		ApplicationResponseDto applicationResponseDto = new ApplicationResponseDto();
		ApplicationResponseDto2 applicationResponseDto2 = new ApplicationResponseDto2();
		RecordCatalogoResponseDto appFormatResponseDto = new RecordCatalogoResponseDto();
		// ParamsDto detalleParams;
		ApplicationDto detalleApplication;
		ApplicationDto2 detalleApplication2;
		StatusDto detalleStatus;
		PrivilegesAllDto detallePrivilege;
		FacilityDto2 detallefacility;
		Long cuantosregistro = (long) 0;
		CampaignFormat2Dto detalleCompaing2;

		List<PrivilegesAllDto> listasPrivelege = new ArrayList<>();

		String sessionid = request.getHeader("Authorization");
		Date fecha = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String dataFormattata = formatter.format(fecha);
		Date fechaDate = formatter.parse(dataFormattata);
		AuditRequestDto auditDto = new AuditRequestDto();

		int idrol;
		String searchIn = "";
		String apptypeparIn = "";
		String drptestyesnoparIn = "";
		int serviceofferidIn = 0;

		String apptypeSearch = "";
		String contentIn = "";
		int searchStatus = 0;
		int facilityIn = 0;
		int formatList = 0;

		String fechaComoCadena;
		int orderIn = 0;
		int offsetIn = 0;
		int numofrecordsIn = 0;
		Date fecha2 = new Date();

		if (sessionid == null) {
			String var = "";
			boolean bloked = false;
			RespuestaDto respuestaDto = new RespuestaDto(var, bloked);
			respuestaDto.setBlocked(bloked);
			respuestaDto.setMsg("Sesión expirada o inválida");
			// Error 400
			return new ResponseEntity(respuestaDto, HttpStatus.BAD_REQUEST);
		} else {

			sessionid = sessionid.substring(7);
			Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(sessionid);

			if (encontreSessionUsuario.isPresent()) {

				Date FechaReg = encontreSessionUsuario.get().getValidthru();
				fechaComoCadena = securityService.consultarSessionActiva(FechaReg, fecha2,
						encontreSessionUsuario.get().getId());

				if (fechaComoCadena == "") {
					String var = "";
					boolean bloked = false;
					RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
					// respuestaDto.setBlocked(bloked);
					respuestaDto.setMsg("Sesión expirada o inválida");
					return new ResponseEntity(respuestaDto, HttpStatus.UNAUTHORIZED);
				}

				// Este proceso permite obtener un listado de los proveedores. (Priv 440)
				Roles roles = encontreSessionUsuario.get().getRolid();
				idrol = roles.getId();
				int rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol, 530);
				formatList = 0;
				
				try {
					formatList = rankingFiltros.getFormat();

				} catch (Exception e) {
					formatList = 0;

				}
				
				if (formatList != 2) {
					if (rolisvalid == 0) {
						String var = "";
						boolean bloked = false;
						RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
						// respuestaDto.setBlocked(bloked);
						respuestaDto.setMsg("No tiene los Privilegios");
						return new ResponseEntity(respuestaDto, HttpStatus.FORBIDDEN);
					}
				}

				searchIn = rankingFiltros.getFilters().getSearch();
				apptypeparIn = rankingFiltros.getFilters().getApptypepar();
				drptestyesnoparIn = rankingFiltros.getFilters().getDrptestyesnopar();
				serviceofferidIn = rankingFiltros.getFilters().getServiceofferid();

				orderIn = rankingFiltros.getOrder();
				offsetIn = rankingFiltros.getOffset();
				numofrecordsIn = rankingFiltros.getNumofrecords();
				contentIn = rankingFiltros.getContent();

				if (contentIn != null) {
					menuService.iscontentdiffnull(contentIn, encontreSessionUsuario.get().getId());
				}
				
				

			} else {
				String var = "";
				boolean bloked = false;
				RespuestaDto respuestaDto = new RespuestaDto(var, bloked);
				respuestaDto.setBlocked(bloked);
				respuestaDto.setMsg("Sesión expirada o inválida");
				// Error 400
				return new ResponseEntity(respuestaDto, HttpStatus.UNAUTHORIZED);
			}
		}

		try {

			
			String SentenciaBase = "";
			Query query;

			SentenciaBase = " WITH CampanasConRanking AS ( "
					+ "    SELECT "
					+ "        id, "
					+ "        ROW_NUMBER() OVER (ORDER BY dateto DESC) AS ranking_campana "
					+ "    FROM main.campaigns "
					+ "    WHERE DATE_TRUNC('day', dateto) <= CURRENT_DATE "
					+ "	ORDER BY ranking_campana DESC "
					+ "), CantidadProcesosByEvaluacion AS (   "
					+ "    SELECT   "
					+ "        a.applicationid,   "
					+ "        COUNT(a.evalprocessid) AS procesos, "
					+ " cast(COUNT(DISTINCT p.id) as integer ) AS numero_de_procesos,  "
					//+ "		COUNT(DISTINCT p.id) AS numero_de_procesos,   "
					+ "		array_to_string(ARRAY_AGG(DISTINCT p.id), ';') AS idprocesos,   "
					+ "		array_to_string(ARRAY_AGG(p.name), ';') AS nombre_procesos,   "
					+ "		array_to_string(ARRAY_AGG(p.processtypepar), ';') AS tipo_proceso,   "
					+ "		array_to_string(ARRAY_AGG(pr.descr), ';') AS nombre_tipo_proceso,   "
					+ "		array_to_string(ARRAY_AGG(p.operationlineid), ';') AS linea,   "
					+ "		array_to_string(ARRAY_AGG(o.name), ';') AS nombre_linea,   "
					+ "		array_to_string(ARRAY_AGG(t1.rtoqty), ';') AS rtoqty   "
					+ "    FROM main.evalprocapps a   "
					+ "    INNER JOIN main.evalprocesses eval   "
					+ "        ON eval.id = a.evalprocessid AND eval.appst = 1  "
					+ "    INNER JOIN main.campaignunits cu ON eval.campaignunitid = cu.id "
					+ "    INNER JOIN main.campaigns c ON cu.campaingid = c.id "
					+ "	INNER JOIN main.evalprocimpacts t1 ON eval.id = t1.evalprocessid "
					+ "	INNER JOIN main.unitprocesses up   "
					+ "		ON up.id = eval.unitprocessid   "
					+ "	INNER JOIN main.processes p   "
					+ "		ON p.id=up.processid   "
					+ "	INNER JOIN main.operationlines o   "
					+ "		ON o.id=p.operationlineid   "
					+ "	INNER JOIN (   "
					+ "		SELECT elemento ->> 'dsc' AS descr,   "
					+ "				elemento ->> 'value' AS valor   "
					+ "		FROM main.params p, jsonb_array_elements(CAST(p.value AS jsonb)) AS elemento   "
					+ "		 WHERE p.paramname = 'PROCESS_TYPE'   "
					+ "		) pr ON p.processtypepar = CAST(pr.valor AS integer)  "
					+ "    INNER JOIN CampanasConRanking cr ON c.id = cr.id "
					+ "    WHERE eval.impactst = 1  "
					+ "    GROUP BY a.applicationid "
					+ "           "
					+ "),   "
					+ "RTOs_canales_minimos AS (     "
					+ "	SELECT  ab.applicationid,     "
					+ "			c.id AS channel_id,     "
					+ "			MIN(ei.rtoqty) AS rto_minimo_canal     "
					+ "	FROM main.evalprocapps ab     "
					+ "	INNER JOIN main.evalprocesses eval ON eval.id = ab.evalprocessid "
					+ "	INNER JOIN main.campaignunits cu ON eval.campaignunitid = cu.id "
					+ "    INNER JOIN main.campaigns c ON cu.campaingid = c.id "
					+ "	INNER JOIN CampanasConRanking cr ON c.id = cr.id "
					+ "	INNER JOIN main.evalprocimpacts ei ON ei.evalprocessid = eval.id     "
					+ "	INNER JOIN main.applications a ON a.id = ab.applicationid     "
					+ "	INNER JOIN main.unitprocesses up ON up.id = eval.unitprocessid     "
					+ "	INNER JOIN main.processchannels pc ON pc.processid = up.processid     "
					+ "	INNER JOIN main.channels ch ON ch.id = pc.channelid AND a.channelids LIKE '%' || c.id || '%'     "
					+ "	WHERE   eval.appst = 1 AND eval.impactst = 1   "
					+ "	GROUP BY ab.applicationid, c.id     "
					+ "), "
					+ " canales_por_aplicacion AS (   "
					+ "    SELECT a.id,   "
					+ "        COALESCE(array_length(string_to_array(a.channelids, ','), 1), 0) AS numero_canales "
					+ "    FROM   "
					+ "        main.evalprocapps ab   "
					+ "    INNER JOIN main.evalprocesses eval   "
					+ "        ON eval.id = ab.evalprocessid AND eval.appst = 1 AND eval.impactst = 1 "
					+ "		INNER JOIN main.campaignunits cu ON eval.campaignunitid = cu.id "
					+ "    INNER JOIN main.campaigns c ON cu.campaingid = c.id "
					+ "	INNER JOIN main.evalprocimpacts t1 ON eval.id = t1.evalprocessid "
					+ "    INNER JOIN CampanasConRanking cr ON c.id = cr.id "
					+ "    INNER JOIN main.applications a ON a.id = ab.applicationid and a.status=1 "
					+ "    GROUP BY a.id  "
					+ "),   "
					+ "canales_con_info AS (     "
					+ "	SELECT   a.id AS application_id,     "
					+ "			array_to_string(ARRAY_AGG(c.id), ';') AS canales,     "
					+ "			array_to_string(ARRAY_AGG( c.name), ';') AS nombre_canales,     "
					+ "			array_to_string(ARRAY_AGG( c.channeltypepar), ';') AS tipo_canal,     "
					+ "			array_to_string(ARRAY_AGG( po.descr), ';') AS nombre_tipo_canal,     "
					+ "			array_to_string(ARRAY_AGG(CASE    "
					+ "			WHEN rto.rto_minimo_canal IS NULL THEN '0'   "
					+ "			ELSE rto.rto_minimo_canal   "
					+ "			END), ';') AS rtos_minimos_por_canal , "
					+ "			ca.numero_canales "
					+ "	FROM main.applications a     "
					+ "	 INNER JOIN UNNEST(string_to_array(a.channelids, ',')) AS channel_id_str ON TRUE     "
					+ "	 INNER JOIN main.channels c ON c.id = CAST(channel_id_str AS INTEGER)     "
					+ "	 LEFT JOIN RTOs_canales_minimos rto ON rto.applicationid = a.id AND rto.channel_id = c.id     "
					+ "	 LEFT JOIN canales_por_aplicacion ca ON a.id=ca.id "
					+ "	LEFT JOIN (     "
					+ "			SELECT   elemento ->> 'dsc' AS descr,     "
					+ "					 elemento ->> 'value' AS valor     "
					+ "			FROM main.params p, jsonb_array_elements(CAST(p.value AS jsonb)) AS elemento     "
					+ "			 WHERE p.paramname = 'CHANNEL_TYPE'     "
					+ "			) po ON c.channeltypepar = CAST(po.valor AS integer)     "
					+ "		GROUP BY a.id,ca.numero_canales     "
					+ "	), "
					+ " RTOsPotencialesPorAplicacion AS (   "
					+ "   SELECT "
					+ "        epa.applicationid, "
					+ "        MIN(ei.rtoqty) AS rtoqty, "
					+ "		cr.ranking_campana "
					+ "    FROM main.evalprocapps epa "
					+ "    JOIN main.evalprocesses ep ON epa.evalprocessid = ep.id "
					+ "    INNER JOIN main.campaignunits cu ON ep.campaignunitid = cu.id "
					+ "    INNER JOIN main.campaigns c ON cu.campaingid = c.id "
					+ "    JOIN main.evalprocimpacts ei ON ep.id = ei.evalprocessid "
					+ "    INNER JOIN CampanasConRanking cr ON c.id = cr.id "
					+ "    WHERE ep.appst = 1  AND ep.impactst = 1  "
					+ "    GROUP BY epa.applicationid, cr.ranking_campana "
					+ "),   "
					+ "RTOsMasProximosFinal AS (   "
					+ "    SELECT   "
					+ "        ranked_rto.applicationid,   "
					+ "        ranked_rto.rtoqty AS rtopr  "
					+ "    FROM (   "
					+ "        SELECT   "
					+ "            A.applicationid,   "
					+ "            A.rtoqty,   "
					+ "            ROW_NUMBER() OVER (   "
					+ "                PARTITION BY A.applicationid "
					+ "                ORDER BY A.ranking_campana ASC,    "
					+ "                    a.rtoqty ASC "
					+ "					 "
					+ "            ) AS rn   "
					+ "        FROM RTOsPotencialesPorAplicacion  A  "
					+ "    ) AS ranked_rto   "
					+ "    WHERE rn = 1   "
					+ ")   "
					+ "SELECT   "
					+ "    distinct cpa.id,   "
					+ "    a.name,   "
					+ "    cpea.numero_de_procesos,   "
					+ "	CASE  "
					+ "		WHEN ca1.numero_canales IS NULL THEN 0  "
					+ "		ELSE ca1.numero_canales "
					+ "	END numero_de_canales, "
					+ "	CASE   "
					+ "		WHEN ca1.canales IS NULL THEN '0'   "
					+ "		ELSE ca1.canales   "
					+ "	END canales,   "
					+ "    cpea.idprocesos,   "
					+ "    pr.valor AS codigo_tipo,   "
					+ "	pr.descr AS desc_tipo,     "
					+ "	po.valor AS codigo_drptest,   "
					+ "	po.descr AS desc_drptest,   "
					+ "	a.registered ,     "
					+ "    RMPF.rtopr, "
					+ "	services_agg.nombres_ofertas_servicio_agrupados,   "
					+ "	coalesce(services_agg.estado_horario_agrupado,'NO') estado_horario_agrupado,   "
					+ "	a.serviceoffers,  "
					+ "	cpea.nombre_procesos,     "
					+ "	cpea.tipo_proceso,     "
					+ "	cpea.nombre_tipo_proceso,     "
					+ "	cpea.linea,     "
					+ "	cpea.nombre_linea,   "
					+ "	cpea.rtoqty,   "
					+ "	ca1.nombre_canales,   "
					+ "	ca1.tipo_canal,    "
					+ "	ca1.nombre_tipo_canal,   "
					+ "	ca1.rtos_minimos_por_canal "
					+ "FROM main.applications a   "
					+ "INNER JOIN canales_por_aplicacion cpa ON cpa.id = a.id and a.status=1 "
					+ "INNER JOIN CantidadProcesosByEvaluacion cpea ON cpea.applicationid = a.id   "
					+ "LEFT JOIN (   "
					+ "    SELECT elemento ->> 'dsc' AS descr,   "
					+ "           elemento ->> 'value' AS valor   "
					+ "    FROM main.params p, jsonb_array_elements(CAST(p.value AS jsonb)) AS elemento   "
					+ "    WHERE p.paramname = 'APPS_TYPE'   "
					+ ") pr ON a.apptypepar = pr.valor  "
					+ "LEFT JOIN (   "
					+ "	SELECT elemento ->> 'dsc' AS descr,   "
					+ "		   elemento ->> 'value' AS valor   "
					+ "	FROM main.params p, jsonb_array_elements(CAST(p.value AS jsonb)) AS elemento   "
					+ "	WHERE p.paramname = 'APPS_YESNO' ) po ON a.drptestedpar = CAST(po.valor AS integer)  "
					+ "INNER JOIN RTOsMasProximosFinal RMPF ON RMPF.applicationid = a.id  "
					+ " LEFT JOIN canales_con_info ca1 ON ca1.application_id = a.id   "
					+ "LEFT JOIN LATERAL (   "
					+ "		SELECT STRING_AGG(s.name, ', ' ORDER BY t.ord) AS nombres_ofertas_servicio_agrupados,   "
					+ "				STRING_AGG(CASE WHEN s.offer_full = 1 THEN 'SI' ELSE 'NO' END, ', ' ORDER BY t.ord) AS estado_horario_agrupado   "
					+ "		FROM UNNEST(CAST(string_to_array(a.serviceoffers, ',') AS INTEGER[])) WITH ORDINALITY AS t(service_id, ord)   "
					+ "		JOIN main.serviceoffers s ON s.id = t.service_id   "
					+ "		) AS services_agg ON TRUE";
			
			String QueryTotal = "";
			String name = "a.name";
			String lowername = "LOWER(a.name)";
			String lowerdesc = "LOWER(a.dsc)";
			String LowerSearch = searchIn.toLowerCase();

			switch (searchIn) {
				case "": 
					QueryTotal = SentenciaBase + " WHERE TRUE = TRUE ";
					break;
	
				default: // viene con el parametro para buscar por el like
					QueryTotal = SentenciaBase + " WHERE ( " + lowername + " LIKE  " + "'%" + LowerSearch + "%'" + ") ";
			}
			
			switch (apptypeparIn) {
				case "": 
					QueryTotal = QueryTotal + " AND TRUE = TRUE ";
					break;
	
				default: // viene con el parametro para buscar por el like
					QueryTotal = QueryTotal + " AND CAST(a.apptypepar AS integer) =  " + apptypeparIn;
			}
			
			switch (drptestyesnoparIn) {
				case "": 
					QueryTotal = QueryTotal + " AND TRUE = TRUE ";
					break;
	
				default: // viene con el parametro para buscar por el like
					QueryTotal = QueryTotal + " AND a.drptestedpar =  " + drptestyesnoparIn;
			}
			
	
			switch (serviceofferidIn) {
				case 0:
					QueryTotal = QueryTotal + " AND TRUE = TRUE";
					break;

				default: // viene con el parametro para buscar por el like
					QueryTotal = QueryTotal + " AND CAST(string_to_array(a.serviceoffers, ',') AS INTEGER[]) @> ARRAY["
							+ serviceofferidIn + "] ";

			}


			String ordena = "";
			if (orderIn == 1 || orderIn == 2 || orderIn == 3 || orderIn == 4 || orderIn == 5 || orderIn == 6 || orderIn == 7 ) {
				ordena = " ASC";
			} 
			else 
				if (orderIn == -1 || orderIn == -2 || orderIn == -3 || orderIn == -4 || orderIn == -5 || orderIn == -6 || orderIn == -7 ) {
				ordena = " DESC";
				} else {
					String var2 = "";
					boolean bloked = false;
					RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var2);
					respuestaDto = new RespuestaMsgDto("Llamada al servicio malformado");
					estatus = HttpStatus.BAD_REQUEST;
					return new ResponseEntity(respuestaDto, estatus);
				}

			int absolutoOrden = Math.abs(orderIn);			

			switch (absolutoOrden) {
			case 1: // ordena por name
				QueryTotal = QueryTotal + " ORDER BY " + name + ordena;
				break;
			case 2:// ordena por tipo 

				QueryTotal = QueryTotal + " ORDER BY codigo_tipo " + ordena;
				break;
			case 3:// ordena por drptest
				QueryTotal = QueryTotal + " ORDER BY codigo_drptest " + ordena;
				break;
			case 4:// ordena por RTO min
				QueryTotal = QueryTotal + " ORDER BY RMPF.rtopr " + ordena;
				break;
			case 5:// ordena por RTO TI
				QueryTotal = QueryTotal + " ORDER BY " + " a.recuperation " + ordena;
				break;
			case 6:// ordena por nro de procesos
				QueryTotal = QueryTotal + " ORDER BY " + " numero_de_procesos " + ordena;
				break;
			case 7:// ordena por nro de canales
				QueryTotal = QueryTotal + " ORDER BY " + " numero_de_canales " + ordena;
				break;
			default:
				String var2 = "";
				boolean bloked = false;
				RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var2);
				respuestaDto = new RespuestaMsgDto("Llamada al servicio malformado");
				estatus = HttpStatus.BAD_REQUEST;
				return new ResponseEntity(respuestaDto, estatus);
			}

			List<AppTypeDto> tipoAppList = new ArrayList();
			List<AppyesnoDto> tipoAppYesnoList = new ArrayList();

			List<RankingAplicacionesResponseDto> listado = new ArrayList();
			Query query3;
			Query query4;
			Query query5;
			List<Object[]> resultadosTypes;
			List<Object[]> resultadosTypes2;

			AppTypeDto appTypeDto = new AppTypeDto();
			AppyesnoDto appTypeYesNoDto = new AppyesnoDto();

			String QueryTypes = "SELECT CAST(elem AS TEXT) " + "	FROM main.params pa, "
					+ "	jsonb_array_elements(CAST(pa.value AS jsonb)) AS elem " + "	WHERE pa.paramname = 'APPS_TYPE' ";

			String QueryAppyesno = "SELECT CAST(elem AS TEXT) " + "	FROM main.params pa, "
					+ "	jsonb_array_elements(CAST(pa.value AS jsonb)) AS elem " + "	WHERE pa.paramname = 'APPS_YESNO' ";

			query3 = entityManager.createNativeQuery(QueryTypes);

			resultadosTypes = query3.getResultList();
			JSONObject jsonObject;
			String jsonStringTipo = "";
			if (resultadosTypes.size() > 0) {
				for (Object tipos : resultadosTypes) {
					jsonStringTipo = (String) tipos; // Recupera el JSON como String
					jsonObject = new JSONObject(jsonStringTipo); // Convierte String a JSONObject
					// Extrae los valores del JSONObject
					String dsc = jsonObject.getString("dsc");
					String value = jsonObject.getString("value");

					appTypeDto.setDsc(dsc);
					appTypeDto.setValue(value);
					tipoAppList.add(appTypeDto);
					appTypeDto = new AppTypeDto();
				}
			}

			String QueryTypes2 = "SELECT CAST(elem AS TEXT) " + "	FROM main.params pa, "
					+ "	jsonb_array_elements(CAST(pa.value AS jsonb)) AS elem " + "	WHERE pa.paramname = 'APPS_YESNO' ";

			query4 = entityManager.createNativeQuery(QueryTypes2);

			resultadosTypes2 = query4.getResultList();
			JSONObject jsonObject2;
			String jsonStringTipo2 = "";
			if (resultadosTypes2.size() > 0) {
				for (Object tipos2 : resultadosTypes2) {
					jsonStringTipo2 = (String) tipos2; // Recupera el JSON como String
					jsonObject2 = new JSONObject(jsonStringTipo2); // Convierte String a JSONObject
					// Extrae los valores del JSONObject
					String dsc = jsonObject2.getString("dsc");
					String value = jsonObject2.getString("value");

					appTypeYesNoDto.setDsc(dsc);
					appTypeYesNoDto.setValue(value);
					tipoAppYesnoList.add(appTypeYesNoDto);
					appTypeYesNoDto = new AppyesnoDto();
				}
			}
			
			

			query = entityManager.createNativeQuery(QueryTotal);
			cuantosregistro = (long) query.getResultList().size();
			query.setFirstResult(offsetIn);
			query.setMaxResults(numofrecordsIn);


			List<Object[]> listacompleta = query.getResultList();
			
			if (formatList==2 ) {
				  
			     String unit ="APPLICATIONS";
		        // response.setContentType("text/csv");
		         response.setContentType("text/csv; charset=UTF-8");
			     response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"Ranking_de_Aplicaciones.csv\"");
			     
			    try (PrintWriter writer = response.getWriter();
			                // CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT.withHeader( "UNIDADES", "PROCESOS" , "IM" , "AT" ,  "PR" , "RV" , "PC" ,  "IN" , "RR" ))) {
				//CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT.withHeader("CANAL" + ";"+ "TIPO", "PESO", "TX PROMEDIO MES", "MONTO TOTAL PROMEDIO MES", "CLIENTES MENSUAL", "RTO Min", "RTO Ti", "RTO Delta","Procesos","Aplicaciones"))) {
			    	CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT.withHeader("APLICACION" + ";"+ "TIPO" + ";"+ "DRPTEST" + ";"+ "RTO TI" + ";"+ "RTO MIN" + ";" + "PROCESOS"+ ";"+"CANALES"))) {		
			    	if (cuantosregistro > 0) {
			    		BigDecimal numeroBigDecimal;
			    		Integer numeroEntero;
			    		for (Object[] filaformat2 : listacompleta) {  
			    			
			    			 String aplicacion="";
							 String tipo="";
							 String drptest = "";
							 String rtoti = "";
							 String rtomin = "";
							 String procesos = "";
							 String canales = "";
							 
							 aplicacion = (String) filaformat2[1];
							 aplicacion = aplicacion.replace(',', ' ');
		                	  //cadenaOriginal.replace(',', ' ');
							 tipo = (String) filaformat2[7];
							 tipo = tipo.replace(',', ' ');
							 
							 drptest = (String) filaformat2[9];
							 numeroBigDecimal = (BigDecimal) filaformat2[10];
							 rtoti = numeroBigDecimal.toString();
							 numeroEntero = (Integer) filaformat2[11];
							 rtomin = numeroEntero.toString();
							 
							// seteando el numero de procesos
							 Integer procesosint;
							 try {
								 //BigDecimal bigDecimalValue = (BigDecimal) filaformat2[2];
								// int intValue = bigDecimalValue.intValue(); 
								  procesosint = (int) filaformat2[2];

							} catch (Exception e) {
								  procesosint = 0;

							}
						 
							 
							 String procesosstring = procesosint.toString();
							 procesos = procesosstring;
                               //33
							 //seteando el numero de apps
							 Integer canalesint;
							 try {
							    	 canalesint = (int) filaformat2[3];

								} catch (Exception e) {
									canalesint = 0;

								}
							 
							 
							
							 String canalesstring = canalesint.toString();
							 
							 canales = canalesstring;
							 
							/// terminando de setear los valores 
							 
							 String Imprimir = "\"" + aplicacion+ "\""  + ";" + "\""+ tipo +"\"" + ";" + "\"" + drptest + "\"" + ";" + "\"" + rtoti + "\""  + ";" + "\""+ rtomin + "\"" + ";" + "\"" + procesos + "\"" + ";" + "\"" + canales + "\"";
	                          csvPrinter.printRecord(Imprimir);
			    		}
			    		
			    	  }
			    	
			    	return new ResponseEntity(HttpStatus.OK);	
			    }
		  }	   
			
			
			if (formatList==1 || formatList==0 ) {
				RankingAplicacionesResponseDto rankingAplicacionesResponseDto= new RankingAplicacionesResponseDto();
				RankingAplicacionesResponseDto2 rankingAplicacionesResponseDto2= new RankingAplicacionesResponseDto2();
				List<RankingAplicacionesResponseDto2> listadoAplicaciones = new ArrayList();
				ApplicationDto3 applicationDto3 = new ApplicationDto3();
				TypeDto typeDto = new TypeDto();
				ProcessTypeDto3 processTypeDto3 = new ProcessTypeDto3();
				RtoDto  rtoDto = new RtoDto();
				DrptestedDto3 drptestedDto3 = new DrptestedDto3();
				ProcessRankingDto processRankingDto = new ProcessRankingDto();
				OperationlineDto4 operationline = new OperationlineDto4();
				ChannelsRankingDto channelsRankingDto = new ChannelsRankingDto();
				List<ProcessRankingDto> listaProcesos = new ArrayList();
				List<ChannelsRankingDto> listaCanales = new ArrayList();
				// Se de be hacer el ciclo para poder llenar el objeto de la descripcion del
				// estatus
				for (Object[] fila : listacompleta) {

					listaProcesos = new ArrayList();
					listaCanales =new ArrayList();
					applicationDto3.setId((int) fila[0]);
					applicationDto3.setName((String) fila[1]);
					typeDto.setId(Integer.parseInt((String)fila[6]));
					typeDto.setName((String) fila[7]);
					rtoDto.setMin((int) fila[11]);
					java.math.BigDecimal valorDecimal = (java.math.BigDecimal)fila[10];
					
					rtoDto.setTi(valorDecimal.intValue());
					String valorString = (String)fila[8];
					valorDecimal = new java.math.BigDecimal(valorString);
					drptestedDto3.setId(valorDecimal.intValue());
					drptestedDto3.setName((String) fila[9]);
					
					rankingAplicacionesResponseDto2.setApplication(applicationDto3);
					rankingAplicacionesResponseDto2.setType(typeDto);
					rankingAplicacionesResponseDto2.setRto(rtoDto);
					rankingAplicacionesResponseDto2.setDrptested(drptestedDto3);
					

					//Aqui vienen todos los procesos
					String IdProcesos = (String) fila[5]; 
					String rtosProcesos = String.valueOf(fila[20]); 
					String nombreProcesos = (String) fila[15]; 
					String tipoProcesos = (String) fila[16]; 
					String nombreTipoProcesos = (String) fila[17]; 
					String tipoLinea = (String) fila[18]; 
					String nombreLinea = (String) fila[19]; 
					if (IdProcesos != null && !IdProcesos.isEmpty() 
							&& rtosProcesos != null && !rtosProcesos.isEmpty()
							&&	nombreProcesos != null  && !nombreProcesos.isEmpty()
							&& tipoProcesos !=null && !tipoProcesos.isEmpty()
							&& nombreTipoProcesos != null && !nombreTipoProcesos.isEmpty()
							&& tipoLinea != null && !tipoLinea.isEmpty()
							&& nombreLinea !=null && !nombreLinea.isEmpty() ) {

						String[] IdProce = IdProcesos.split(";");
						String[] rtosProce = rtosProcesos.split(";");
						String[] nombreProce = nombreProcesos.split(";");
						String[] tipoProce = tipoProcesos.split(";");
						String[] nombreTipoProce = nombreTipoProcesos.split(";");
						String[] tipoLi = tipoLinea.split(";");
						String[] nombreLi = nombreLinea.split(";");
						int i = 0;
						
						for (String id : IdProce) {
							
							processRankingDto.setId(id == null ? 0 : Integer.parseInt(id));
							String NombrePr = nombreProce[i];
							processRankingDto.setName(NombrePr);
							String rtosPr = rtosProce[i];
							processRankingDto.setRtomin(id == null ? 0 : Integer.parseInt(rtosPr));
							String tipoPro = tipoProce[i];
							processTypeDto3.setId(id == null ? 0 : Integer.parseInt(tipoPro));
							String nombreTipoPr = nombreTipoProce[i];
							processTypeDto3.setDsc(nombreTipoPr);
							processRankingDto.setType(processTypeDto3);
							String tipo = tipoLi[i];
							String nombre = nombreLi[i];
							operationline.setDsc(nombre);
							operationline.setId(id == null ? 0 : Integer.parseInt(tipo));
							processRankingDto.setOperationline(operationline);
							listaProcesos.add(processRankingDto);
							operationline =  new OperationlineDto4();
							processTypeDto3 = new ProcessTypeDto3();
							processRankingDto = new ProcessRankingDto();
							i = i + 1;
						}
						
					} else {
						
						processRankingDto = new ProcessRankingDto();
						processRankingDto.setId(0);
						processRankingDto.setName("");
						processRankingDto.setRtomin(0);
						processTypeDto3.setId(0);
						processTypeDto3.setDsc("");
						processRankingDto.setType(processTypeDto3);
						operationline.setDsc("");
						operationline.setId(0);
						processRankingDto.setOperationline(operationline);
						listaProcesos.add(processRankingDto);
					}
					
					
					// Aqui vienen todos los canales
					String IdCanales = (String) fila[4];
					String rtosCanales = (String) fila[24]; 
					String nombreCanales = (String) fila[21]; 
					String tipoCanales = (String) fila[22]; 
					String nombreTipoCanales = (String) fila[23]; 
					if (IdCanales != null && !IdCanales.isEmpty() 
							&& rtosCanales != null && !rtosCanales.isEmpty()
							&&	nombreCanales != null  && !nombreCanales.isEmpty()
							&& tipoCanales !=null && !tipoCanales.isEmpty()
							&& nombreTipoCanales != null && !nombreTipoCanales.isEmpty() ) {

						String[] IdCan = IdCanales.split(";");
						String[] rtosCan = rtosCanales.split(";");
						String[] nombreCan = nombreCanales.split(";");
						String[] tipoCan = tipoCanales.split(";");
						String[] nombreTipoCan = nombreTipoCanales.split(";");
						int i = 0;
						
						for (String id : IdCan) {
							
								
							
									
							channelsRankingDto.setId(id == null ? 0 : Integer.parseInt(id));
							String NombreCan = nombreCan[i];
							channelsRankingDto.setName(NombreCan);
							String rtosCa = rtosCan[i];
							channelsRankingDto.setRtomin(id == null ? 0 : Integer.parseInt(rtosCa));
							String tipoCa = tipoCan[i];
							processTypeDto3.setId(id == null ? 0 : Integer.parseInt(tipoCa));
							String nombreTipoCa = nombreTipoCan[i];
							processTypeDto3.setDsc(nombreTipoCa);
							channelsRankingDto.setType(processTypeDto3);
							listaCanales.add(channelsRankingDto);
							processTypeDto3 = new ProcessTypeDto3();
							channelsRankingDto = new ChannelsRankingDto();
							i = i + 1;
							
						}
					} else {
						
						/*channelsRankingDto = new ChannelsRankingDto();
						channelsRankingDto.setId(0);
						channelsRankingDto.setName("");
						channelsRankingDto.setRtomin(0);
						processTypeDto3.setId(0);
						processTypeDto3.setDsc("");
						channelsRankingDto.setType(processTypeDto3);
						listaCanales.add(channelsRankingDto);*/
						
						//channelsRankingDto = new ChannelsRankingDto();
						listaCanales = new ArrayList();
						//listaCanales.add(null);
					}
					
					rankingAplicacionesResponseDto2.setProcesses(listaProcesos);
					rankingAplicacionesResponseDto2.setChannels(listaCanales);
					listadoAplicaciones.add(rankingAplicacionesResponseDto2);
					applicationDto3 = new ApplicationDto3();
					typeDto = new TypeDto();
					rtoDto = new RtoDto();
					drptestedDto3 = new DrptestedDto3();
					processRankingDto = new ProcessRankingDto();
					channelsRankingDto = new ChannelsRankingDto();
					rankingAplicacionesResponseDto2= new RankingAplicacionesResponseDto2();
					
					
				}

				rankingAplicacionesResponseDto.setNumofrecords(cuantosregistro);
				rankingAplicacionesResponseDto.setSessionvalidthru(fechaComoCadena);
				rankingAplicacionesResponseDto.setRecords(listadoAplicaciones);
				rankingAplicacionesResponseDto.setApptype(tipoAppList);
				rankingAplicacionesResponseDto.setAppyesno(tipoAppYesnoList);
				return ResponseEntity.ok(rankingAplicacionesResponseDto);
			}
			

		} catch (Exception e) {
			// Manejo de excepciones
			respuesta = new RespuestaDto("Error interno del servidor" + e.getMessage(), false);
			estatus = HttpStatus.INTERNAL_SERVER_ERROR;
		} finally {
			if (entityManager != null && entityManager.isOpen()) {
				entityManager.close();
			}
		}

		return new ResponseEntity(respuesta, estatus);

	}
}
