package com.dacrt.SBIABackend.controler;
import java.io.PrintWriter;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;
import javax.validation.Valid;

import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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.ApplicationResponseDto2;
import com.dacrt.SBIABackend.dto.CampaignFormat2Dto;
import com.dacrt.SBIABackend.dto.ChannelDto;
import com.dacrt.SBIABackend.dto.ChannelDto2;
import com.dacrt.SBIABackend.dto.DrptestDto;
import com.dacrt.SBIABackend.dto.EntryFollowEvalDto2;
import com.dacrt.SBIABackend.dto.FacilityDto2;
import com.dacrt.SBIABackend.dto.InstrumentsDto2;
import com.dacrt.SBIABackend.dto.ItemDto;
import com.dacrt.SBIABackend.dto.PeriodParResponseDto;
import com.dacrt.SBIABackend.dto.PrivilegesFollowsDto;
import com.dacrt.SBIABackend.dto.RecordCatalogoResponseDto;
import com.dacrt.SBIABackend.dto.RemedyRequestDto;
import com.dacrt.SBIABackend.dto.RisckElementColorsDto;
import com.dacrt.SBIABackend.dto.RiskElementMainDto;
import com.dacrt.SBIABackend.dto.RiskElementMainDto2;
import com.dacrt.SBIABackend.dto.RiskFactorMainDto;
import com.dacrt.SBIABackend.dto.RiskFactorMainDto2;
import com.dacrt.SBIABackend.dto.RiskFactorsElementDto;
import com.dacrt.SBIABackend.dto.RiskFactorsEntryRecordDto;
import com.dacrt.SBIABackend.dto.RiskFactorsEntryRecordDto2;
import com.dacrt.SBIABackend.dto.RiskFactorsRecordDto;
import com.dacrt.SBIABackend.dto.RiskFollowCloseDto;
import com.dacrt.SBIABackend.dto.RiskFollowOpenDto;
import com.dacrt.SBIABackend.dto.RiskFollowactionsDto;
import com.dacrt.SBIABackend.dto.RiskScalesDto;
import com.dacrt.SBIABackend.dto.RiskfollowupsDto;
import com.dacrt.SBIABackend.dto.RiskfollowupsDto2;
import com.dacrt.SBIABackend.dto.RiskfollowupsRecordsDto;
import com.dacrt.SBIABackend.dto.RiskfollowupsResponseDto;
import com.dacrt.SBIABackend.dto.RiskfollowupsSearchDto;
import com.dacrt.SBIABackend.dto.ScalesDto;
import com.dacrt.SBIABackend.dto.SceneryDto;
import com.dacrt.SBIABackend.dto.SceneryDto2;
import com.dacrt.SBIABackend.dto.ServiceOffersDescDto;
import com.dacrt.SBIABackend.dto.SeverityDto;
import com.dacrt.SBIABackend.dto.StateDto;
import com.dacrt.SBIABackend.dto.StatusDto;
import com.dacrt.SBIABackend.dto.StatusDto2;
import com.dacrt.SBIABackend.dto.StatusDto5;
import com.dacrt.SBIABackend.dto.TypesUnitDto;
import com.dacrt.SBIABackend.dto.entryRemedyDto;
import com.dacrt.SBIABackend.dto.scalesDtoAll;
import com.dacrt.SBIABackend.dto.requestDto.ChannelsRequestDto;
import com.dacrt.SBIABackend.dto.requestDto.RiskFactorElementDto;
import com.dacrt.SBIABackend.dto.requestDto.RiskFactorRequestDto;
import com.dacrt.SBIABackend.dto.responseDto.ApplicationResponseDto;
import com.dacrt.SBIABackend.dto.responseDto.ChannelsResponseDto;
import com.dacrt.SBIABackend.dto.responseDto.EntryFollowEvalDto;
import com.dacrt.SBIABackend.dto.responseDto.RickEntryRespondeDto;
import com.dacrt.SBIABackend.dto.responseDto.RiskCategoryResponseDto;
import com.dacrt.SBIABackend.dto.responseDto.RiskFactorsResponseDto;
import com.dacrt.SBIABackend.repository.ChannelsRepository;
import com.dacrt.SBIABackend.repository.FacilitiesRepository;
import com.dacrt.SBIABackend.repository.InstrumentriskfactorsRepository;
import com.dacrt.SBIABackend.repository.RiskFollowUpsRepository;
import com.dacrt.SBIABackend.repository.RiskevalfactorelementsRepository;
import com.dacrt.SBIABackend.repository.RiskevaluationsRepository;
import com.dacrt.SBIABackend.repository.RiskfactorelementsRepository;
import com.dacrt.SBIABackend.repository.RiskfactorsRepository;
import com.dacrt.SBIABackend.repository.RiskfollowupactionsRepository;
import com.dacrt.SBIABackend.repository.SuppliersRepository;
import com.dacrt.SBIABackend.security.dto.AuditRequestDto;
import com.dacrt.SBIABackend.security.dto.ParamsDto;
import com.dacrt.SBIABackend.security.dto.ParamsResponseDto;
import com.dacrt.SBIABackend.security.dto.PrivilegeAllCampaignDto;
import com.dacrt.SBIABackend.security.dto.PrivilegesAllDto;
import com.dacrt.SBIABackend.security.dto.PrivilegesDto;
import com.dacrt.SBIABackend.security.dto.RespuestaDto;
import com.dacrt.SBIABackend.security.dto.RespuestaMsgDto;
import com.dacrt.SBIABackend.security.dto.RespuestaValueDto;
import com.dacrt.SBIABackend.security.dto.RoleDto;
import com.dacrt.SBIABackend.security.dto.UsersListDto;
import com.dacrt.SBIABackend.security.entity.Params;
import com.dacrt.SBIABackend.security.entity.Roles;
import com.dacrt.SBIABackend.entity.Channels;
import com.dacrt.SBIABackend.entity.RiskFollowUps;
import com.dacrt.SBIABackend.entity.Riskevaluations;
import com.dacrt.SBIABackend.entity.Riskfactorelements;
import com.dacrt.SBIABackend.entity.Riskfactors;
import com.dacrt.SBIABackend.entity.Riskfollowupactions;
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.RolesPrivilegesRepository;
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;
import com.dacrt.SBIABackend.service.ChannelsService;
import com.dacrt.SBIABackend.service.RiskfactorelementsService;
import com.dacrt.SBIABackend.service.RiskfactorsService;
import com.dacrt.SBIABackend.utils.HttpReqRespUtils;

@Valid
@RestController
//@RequestMapping("/units")   
@CrossOrigin(origins = "*")

public class RiskfollowupsController {
	

	@Autowired
	private ParamsRepository paramsRepository;
	
	@Autowired
	private UsersRepository usersRepository;
	
	@Autowired
	private AuditRepository auditRepository;
	
	@Autowired
	private ChannelsRepository channelsRepository;
	
	@Autowired
	private RolesPrivilegesRepository rolesPrivilegesRepository;
	
	@Autowired
	UsersService usersService;
	
	@Autowired
	ParamsService paramsService;
	
	@Autowired
	ChannelsService channelsService;
	
	@Autowired
	SecurityService securityService;
	
	@Autowired
	MenuService menuService;
	
	@PersistenceContext
    private EntityManager entityManager;
	
	@Autowired
	SuppliersRepository suppliersRepository;
	
	@Autowired
	RiskfactorsRepository riskfactorsRepository;
	
	@Autowired
	FacilitiesRepository facilitiesRepository;
	
	@Autowired
	RiskFollowUpsRepository riskFollowUpsRepository;
	
	@Autowired
	RiskfollowupactionsRepository riskfollowupactionsRepository;
	
	@Autowired
	RiskevalfactorelementsRepository riskevalfactorelementsRepository;

	@Autowired
	RiskevaluationsRepository riskevaluationsRepository;
	
	@PostMapping("/riskfollowups")
	public ResponseEntity<?> riskfollowups(HttpServletRequest request, @RequestBody RiskfollowupsSearchDto tiposfiltros)
			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 drptestyesnoparSearch = "";
		String apptypeSearch = "";
		String contentIn = "";
		int serviceofferidIn = 0;
		int searchStatus = 0;
		int sceneryid = 0;
		int elementstatus = 0;
		int status3=0;
		String from="";
		String to="";

		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);
				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 seguimientos. (Priv 440)

				Roles roles = encontreSessionUsuario.get().getRolid();
				idrol = roles.getId();
				int rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol, 827);
				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);

				}

				/*
				 * 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 = tiposfiltros.getFilters().getSearch();
				searchStatus = tiposfiltros.getFilters().getElementstatus();
				sceneryid = tiposfiltros.getFilters().getSceneryid();
				status3 = tiposfiltros.getFilters().getStatus();
				from = tiposfiltros.getFilters().getDates().getFrom();
				to = tiposfiltros.getFilters().getDates().getTo();
				orderIn = tiposfiltros.getOrder();
				offsetIn = tiposfiltros.getOffset();
				contentIn = tiposfiltros.getContent();
				numofrecordsIn = tiposfiltros.getNumofrecords();

				String Salida = usersService.verificarCaracteresValidosConRegex(searchIn);

				if (Salida == "NOOK") {
					String var = "";
					boolean bloked = false;
					RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
					// respuestaDto.setBlocked(bloked);
					respuestaDto.setMsg("Caracteres no permitidos en la busqueda");
					return new ResponseEntity(respuestaDto, HttpStatus.BAD_REQUEST);
				}

				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 = "";
			String status="";
			
			//elementstatus
			switch (searchStatus) {
			case 0:
				status = " WHERE TRUE = TRUE ";
				break;
			case 1:
				status = " WHERE resultado.sin_asignar>0 ";
				break;
			case 2:
				status = " WHERE resultado.asignado>0 ";
				break;
			case 3:
				status = " WHERE resultado.en_proceso>0 ";
				break;
			case 4:
				status = " WHERE resultado.por_revisar>0 ";
				break;
			case 5:
				status = " WHERE resultado.cerrado>0 ";
				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);

			}
			String status4="";
			switch (status3) {
			case 0:
				status4 = " AND  1=1 ";
				break;
			case 1:
				status4 = " AND resultado.status_id=1 ";
				break;
			case 2:
				status4 = " AND resultado.status_id=2 ";
				break;
			case 3:
				status4 = " AND resultado.status_id=3 ";
				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);

			}
			
			String groubby=" GROUP BY    id,  "
					+ "          instrumentid,  "
					+ "			 instrumentname,  "
					+ "          scenery,   "
					+ "			 scenerydsc,  "
					+ "			 relateditem,  "
					+ "			 relateditemdsc,   "
					+ "			 sIni,   "
					+ "			 sFin,   "
					+ "			 fecha,"
					+ "          attenuator, "
					+ "          remedyprob, "
					+ "			 remedyimpact  ";

			SentenciaBase = "SELECT resultado.id,         "
					+ "				resultado.instrumentid,        "
					+ "				resultado.instrumentname,      "
					+ "				resultado.scenery,        "
					+ "				resultado.scenerydsc,        "
					+ "				resultado.relateditem,        "
					+ "				resultado.relateditemdsc,      "
					+ "				resultado.sIni,          "
					+ "				resultado.sFin,              "
					+ "				resultado.fecha,         "
					+ "				resultado.sin_asignar,        "
					+ "				resultado.asignado,        "
					+ "				resultado.en_proceso,        "
					+ "				resultado.por_revisar,        "
					+ "				resultado.cerrado,       "
					+ "				resultado.attenuator,    "
					+ "				resultado.status_id,    "
					+ "				resultado.status_name        "
					+ "  "
					+ " FROM (      SELECT  id,       "
					+ "              instrumentid,  "
					+ "			     instrumentname,  "
					+ "              scenery,   "
					+ "			     scenerydsc,  "
					+ "			     relateditem,  "
					+ "			     relateditemdsc,   "
					+ "			     coalesce(sIni,0) as sIni,    "
					+ "			     coalesce(sFin,0) as sFin,        "
					+ "			     fecha,   "
					+ "              SUM(sin_asignar) sin_asignar,  "
					+ "              SUM(asignado) asignado,  "
					+ "              SUM(en_proceso) en_proceso,  "
					+ "              SUM(por_revisar) por_revisar,  "
					+ "              SUM(cerrado) cerrado, "
					+ "					                attenuator,  "
					+ "        							CASE   "
					+ "							WHEN COUNT(CASE WHEN tiene_seguimiento = 1 THEN 1 END) > 0 "
					+ "							 AND COUNT(CASE WHEN mitigation IS NOT NULL THEN 1 END) > 0 "
					+ "							 AND remedyprob!=0 AND remedyimpact!=0 THEN 2  "
					+ "                                    ELSE 1  "
					+ "                                 END status_id,  "
					+ "                                 CASE  "
					+ "                         WHEN COUNT(CASE WHEN tiene_seguimiento = 1 THEN 1 END) > 0 "
					+ "							 AND COUNT(CASE WHEN mitigation IS NOT NULL THEN 1 END) > 0 "
					+ "							 AND remedyprob!=0 AND remedyimpact!=0 THEN 'Remediado'   "
					+ "                                    ELSE 'En Proceso'  "
					+ "                                 END status_name      "
					+ "					  FROM      "
					+ "					  (      "
					+ "					  SELECT  E.id,        "
					+ "	       E.instrumentid,   "
					+ "		   E.instrumentname,                   "
					+ "		   E.scenery,          "
					+ "		   E.scenerydsc,   "
					+ "		   E.relateditem,          "
					+ "		   E.relateditemdsc,    "
					+ "		   round(CAST(E.impact as NUMERIC))*round(CAST(E.probability as NUMERIC)) sIni, "
					+ "		   round(CAST(E.remedyprob as NUMERIC))*round(CAST(E.remedyimpact as NUMERIC)) sFin,   "
					+ "		   E.initialdate fecha,  "
					+ "        CASE WHEN (FL.id IS NULL) THEN 1 ELSE 0 END sin_asignar,  "
					+ "        CASE WHEN (FL.id IS NOT NULL AND FLA.id IS NULL) THEN 1 ELSE 0 END asignado,  "
					+ "        CASE WHEN (FLA.id IS NOT NULL AND FLA.progress <> 100) THEN 1 ELSE 0 END en_proceso,  "
					+ "        CASE WHEN (FLA.id IS NOT NULL AND FLA.progress =  100 AND FL.mitigation IS NULL) THEN 1 ELSE 0 END por_revisar,  "
					+ "					           CASE WHEN (FL.mitigation IS NOT NULL) THEN 1 ELSE 0 END cerrado,    "
					+ "					           E.attenuator, FL.mitigation as mitigation,  "
					+ "        					   FLA.progress as progreso_accion,  "
					+ "                           CASE WHEN FL.id IS NOT NULL THEN 1 ELSE 0 END as tiene_seguimiento,"
					+ "                           E.remedyprob, "
					+ "							  E.remedyimpact "
					+ "					  FROM        main.riskevaluations E      "
					+ "					  INNER JOIN  main.riskevalfactors F      "
					+ "					  ON          E.id=F.riskevaluationid AND E.status=0      "
					+ "					  INNER JOIN  main.riskevalfactorelements EL      "
					+ "					  ON          F.id=EL.riskevalfactorid and EL.active=1     "
					+ "					  LEFT JOIN   main.riskfollowups FL      "
					+ "					  ON          EL.id=FL.riskevalfactorelementid      "
					+ "					  LEFT JOIN   (SELECT riskfollowupid id, MAX(progress) progress FROM main.riskfollowupactions GROUP BY riskfollowupid) FLA      "
					+ "					  ON          FL.id=FLA.id      "
					+ "					  ) E"
					+ groubby
					+ ") resultado "
					+ status + status4;
					

			String QueryTotal = "";
			String instrumento = "instrumentname";
			String escenario = "scenerydsc";
			String item = "relateditemdsc";
			String lowerinstrumento = "LOWER(instrumentname)";
			String lowerescenario = "LOWER(scenerydsc)";
			String loweritem = "LOWER(relateditemdsc)";
			String LowerSearch = searchIn.toLowerCase();

			switch (searchIn) {
			case "":
				QueryTotal = SentenciaBase + " AND TRUE = TRUE";
				break;

			default: // viene con el parametro para buscar por el like
				QueryTotal = SentenciaBase + " AND (" + lowerinstrumento + " LIKE  " + "'%" + LowerSearch + "%'"
						+ " OR " + lowerescenario + " LIKE " + "'%" + LowerSearch + "%'" + " OR " + loweritem + " LIKE " + "'%"
						+ LowerSearch + "%'" + ")";

			}

			switch (sceneryid) {
			case 0: // Busca por cualquier escenario
				QueryTotal = QueryTotal;
				break;

			default: // viene con el parametro para buscar por el like
				QueryTotal = QueryTotal + " AND " + " scenery " + " = " + sceneryid;
				break;

			}
			
			LocalDate fechaDesde= LocalDate.now();
			LocalDate fechaHasta= LocalDate.now();;
			if (from!="") 
				fechaDesde = LocalDate.parse(from);
			
			if (to!="") 
				fechaHasta = LocalDate.parse(to);
	            
			String buscarFecha="";
			if (from!="" && to=="") 
				buscarFecha=" AND CAST(fecha AS date) >= '"+fechaDesde + "'";
			
			if (from=="" && to!="")
				buscarFecha=" AND CAST(fecha AS date) <= '"+fechaHasta + "'";
			    
			
			if (from!="" && to!="")
				buscarFecha = " AND CAST(fecha AS date) >= '" + fechaDesde + "' AND CAST(fecha AS date) <= '" + fechaHasta + "'";
			
			QueryTotal=QueryTotal+buscarFecha;
			String ordena = "";
			if (orderIn == 1 || orderIn == 2 || orderIn == 3 || orderIn == 4 || orderIn == 5 || orderIn == 6
					|| orderIn == 7 || orderIn == 8 || orderIn == 9 || orderIn == 10 || orderIn == 11 || orderIn == 12
					|| orderIn == 99) {
				ordena = " ASC";
			} else if (orderIn == -1 || orderIn == -2 || orderIn == -3 || orderIn == -4 || orderIn == -5
					|| orderIn == -6 || orderIn == -7 || orderIn == -8 || orderIn == -9 || orderIn == -10
					|| orderIn == -11 || orderIn == -12 || orderIn == -99) {
				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: // 1=escenario+instrumento
				QueryTotal = QueryTotal + " ORDER BY " + escenario + " " + ordena +  ", " +instrumento + " " + ordena;
				break;
			case 2:// 2=instrumento
				QueryTotal = QueryTotal + " ORDER BY " + instrumento + " " + ordena;
				break;
			case 3:// 3=item,
				QueryTotal = QueryTotal + " ORDER BY " + item + " " + ordena;
				break;
			case 4:// 4=Sev Inicial
				QueryTotal = QueryTotal + " ORDER BY " + " sIni " + ordena;
				break;
			case 5:// 5=Sev Final
				QueryTotal = QueryTotal + " ORDER BY " + " sFin " + ordena;
				break;
			case 6:// 6=Fecha,
				QueryTotal = QueryTotal + " ORDER BY " + " fecha " + ordena;
				break;
			case 7:// 7=Atenuador,
				QueryTotal = QueryTotal + " ORDER BY " + " attenuator " + ordena;
				break;
			case 8:// 8=sin asignar,
				QueryTotal = QueryTotal + " ORDER BY " + " sin_asignar " + ordena;
				break;
			case 9:// 8=sin asignar,
				QueryTotal = QueryTotal + " ORDER BY " + " asignado " + ordena;
				break;
			case 10:// 9=asignado,
				QueryTotal = QueryTotal + " ORDER BY " + " en_proceso " + ordena;
				break;
			case 11:// 10=en proceso,
				QueryTotal = QueryTotal + " ORDER BY " + " por_revisar " + ordena;
				break;
			case 12:// 11=por revisar,
				QueryTotal = QueryTotal + " ORDER BY " + " cerrado " + ordena;
				break;
			case 99: // 99=id (negativos ordenan descendentemente)
				QueryTotal = QueryTotal + " ORDER BY " + " id " + 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);
			}

			
			RiskfollowupsResponseDto riskfollowupsResponseDto = new RiskfollowupsResponseDto();
			RiskfollowupsRecordsDto riskfollowupsRecordsDto = new RiskfollowupsRecordsDto();
			List<RiskfollowupsRecordsDto> records = new ArrayList();
			List<SceneryDto2> sceneries = new ArrayList();
			List<SceneryDto2> severitycolors= new ArrayList();
			List<SceneryDto2> colorseveritys = new ArrayList();
			List<StatusDto2> statusList = new ArrayList();
			SceneryDto2 sceneryDto2 = new SceneryDto2();
			SceneryDto2 sceneryDtoColor = new SceneryDto2();
			PrivilegesAllDto privileges = new PrivilegesAllDto();			
			InstrumentsDto2 instrument = new InstrumentsDto2();
			SceneryDto scenery= new SceneryDto();
			ItemDto item2= new ItemDto();
			SeverityDto severity= new SeverityDto();
			String date= "";
			
			StatusDto2 status2 = new StatusDto2();
			StatusDto5 status5= new StatusDto5();
			
			Query query;
			Query query2;
			Query query3;
			Query querycolor;
			List<Object[]> resultadosTypes;
			List<Object[]> resultadosTypes2;
			List<Object[]> resultadosTypes3;
			List<Object[]> resultadosColor;

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

			query2 = entityManager.createNativeQuery(QueryTypes);
			
		
			resultadosTypes = query2.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");

					sceneryDto2.setDsc(dsc);
					sceneryDto2.setValue(value);
					sceneries.add(sceneryDto2);
					sceneryDto2 = new SceneryDto2();
				}
			}
			
			////////////////////OBTENIENDO EL RISKCOLORSEVERITY///////////////
			/*String QueryTypesColor = "SELECT CAST(elem AS TEXT) " + "FROM main.params pa, "
					+ "	jsonb_array_elements(CAST(pa.value AS jsonb)) AS elem "
					+ "	WHERE pa.paramname = 'RISK_COLORSEVERITY' ";

			querycolor = entityManager.createNativeQuery(QueryTypesColor);
			resultadosColor = querycolor.getResultList();
			
			JSONObject jsonObjectCOLOR;
			String jsonStringTipoCOLOR = "";
			if (resultadosColor.size() > 0) {
				for (Object tipos : resultadosColor) {
					jsonStringTipoCOLOR = (String) tipos; // Recupera el JSON como String
					jsonObjectCOLOR = new JSONObject(jsonStringTipoCOLOR); // Convierte String a JSONObject
					// Extrae los valores del JSONObject
					String dsc = jsonObjectCOLOR.getString("dsc");
					String value = jsonObjectCOLOR.getString("value");

					sceneryDtoColor.setDsc(dsc);
					sceneryDtoColor.setValue(value);
					severitycolors.add(sceneryDtoColor);
					sceneryDtoColor = new SceneryDto2();
				}
			}*/
			
			///////////////////////////////
			
			
			String QueryTypes2 = " SELECT id, name "
								+ " FROM ( "
								+ "    VALUES  "
								+ "        (1, 'En Proceso'), "
								+ "        (2, 'Por Mitigar'), "
								+ "        (3, 'Cerrado') "
								+ ") AS status(id, name) ";

			query3 = entityManager.createNativeQuery(QueryTypes2);

			resultadosTypes3 = query3.getResultList();
			jsonStringTipo = "";
			if (resultadosTypes3.size() > 0) {
				for (Object[] tipos : resultadosTypes3) {
					status2.setId((Integer)tipos[0]);
					status2.setName((String)tipos[1]);
					statusList.add(status2);
					status2 = new StatusDto2();
				}
			}
			System.out.println(QueryTotal);
			
			query = entityManager.createNativeQuery(QueryTotal);
			cuantosregistro = (long) query.getResultList().size();
			query.setFirstResult(offsetIn);
			query.setMaxResults(numofrecordsIn);

			List<Object[]> listacompleta = query.getResultList();
			
			for (Object[] fila : listacompleta) {
				riskfollowupsRecordsDto.setId((int) fila[0]);
				instrument.setId((int) fila[1]);
				instrument.setName((String) fila[2]);
				riskfollowupsRecordsDto.setInstrument(instrument);
				scenery.setId((int) fila[3]);
				scenery.setName((String) fila[4]);
				riskfollowupsRecordsDto.setScenery(scenery);
				item2.setId((int) fila[5]);
				item2.setName((String) fila[6]);
				riskfollowupsRecordsDto.setItem(item2);
				if (fila[9] != null) {
				    java.sql.Timestamp ts = (java.sql.Timestamp) fila[9];
				    // Formato simple: 2026-04-27
				    String fechaFormateada = ts.toLocalDateTime().toLocalDate().toString(); 
				    riskfollowupsRecordsDto.setDate(fechaFormateada);
				} else {
				    riskfollowupsRecordsDto.setDate("");
				}
				severity.setFinals((BigDecimal) fila[8]);
				severity.setInitial((BigDecimal) fila[7]);
				riskfollowupsRecordsDto.setSeverity(severity);
				status5.setAssigned((BigInteger) fila[11]);
				status5.setClosed((BigInteger) fila[14]);
				status5.setForreview((BigInteger) fila[13]);
				status5.setInprocess((BigInteger) fila[12]);
				status5.setNotassigned((BigInteger) fila[10]);
				status2.setId((Integer) fila[16]);
				status2.setName((String) fila[17]);
				riskfollowupsRecordsDto.setElementstatus(status5);
				riskfollowupsRecordsDto.setStatus(status2);
				records.add(riskfollowupsRecordsDto);
				
				instrument = new InstrumentsDto2();
				scenery= new SceneryDto();
				item2= new ItemDto();
				severity= new SeverityDto();
				date= "";
				status5= new StatusDto5();
				status2= new StatusDto2();
				riskfollowupsRecordsDto=new RiskfollowupsRecordsDto();
			}

			privileges = new PrivilegesAllDto();
			boolean tieneView = rolesPrivilegesRepository.existsByRolidAndPrivilegeid(idrol, 827);
			boolean tieneUpdate = rolesPrivilegesRepository.existsByRolidAndPrivilegeid(idrol, 828);

			privileges.setView(tieneView);
			privileges.setUpdate(tieneUpdate);

			riskfollowupsResponseDto.setNumofrecords(cuantosregistro);
			riskfollowupsResponseDto.setSessionvalidthru(fechaComoCadena);
			riskfollowupsResponseDto.setRecords(records);
			riskfollowupsResponseDto.setSceneries(sceneries);
			//riskfollowupsResponseDto.setSeveritycolors(severitycolors);
			riskfollowupsResponseDto.setStatus(statusList);
			riskfollowupsResponseDto.setPrivileges(privileges);
			return ResponseEntity.ok(riskfollowupsResponseDto);

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

	}
	
	@GetMapping("/riskfollowups/{riskevaluationid}")
	public ResponseEntity<?> getoneriskfollowups(HttpServletRequest request, @PathVariable("riskevaluationid") final Integer riskevaluationid) throws ParseException {
		
		  int idrol;
	   	  String searchIn = "";
	   	  String contentIn = "";
	     // String searchModule = "";
		  int searchStatus = 0;
		  int typeIn=0;
		  String fechaComoCadena; 
		 int orderIn = 0;
		 int offsetIn = 0;
		 int numofrecordsIn = 0;
		 Date fecha2 = new Date();
         Long cuantosregistro = (long) 0;
     	RickEntryRespondeDto detalleRickEntryRespondeDto=null;
		RiskFactorsRecordDto detalleRiskFactorsRecordDto;
		List<RiskFactorsRecordDto> listasRiskFactorsRecordDto= new ArrayList<>();
         List<TypesUnitDto> listasTypes = new ArrayList<>();
	     List<RiskFactorsEntryRecordDto> listasRecordRisk= new ArrayList<>();
	     
	     PrivilegesFollowsDto detallePrivilege;
	     
	     TypesUnitDto detalleTypes;
	     RiskScalesDto detalleTypes2;
	     TypesUnitDto detallePeriodos;
	     entryRemedyDto remedysession;
	     List<TypesUnitDto> listasPeriodos = new ArrayList<>();
	     List<ScalesDto> scalespro = new ArrayList<>();
	     List<ScalesDto> scales = new ArrayList<>();
		 String sessionid = request.getHeader("Authorization");
		 RiskFactorsEntryRecordDto riskRecordDto = new RiskFactorsEntryRecordDto();
		  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();
		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);
			//   String usuarioIN = encontreSessionUsuario.get().getUsr();
			 //  int position = usuarioIN.indexOf('('); 
			   
			   if (encontreSessionUsuario.isPresent()) {
				   
				   Date FechaReg = encontreSessionUsuario.get().getValidthru(); 

				   //fechaComoCadena  = securityService.consultarSessionActiva(FechaReg,fecha2);
				   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);
					   
				    }
				
				    if (!riskevaluationsRepository.existsById(riskevaluationid)) {
				    	   String var = "";
							boolean bloked = false;
							RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
							//respuestaDto.setBlocked(bloked);
							respuestaDto.setMsg("Registro no encontrado"); 
							return new ResponseEntity(respuestaDto, HttpStatus.NOT_FOUND);
				    }
				    
				    if (!riskevaluationsRepository.existsByIdAndStatus(riskevaluationid,0)) {
				    	   String var = "";
							boolean bloked = false;
							RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
							//respuestaDto.setBlocked(bloked);
							respuestaDto.setMsg("La evaluación no esta cerrada"); 
							return new ResponseEntity(respuestaDto, HttpStatus.CONFLICT);
				    }
				    
				  // Este proceso permite obtener un listado de los proveedores. (Priv 440)
				   Roles roles = encontreSessionUsuario.get().getRolid();
				   idrol = roles.getId();
				   int rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol, 827);
				
				        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);
				        }	
				    
					  						 				
					  
					  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 {
	        // ... (Tu código de validación de sesión y privilegios aquí) ...
	    	String SentenciaBase;
	    	// SentenciaBase = "SELECT new com.dacrt.SBIABackend.dto.ChannelsDtoStatus (u.id,u.name,u.status,CASE WHEN u.status = 1 then 'Activo' ELSE 'Inactivo' END AS estatus) FROM Channels u";
	    	String SentenciaStatus="SELECT " +
		            "    CASE " +
		            "        WHEN COUNT(CASE WHEN tiene_seguimiento = 1 AND mitigation IS NULL THEN 1 END) = 0 " +
		            "            AND COUNT(CASE WHEN tiene_seguimiento = 1 THEN 1 END) > 0 THEN 3 " +
		            "        WHEN MAX(progreso_accion) = 100 " +
		            "            AND COUNT(CASE WHEN mitigation IS NULL THEN 1 END) > 0 THEN 2 " +
		            "        ELSE 1 " +
		            "    END AS statusId, " + // Alias en camelCase para que coincida con el método de la proyección
		            "    CASE " +
		            "        WHEN COUNT(CASE WHEN tiene_seguimiento = 1 AND mitigation IS NULL THEN 1 END) = 0 " +
		            "            AND COUNT(CASE WHEN tiene_seguimiento = 1 THEN 1 END) > 0 THEN 'Cerrado' " +
		            "        WHEN MAX(progreso_accion) = 100 AND COUNT(CASE WHEN mitigation IS NULL THEN 1 END) > 0 THEN 'Por Mitigar' " +
		            "        ELSE 'En Proceso' " +
		            "    END AS statusName " + // Alias en camelCase
		            "FROM ( " +
		            "    SELECT " +
		            "        E.id, " +
		            "        E.attenuator, " +
		            "        FL.mitigation as mitigation, " +
		            "        FLA.progress as progreso_accion, " +
		            "        CASE WHEN FL.id IS NOT NULL THEN 1 ELSE 0 END as tiene_seguimiento " +
		            "    FROM main.riskevaluations E " +
		            "    INNER JOIN main.riskevalfactors F " +
		            "        ON E.id = F.riskevaluationid AND E.status = 0 " +
		            "    INNER JOIN main.riskevalfactorelements EL " +
		            "        ON F.id = EL.riskevalfactorid AND EL.active = 1 " +
		            "    LEFT JOIN main.riskfollowups FL " +
		            "        ON EL.id = FL.riskevalfactorelementid " +
		            "    LEFT JOIN ( " +
		            "        SELECT riskfollowupid id, MAX(progress) progress " +
		            "        FROM main.riskfollowupactions " +
		            "        GROUP BY riskfollowupid " +
		            "    ) FLA ON FL.id = FLA.id " +
		            ") E " +
		            "WHERE E.id = ?1";
	    	
	    	Query query2;
	    	query2 = entityManager.createNativeQuery(SentenciaStatus);
	    	query2.setParameter(1, riskevaluationid);
	        List<Object[]> listacompleta2 = query2.getResultList();
	        StatusDto2 statusDto=new StatusDto2(); 
	        for (Object[] reg2 : listacompleta2) {
	        	statusDto.setId((Integer) reg2[0]);
	        	statusDto.setName((String) reg2[1]);
	        	
	        }
			
			SentenciaBase = " SELECT "
					+ "    e.id as ideva, "
					+ "    i.id as idisnt, "
					+ "    i.name as nombinst, "
					+ "    e.scenery, "
					+ "    e.scenerydsc, "
					+ "    e.relateditem, "
					+ "    e.relateditemdsc, "
					+ "    e.impact, "
					+ "    e.probability, "
					//+ "    -- Formateo de fecha a Texto YYYY-MM-DD"
					+ "    TO_CHAR(e.enddate, 'YYYY-MM-DD') AS enddate, "
					+ "    re.id AS factor_id ,"
					+ "    re.riskfactornam, "
					+ "    rele.id AS ideleme, "
					+ "    rele.riskfactorelementdsc AS nameleme, rele.impact as impac_ele, rele.probability as prob_ele," 
					+ "    ups.id AS idfollow, "
					+ "    ups.name AS namefollow, "
					+ "    ups.responsable, "
					+ "    TO_CHAR(ups.estfinishdate, 'YYYY-MM-DD') AS estfinishdate, "
					+ "    TO_CHAR(ups.createdat, 'YYYY-MM-DD') AS createdat, "
					+ "    TO_CHAR(ups.finishdate, 'YYYY-MM-DD') AS finishdate, "
					//+ "    -- Campos Agrupados"
					+ "    STRING_AGG(TO_CHAR(a.date, 'YYYY-MM-DD'), ' | ' ORDER BY a.date) AS fechas_acciones, "
					+ "    STRING_AGG(a.action, ' | ' ORDER BY a.date) AS resumen_acciones, "
					+ "    STRING_AGG(CAST(a.progress AS TEXT), ' | ' ORDER BY a.date) AS progresos_acciones, "
				
					//+ "    -- Lógica de Estatus"
					+ "    CASE "
					+ "        WHEN ups.id IS NULL THEN 'Sin asignar' "
					+ "        WHEN ups.mitigation IS NOT NULL THEN 'Cerrado' "
					+ "        WHEN COUNT(a.id) = 0 THEN 'Asignado' "
					+ "        WHEN MAX(a.progress) = 100 AND ups.mitigation IS NULL THEN 'Por revisar' "
					+ "        ELSE 'En Proceso' "
					+ "    END AS status, "
					+ "   ups.mitigation as idmitig, "
					+ "    (SELECT elemento ->> 'dsc' "
					+ "     FROM main.params p, jsonb_array_elements(CAST(p.value AS jsonb)) AS elemento "
					+ "     WHERE p.paramname = 'RISK_MITIGATION' "
					+ "     AND (elemento ->> 'value') = CAST(ups.mitigation AS TEXT) LIMIT 1) as namemitig, cast(e.remedyprob as integer), "
					+ "	    cast(e.remedyimpact as integer),remedydsc,ups.validator,(rele.impact * rele.probability) AS riesgo_total  "
					+ " FROM main.riskevaluations e "
					+ " JOIN main.instruments i ON i.id = e.instrumentid "
					+ " JOIN main.riskevalfactors re ON re.riskevaluationid = e.id "
					+ "  JOIN main.riskevalfactorelements rele ON rele.riskevalfactorid = re.id "
					+ " LEFT JOIN main.riskfollowups ups ON ups.riskevalfactorelementid = rele.id "
					+ " LEFT JOIN main.riskfollowupactions a ON a.riskfollowupid = ups.id "
					+ " WHERE e.id = " + riskevaluationid + " and rele.active= " + 1;
			String groupby = " GROUP BY "
					+ "    e.id,i.id,i.name,e.scenery,e.scenerydsc,e.relateditem,e.relateditemdsc,re.id, re.riskfactornam,rele.impact, rele.probability, "
					+ " 	e.impact,e.probability,e.enddate,"
					+ "  rele.id, rele.riskfactorelementdsc, "
					+ "    ups.id, ups.name, ups.responsable, ups.estfinishdate,ups.createdat, ups.finishdate, ups.mitigation"
					+ " ORDER BY riesgo_total DESC ";
			
			Query query;
	        String queryTotal = SentenciaBase + groupby; // El query que construimos
	         query = entityManager.createNativeQuery(queryTotal);
	        List<Object[]> listacompleta = query.getResultList();

	        if (listacompleta.isEmpty()) {
	            return ResponseEntity.notFound().build();
	        }

	        EntryFollowEvalDto entry = new EntryFollowEvalDto();
	        Map<Integer, RiskFactorMainDto> factorsMap = new LinkedHashMap<>();

	        for (Object[] reg : listacompleta) {
	            // 1. Llenar datos de la Evaluación (Solo la primera vez)
	            if (entry.getId() == null) {
	                entry.setId((Integer) reg[0]);
	                entry.setInstrument(new StateDto((Integer) reg[1], (String) reg[2]));
	                entry.setScenery(new StateDto((Integer) reg[3], (String) reg[4]));
	                entry.setElement(new StateDto((Integer) reg[5], (String) reg[6]));
	                entry.setImpact(reg[7] != null ? new BigDecimal(reg[7].toString()) : BigDecimal.ZERO);
	                entry.setProbability(reg[8] != null ? new BigDecimal(reg[8].toString()) : BigDecimal.ZERO);
	                remedysession = new entryRemedyDto();
	                entry.setStatus(statusDto);
	                remedysession.setImpact((Integer) reg[29]);
	                remedysession.setProbability((Integer) reg[28]);
	                remedysession.setDsc((String) reg[30]);
	                
	                entry.setRemedy(remedysession);
	                
	                if ((String) reg[9]==null) {
	                	entry.setDate("");
	                } else {
	                	entry.setDate((String) reg[9]);
	                }
	                 // createdat de ups o e
	                
	                if ((String) reg[20]==null) {
	                	entry.setCreationdate("");
	                } else {
	                	entry.setCreationdate((String) reg[20]);
	                }
	              //  BigDecimal impactColor  = (BigDecimal) reg[7];
	              //  BigDecimal impactPro  = (BigDecimal) reg[8];
	                ////////////////////query para capturar el color//////////////
	              /*  String coloreval = " WITH valor_calculado AS ( "
	                		+ "    SELECT  "
	                		+ "        (CASE  "
	                		+ "            WHEN ((re.impact - 1) * 5 + re.probability) < 0 THEN 1 "
	                		+ "            ELSE ROUND((re.impact - 1) * 5 + re.probability)::integer "
	                		+ "         END)::text AS resultado_id "
	                		+ "    FROM main.riskevaluations re  "
	                		+ "    WHERE id =  " + riskevaluationid
	                		+ " ) "
	                		+ "SELECT  "
	                		+ "    elem->>'dsc' AS descripcion  "
	                		+ "FROM main.params, "
	                		+ "LATERAL json_array_elements(value::json) AS elem "
	                		+ "JOIN valor_calculado vc ON (elem->>'value') = vc.resultado_id "
	                		+ "WHERE paramname = 'RISK_COLORSEVERITY' ";*/
	                ////////////////////////////////////////////////////////////////
	                entry.setColor(riskevaluationsRepository.findRiskDescriptionById(riskevaluationid));
	            }

	            // 2. Agrupar por Factores
	            Integer factorId = (Integer) reg[10];
	            RiskFactorMainDto factor = factorsMap.computeIfAbsent(factorId, k -> {
	                RiskFactorMainDto f = new RiskFactorMainDto();
	                f.setId(factorId);
	                f.setName((String) reg[11]);
	                f.setElements(new ArrayList<>());
	                return f;
	            });

	            // 3. Crear el Elemento
	            RiskElementMainDto element = new RiskElementMainDto();
	            List<RiskElementMainDto> elements = new ArrayList<>();
	            
	                element.setId((Integer) reg[12]);
	                element.setName((String) reg[13]);
	           	    element.setImpact((BigDecimal) reg[14]);
	                element.setProbability((BigDecimal) reg[15]);
	                	                           
	                BigDecimal unoimpact = (BigDecimal) reg[14];
	                BigDecimal valorimpact = unoimpact;
	                String impactcolor =valorimpact.toBigInteger().toString();
	                
	             
	                
                        //////////////////////////COLOR IMPACTO///////////////////////////
	                  // query para  buscar los colores
	                  String sentenciaColorImpact = "SELECT elemento ->> 'dsc' "
	                	        + "FROM main.params p, jsonb_array_elements(CAST(p.value AS jsonb)) AS elemento "
	                	        + "WHERE p.paramname = 'RISK_COLORIMPACT' "
	                	        + "AND elemento ->> 'value' = :valorImpacto";

	                	Query queryColor = entityManager.createNativeQuery(sentenciaColorImpact);
	                	queryColor.setParameter("valorImpacto", impactcolor); // impactcolor es "1", "2", etc.
	                	

	                	List<Object> res = queryColor.getResultList();
	                	String finalColor = res.isEmpty() ? "#FFFFFF" :  res.get(0).toString();
	                	//////////////////////////COLOR PROBABILIDAD///////////////////////////
	                	   BigDecimal unoprob = (BigDecimal) reg[15];
	   	                   BigDecimal valorProba = unoprob;
	   	                    String impactProbab =valorProba.toBigInteger().toString();
	   	               	
	                	 String sentenciaColorProba = "SELECT elemento ->> 'dsc' "
		                	        + "FROM main.params p, jsonb_array_elements(CAST(p.value AS jsonb)) AS elemento "
		                	        + "WHERE p.paramname = 'RISK_COLORPROB' "
		                	        + "AND elemento ->> 'value' = :valorProba";

		                	Query queryColorProba = entityManager.createNativeQuery(sentenciaColorProba);
		                	queryColorProba.setParameter("valorProba", impactProbab); // impactcolor es "1", "2", etc.

		                	List<Object> respro = queryColorProba.getResultList();
		                	String finalColorProb = respro.isEmpty() ? "#FFFFFF" : respro.get(0).toString();
		                	
	                      //////////////////////////COLOR PROBABILIDAD///////////////////////////	
	                      //////////////////////////COLOR SEVERIDAD///////////////////////////
		                	   BigDecimal unoseverity =  unoprob.multiply(unoimpact);
		   	                   BigDecimal valorSeverity = unoseverity;
		   	                    String impactSeverity =valorSeverity.toBigInteger().toString();
		   	               	
		                	 String sentenciaColorSeve = "SELECT elemento ->> 'dsc' "
			                	        + "FROM main.params p, jsonb_array_elements(CAST(p.value AS jsonb)) AS elemento "
			                	        + "WHERE p.paramname = 'RISK_COLORSEVERITY' "
			                	        + "AND elemento ->> 'value' = :valorseve";

			                	Query queryColorSeve= entityManager.createNativeQuery(sentenciaColorSeve);
			                	queryColorSeve.setParameter("valorseve", impactSeverity); // impactcolor es "1", "2", etc.

			                	List<Object> reseve = queryColorSeve.getResultList();
			                	String finalColorSeve = reseve.isEmpty() ? "#FFFFFF" : reseve.get(0).toString();
			                	
		                      //////////////////////////COLOR PROBABILIDAD///////////////////////////	
	                	element.setColors(new RisckElementColorsDto(finalColor, finalColorProb, finalColorSeve));
	                
	 	                element.setStatus((String) reg[25]); // El CASE status del query
	 	                
	            // 4. Llenar Followups (si existen)
	                // List<RiskfollowupsDto> follow = new ArrayList<>();   
	                  RiskfollowupsDto follow = new RiskfollowupsDto();
	            if (reg[16] != null) { // idfollow
	             //   RiskfollowupsDto follow = new RiskfollowupsDto();
	                
	                // Open section
	                follow.setOpen(new RiskFollowOpenDto((String) reg[17], (String) reg[18], (String) reg[19]));

	                // Actions section (Parsear las strings concatenadas con " | ")
	                List<RiskFollowactionsDto> actionsList = new ArrayList<>();
	                if (reg[22] != null) {
	                    String[] dates = reg[22].toString().split(" \\| ");
	                    String[] descs = reg[23].toString().split(" \\| ");
	                    String[] progs = reg[24].toString().split(" \\| ");
	                    for (int i = 0; i < dates.length; i++) {
	                        actionsList.add(new RiskFollowactionsDto(dates[i], descs[i], Integer.parseInt(progs[i].trim())));
	                    }
	                }
	                follow.setActions(actionsList);

	                // Close section
	                StateDto mitigation = new StateDto();
	                mitigation.setId(reg[26] != null ? Integer.parseInt(reg[26].toString()) : 0); // Ajustar índice según tu query
	                mitigation.setName(reg[27] != null ? (String) (reg[27]) : ""); // Ajustar índice según tu query
	                
	               // mitigation.setName((String) reg[27]); // Nombre de mitigación
	                
	                follow.setClose(new RiskFollowCloseDto(mitigation, Optional.ofNullable((String) reg[31]).orElse(""), Optional.ofNullable((String) reg[21]).orElse("")));
	                
	                
	            } else {
	            	// SI NO HAY DATOS (Caso que solicitas): Inicializar con valores por defecto/vacíos
	                
	                // 1. Inicializar Open con strings vacíos
	                follow.setOpen(new RiskFollowOpenDto("", "", ""));

	                // 2. Inicializar Actions como lista vacía (ya lo hace el constructor usualmente, pero aseguramos)
	                follow.setActions(new ArrayList<>());

	                // 3. Inicializar Close con objeto mitigation y strings vacíos
	                StateDto emptyMitigation = new StateDto(0, ""); // id 0, name ""
	                follow.setClose(new RiskFollowCloseDto(emptyMitigation, "", ""));
	            }
	            element.setFollowups(follow);
	           // element.setFollowups("");
	            factor.getElements().add(element);
	        }

	        entry.setRiskfactors(new ArrayList<>(factorsMap.values()));

	     	/////MITIGACION
   	  	 String SetenciaSceneries="";
				
   	  	SetenciaSceneries= "SELECT  elemento ->> 'dsc' AS descr,elemento ->> 'value' AS valor "
		 		+ " FROM main.params p, jsonb_array_elements(CAST(p.value AS jsonb)) AS elemento WHERE paramname = 'RISK_MITIGATION' ORDER BY valor ASC";
		      
		      Query queryTypes = entityManager.createNativeQuery(SetenciaSceneries);
		       List<Object[]> listasceneries= queryTypes.getResultList();
		       for (Object[] types : listasceneries) {
		    	   detalleTypes = new TypesUnitDto();
		    	  
		    	   detalleTypes.setDsc((String) types[0]);
		    	   detalleTypes.setValue((String) types[1]);
		    	   listasTypes.add(detalleTypes);
		       }
		       detalleRickEntryRespondeDto = new RickEntryRespondeDto();
		    //   detalleRickEntryRespondeDto.setEntry(riskRecordDto);
		     //  detalleRickEntryRespondeDto.setSceneries(listasTypes);
	   	    ////////////////TERMINO DE RECORRER EL PARAMETRO DE MITIGACIONES
		    //// AQUI COMIENZO PARA BUSCAR EL PARAMETRO DE ESCALAS////////////   
		   	//scalesDtoAll detalleImpact;
				scalesDtoAll detalleImpact = new scalesDtoAll();
				String SetenciascalesImpact = "";
				
				SetenciascalesImpact =  " SELECT elemento ->> 'dsc' AS descr,"
				          + "      elemento ->> 'value' AS valor,"
				          + "      elemento ->> 'filter' AS lng "
				          + " FROM main.params p, jsonb_array_elements(CAST(p.value AS jsonb)) AS elemento "
				          + " WHERE paramname = 'RISK_SCALEIMPACT' ORDER BY valor ASC ";
				          
				Query queryScales = entityManager.createNativeQuery(SetenciascalesImpact);
				List<Object[]> listascales = queryScales.getResultList();
				ScalesDto scal;
				ScalesDto scal2;
				for (Object[] scales2 : listascales) {
					scal = new ScalesDto();
					scal.setDsc(scales2[0] != null ? scales2[0].toString() : "");
				    scal.setValue(scales2[1] != null ? scales2[1].toString() : "");
				    scal.setLng(scales2[2] != null ? scales2[2].toString() : ""); 
				    scales.add(scal);
				}
				
				detalleImpact.setImpact(scales);
				
				String SetenciascalesProb = "";
				
				SetenciascalesProb =  " SELECT elemento ->> 'dsc' AS descr,"
				          + "      elemento ->> 'value' AS valor,"
				          + "      elemento ->> 'filter' AS lng "
				          + " FROM main.params p, jsonb_array_elements(CAST(p.value AS jsonb)) AS elemento "
				          + " WHERE paramname = 'RISK_SCALEPROB' ORDER BY valor ASC ";
				          
				Query querySetenciascalesProb = entityManager.createNativeQuery(SetenciascalesProb);
				List<Object[]> listaProb= querySetenciascalesProb.getResultList();
				ScalesDto pro;
				for (Object[] scales2 : listaProb) {
					scal2 = new ScalesDto();
					scal2.setDsc(scales2[0] != null ? scales2[0].toString() : "");
					scal2.setValue(scales2[1] != null ? scales2[1].toString() : "");
					scal2.setLng(scales2[2] != null ? scales2[2].toString() : ""); 
					scalespro.add(scal2);
				}
				detalleImpact.setProbability(scalespro);
				
				detallePrivilege = new PrivilegesFollowsDto();
     	    	 // Roles roles = encontreSessionUsuario.get().getRolid();
				  // int idrol = roles.getId();
				  // int rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol, 100);
				   boolean tieneView = rolesPrivilegesRepository.existsByRolidAndPrivilegeid(idrol,827);
				   boolean tieneUpdate = rolesPrivilegesRepository.existsByRolidAndPrivilegeid(idrol,828);
				   boolean tieneClose = rolesPrivilegesRepository.existsByRolidAndPrivilegeid(idrol,830);
				   boolean tieneUpdateafterclose= rolesPrivilegesRepository.existsByRolidAndPrivilegeid(idrol,831);				   
				//   boolean tieneUpdateStatus = rolesPrivilegesRepository.existsByRolidAndPrivilegeid(idrol,104);
				   //existsByRolidAndPrivilegeid
				   
     	    	 	detallePrivilege.setView(tieneView);
		    	  	detallePrivilege.setUpdate(tieneUpdate);		    	  
		    	  	detallePrivilege.setClose(tieneClose);
		    	  	detallePrivilege.setUpdateafterclose(tieneUpdateafterclose);
		    	  //	detallePrivilege.setUpdateStatus(tieneUpdateStatus);
	        
	        // 5. Construir respuesta final
	        Map<String, Object> response = new HashMap<>();
	        response.put("entry", entry);
	        response.put("mitigation", listasTypes); // La que ya tienes
	        response.put("scales", detalleImpact);   // La que ya tienes
	        response.put("privileges", detallePrivilege);   // La que ya tienes

	        return ResponseEntity.ok(response);

	    } catch (Exception e) {
	        return new ResponseEntity<>(new RespuestaDto("Error: " + e.getMessage(), false), HttpStatus.INTERNAL_SERVER_ERROR);
	    }  finally {
			if (entityManager != null && entityManager.isOpen()) {
				entityManager.close();
			}
		}
	}

  @Transactional(rollbackOn = Exception.class) 
  @PostMapping("/riskfollowups/{riskevaluationid}")
	public ResponseEntity<?> upsertRiskFollowups(
	        HttpServletRequest request, 
	        @PathVariable("riskevaluationid") Integer riskevaluationid,
	        @RequestBody EntryFollowEvalDto2 requestDto) {
	  Optional<Users> encontreSessionUsuario;   
	  Date fecha2 = new Date();
	   Calendar calendar = Calendar.getInstance();
	   RespuestaValueDto respuestaValueDto = null;
		RespuestaMsgDto respuesta = new RespuestaMsgDto("");
		HttpStatus estatus = HttpStatus.FORBIDDEN;
	    // 1. (Opcional) Validación de sesión y roles aquí...
	  String sessionid = request.getHeader("Authorization");
	  if (sessionid==null) {
			String var = "";
			boolean bloked = false;
			RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
			//respuestaDto.setBlocked(bloked);
			respuestaDto.setMsg("Llamada al servicio malformado");
			//Error 400
			return new ResponseEntity(respuestaDto, HttpStatus.BAD_REQUEST);
		} else   {
			 
			   sessionid = sessionid.substring(7);
			   encontreSessionUsuario =usersRepository.getBySessionid(sessionid);
		       String fechaComoCadena;
			   
			   if (encontreSessionUsuario.isPresent()) {
				   
				   Date FechaReg = encontreSessionUsuario.get().getValidthru();
				   
				   //Llamada a la funcion que validad el tiempo de Session, retorna la fecha sumandole el tiempo de session activa, y vacio si no esta activa
				   
				  //  fechaComoCadena  = securityService.consultarSessionActiva(FechaReg,fecha2);
				   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);
					   
				    }
				    
				    if (!riskevaluationsRepository.existsById(riskevaluationid)) {
				    	   String var = "";
							boolean bloked = false;
							RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
							//respuestaDto.setBlocked(bloked);
							respuestaDto.setMsg("Registro no encontrado"); 
							return new ResponseEntity(respuestaDto, HttpStatus.NOT_FOUND);
				    }
				    
				    
				    Roles roles = encontreSessionUsuario.get().getRolid();
					  int idrol = roles.getId();
					   int rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol, 828);
					   int rolisvalid2 = auditRepository.getCantbyRolAndPrivi(idrol, 831);
					
					        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);
					        }	
					        if (rolisvalid2==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);
							        }	
					    
						  						 				
						 
				    
			   }
		}		    
	    try {
	    	Riskevaluations objeto = riskevaluationsRepository.getById(riskevaluationid);
	        // Recorremos los factores de riesgo del JSON
	        for (RiskFactorMainDto2 factor : requestDto.getRiskfactors()) {
	            
	            // Recorremos los elementos de cada factor
	            for (RiskElementMainDto2 element : factor.getElements()) {
	                
	            	if (!riskevalfactorelementsRepository.existsById(element.getId())) {
	                    throw new RuntimeException("El ID de la evaluación del elemento de riesgo no existe.");
	                    //return new ResponseEntity<>(new RespuestaDto("Error al guardar: " + e.getMessage(), false), 
	        	          //      HttpStatus.INTERNAL_SERVER_ERROR);
	                }
	                // Solo procesamos si trae información de followups
	                if (element.getFollowups() != null) {
	                	
	                    processFollowup(element,encontreSessionUsuario.get().getEmail(),riskevaluationid,objeto.getInstrumentid());
	                }
	            }
	        }
	        
	 		   
			estatus=HttpStatus.OK;
			return new ResponseEntity(riskevaluationid, estatus); 
	        //return ResponseEntity.ok(new RespuestaMsgDto(riskevaluationid.toString()));

	    } catch (Exception e) {
	        return new ResponseEntity<>(new RespuestaDto("Error al guardar: " + e.getMessage(), false), 
	                HttpStatus.INTERNAL_SERVER_ERROR);
	      //  throw new RuntimeException(e.getMessage());
	    }
	}
	
	private void processFollowup(RiskElementMainDto2 element,String email,int idEval,int instrumento) throws ParseException {
	    Integer elementId = element.getId(); // riskevalfactorelementid
	    RiskfollowupsDto2 followupDto = element.getFollowups();
	    Date fecha = new Date();
	    SimpleDateFormat  formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dataFormattata = formatter.format(fecha);
        Date fechaDate = formatter.parse(dataFormattata);
        RespuestaValueDto respuestaValueDto;
      		RespuestaMsgDto respuesta = new RespuestaMsgDto("");
      		HttpStatus estatus = HttpStatus.FORBIDDEN;
	    // 1. Buscar si ya existe un seguimiento para este elemento
	    // Suponiendo que tienes un repositorio para RiskFollowups
	    Optional<RiskFollowUps> existingFollow = riskFollowUpsRepository.findByRiskevalfactorelementid(elementId);
	                                             
	    RiskFollowUps followEntity = existingFollow.orElse(new RiskFollowUps());
	    String elimine = "SI";
	  
	    
	    if (followupDto.getOpen().getName().equals("")) {
	    	
	         	boolean existeElement = riskFollowUpsRepository.existsByRiskevalfactorelementid(elementId);
	    	
	    	      if (existeElement) {
	    	    	    elimine = "SI";
	    	    	    riskFollowUpsRepository.deleteByRiskevalfactorelementid(elementId);
	             	} else { 
	             		elimine = "NO";
	             	}
	    	
	     } else {
	   // boolean existeElement = riskFollowUpsRepository.existsByRiskevalfactorelementid(elementId);
	    // 2. Mapear datos del "Open"
	   // if (elimine.equals("SI")) {
	    	
	    	  if (existingFollow.isPresent()) { 
	  	    	//followEntity.setCreatedAt(fechaDate);
	  	    	followEntity.setModifiedat(fechaDate);
	  	    } else 
	  	       {
	  	    	followEntity.setCreatedat(fechaDate);
	  	    	followEntity.setModifiedat(fechaDate);
	  	       }
	    
	    if (followupDto.getOpen() != null) {
	    	
	    	
	    	
	        followEntity.setRiskevalfactorelementid(elementId);
	        followEntity.setName(followupDto.getOpen().getName());
	        followEntity.setResponsable(followupDto.getOpen().getResponsable());
	        Date valor  = parseDate(followupDto.getOpen().getEstenddate());
	        followEntity.setEstfinishdate(valor);
	    }
	    
	    // 3. Mapear datos del "Close" (Si la mitigación es > 0 se considera cierre)
	  //  if (followupDto.getClose() != null && followupDto.getClose().getMitigation() > 0) {
	 // 3. Mapear datos del "Close"
	    if (followupDto.getClose() != null) {
	        
	        // Manejo de Mitigación
	        if (followupDto.getClose().getMitigation() == null || followupDto.getClose().getMitigation() == 0) {
	            followEntity.setMitigation(null);
	        } else {
	            followEntity.setMitigation(followupDto.getClose().getMitigation());
	        }

	        // Manejo de EndDate (Finishdate)
	        String endDateStr = followupDto.getClose().getEnddate();
	        if (endDateStr != null && !endDateStr.trim().isEmpty()) {
	            // Asegúrate de que parseDate maneje bien el formato que viene en el JSON
	            followEntity.setFinishdate(parseDate(endDateStr));
	        } else {
	            followEntity.setFinishdate(null);
	        }

	        // Manejo de Responsable (Validator)
	        String responsable = followupDto.getClose().getResponsable();
	        if (responsable != null && !responsable.trim().isEmpty()) {
	            followEntity.setValidator(responsable);
	        } else {
	            followEntity.setValidator("");
	        }
	    } else {
	        // Si el objeto Close es nulo en el JSON, limpiamos los campos
	        followEntity.setMitigation(null);
	        followEntity.setFinishdate(null);
	    }

	    // Guardar el padre (RiskFollowups)
	    followEntity = riskFollowUpsRepository.save(followEntity);

	    // 4. Procesar Acciones (Approach: Borrar anteriores y re-insertar)
	    // Esto es más limpio cuando el usuario puede quitar o poner acciones en el grid
	    if (followupDto.getActions() != null) {
	        // Borrar acciones existentes para este ID de seguimiento
	    	riskfollowupactionsRepository.deleteByRiskfollowupid(followEntity.getId());
	        
	        for (RiskFollowactionsDto actDto : followupDto.getActions()) {
	        	Riskfollowupactions actionEntity = new Riskfollowupactions();
	            actionEntity.setRiskFollowUpId(followEntity.getId());
	            actionEntity.setDate(parseDate(actDto.getDate()));
	            actionEntity.setAction(actDto.getDsc());
	            actionEntity.setProgress(actDto.getProgress());
	            
	            riskfollowupactionsRepository.save(actionEntity);
	        }
	    }
	    String Descmodule ="";
	    if (existingFollow.isPresent()) {  
	    	  Descmodule = "Se actualizo el seguimiento de evaluación de riesgos de la Evaluación con Id:" + idEval + " Elemento ID : " + elementId + ", Instrumento ID:" + instrumento + ", Plan de Accion con Nombre:" + followupDto.getOpen().getName() ;
	 	    
	    } else {
	    	  Descmodule = "Se creo el seguimiento de evaluación de riesgos de la Evaluación con Id:" + idEval + " Elemento ID : " + elementId + ", Instrumento ID:" + instrumento + ", Plan de Accion con Nombre:" + followupDto.getOpen().getName() ;
	 	    
	    }
        AuditRequestDto  auditDto=new AuditRequestDto();
        fechaDate = formatter.parse(dataFormattata);
    	respuestaValueDto= new RespuestaValueDto(idEval);
    	   //////////////////////////INSERCION BLOQUE DE AUDITORIA///////////////////
	     String module = "Seguimiento de Evaluacion de Riesgos";
	     //String Descmodule = "Actualización de parametro del Sistema con id: " + parmid  ;
	    // Se creó (o actualizco) el seguimiento de evaluación de riesgos para la Evaluación ID: 302 Elemento ID: [X], Instrumento ID: [X] Plan de Accion ID: [X] 
	    
         auditDto.setIpaddr(HttpReqRespUtils.getClientIpAddressIfServletRequestExist());			        
         
         String singo1 = "(";
         String singo2 = ")";
         String usryemail = email;
         auditDto.setUserref(usryemail);
         auditDto.setModule(module);
         auditDto.setDesc(Descmodule);
         auditDto.setCreatedat(fechaDate);
 		   usersService.registrarAuditSesion(auditDto); 
	   
	}
}
	// Helper para parsear fechas string a Date
	private Date parseDate(String dateStr) {
	    if (dateStr == null || dateStr.isEmpty()) return null;
	    try {
	        return new SimpleDateFormat("yyyy-MM-dd").parse(dateStr);
	    } catch (Exception e) {
	        return null;
	    }
	}
	
	@PostMapping("/riskfollowups/{riskevaluationid}/remedy")
	public ResponseEntity<?> remedy(HttpServletRequest request, 
			@RequestBody RemedyRequestDto remedy,
			@PathVariable("riskevaluationid") Integer riskevaluationid)
			throws ParseException {
		RespuestaDto respuesta = new RespuestaDto("", false);
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		
		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();
		Optional<Users> encontreSessionUsuario;
		int idrol;
		int rolisvalid;
		
		String fechaComoCadena;
		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");
			return new ResponseEntity(respuestaDto, HttpStatus.BAD_REQUEST);
		} else {

			sessionid = sessionid.substring(7);
			encontreSessionUsuario = usersRepository.getBySessionid(sessionid);

			if (encontreSessionUsuario.isPresent()) {

				Date FechaReg = encontreSessionUsuario.get().getValidthru();

				// fechaComoCadena = securityService.consultarSessionActiva(FechaReg,fecha2);
				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);

				}
				
				/*String Salida = usersService.verificarCaracteresValidosConRegex(remedy.getDsc());

				if (Salida == "NOOK") {
					String var = "";
					boolean bloked = false;
					RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
					respuestaDto.setMsg("Caracteres no permitidos en el campo descripción del remedy");
					return new ResponseEntity(respuestaDto, HttpStatus.BAD_REQUEST);
				}*/

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

		try {
			
			Optional<Riskevaluations> riskevaluas= riskevaluationsRepository.findById(riskevaluationid);

			// Verifico si encontre la evaluación
			if (!riskevaluas.isPresent()) {
				respuesta.setMsg("Registro no encontrado");
				return new ResponseEntity(respuesta, HttpStatus.NOT_FOUND);
			}
						
			Riskevaluations riskeval=riskevaluas.get();

			Roles roles = encontreSessionUsuario.get().getRolid();
			idrol = roles.getId();
			//Valido que se pueda cerrar el remedy
			rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol, 830);
			
			if ((riskeval.getRemedyprob()==null || riskeval.getRemedyprob().compareTo(BigDecimal.ZERO) == 0)
					&& (riskeval.getRemedyimpact()==null || riskeval.getRemedyimpact().compareTo(BigDecimal.ZERO) == 0) 
					&& rolisvalid == 0) {
				String var = "";
				boolean bloked = false;
				RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
				respuestaDto.setMsg("No tiene los Privilegios");
				return new ResponseEntity(respuestaDto, HttpStatus.FORBIDDEN);

			}
			
			
			rolisvalid=0;
			
			//Valido que se pueda editar el remedy
			rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol, 831);
			
			if ((riskeval.getRemedyprob()==null || riskeval.getRemedyprob().compareTo(BigDecimal.ZERO) != 0)
					&& (riskeval.getRemedyimpact()==null || riskeval.getRemedyimpact().compareTo(BigDecimal.ZERO) != 0)
					&& rolisvalid==0) {
				String var = "";
				RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
				respuestaDto.setMsg("No tiene los Privilegios");
				return new ResponseEntity(respuestaDto, HttpStatus.FORBIDDEN);
			}
				
			String Descmodule="";
			if ((riskeval.getRemedyprob()==null || riskeval.getRemedyprob().compareTo(BigDecimal.ZERO) == 0)
					&& (riskeval.getRemedyimpact()==null || riskeval.getRemedyimpact().compareTo(BigDecimal.ZERO) == 0))	
				Descmodule = "Se registró la remediación de la Evaluación "  + riskeval.getId() + ", con remediación de probabilidad: "+remedy.getProbability()+ " y remediación de Impacto: "+remedy.getImpact();
			else
				Descmodule = "Se modificó la remediación de la Evaluación "  + riskeval.getId() + ", con remediación de probabilidad: "+remedy.getProbability()+ " y remediación de Impacto: "+remedy.getImpact();

			riskeval.setRemedydsc(remedy.getDsc());
			riskeval.setRemedyimpact(new BigDecimal(remedy.getImpact()));
			riskeval.setRemedyprob(new BigDecimal(remedy.getProbability()));
			riskevaluationsRepository.save(riskeval);
			
			String module = "Actualización de Remediación de la Evaluación";

		    auditDto.setIpaddr(HttpReqRespUtils.getClientIpAddressIfServletRequestExist());
		    String singo1 = "(";
		    String singo2 = ")";
		    String usryemail = encontreSessionUsuario.get().getUsr().concat(" ").concat(singo1)
		            .concat(encontreSessionUsuario.get().getEmail().concat(singo2));
		    
		    auditDto.setUserref(usryemail);
		    auditDto.setModule(module);
		    auditDto.setDesc(Descmodule); // Usar la descripción de modificación
		    auditDto.setCreatedat(fechaDate);
		    usersService.registrarAuditSesion(auditDto);

		    
			RespuestaValueDto respuestaValueDto = new RespuestaValueDto(riskeval.getId());
			URI location = URI.create("/riskfollowups/"+riskeval.getId()+"/remedy" ); 

			return ResponseEntity.created(location).body(respuestaValueDto);

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

	}
	
}
