package com.dacrt.SBIABackend.controler;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.DeleteMapping;
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.ContactDto;
import com.dacrt.SBIABackend.dto.EntryRequestersDto;
import com.dacrt.SBIABackend.dto.EntryRequestersDto2;
import com.dacrt.SBIABackend.dto.FacilitResponseDto2;
import com.dacrt.SBIABackend.dto.FacilitiesResponseDto;
import com.dacrt.SBIABackend.dto.FacilitiesResponseDto2;
import com.dacrt.SBIABackend.dto.FacilitiesResponseDto3;
import com.dacrt.SBIABackend.dto.IddscDto;
import com.dacrt.SBIABackend.dto.OperationlineDto;
import com.dacrt.SBIABackend.dto.ProcessRemoteDto;
import com.dacrt.SBIABackend.dto.ProcessResponseDto;
import com.dacrt.SBIABackend.dto.ProcessTypeDto;
import com.dacrt.SBIABackend.dto.RequestersListDto;
import com.dacrt.SBIABackend.dto.RequestersRecordsDto;
import com.dacrt.SBIABackend.dto.RequestersRecordsDto2;
import com.dacrt.SBIABackend.dto.RequestersRecordsDto4;
import com.dacrt.SBIABackend.dto.RequestersRequestDto;
import com.dacrt.SBIABackend.dto.RequestersResponseDto;
import com.dacrt.SBIABackend.dto.RequestersResponseDto3;
import com.dacrt.SBIABackend.dto.ServiceoffersDto;
import com.dacrt.SBIABackend.dto.StatusDto;
import com.dacrt.SBIABackend.dto.StatusDto2;
import com.dacrt.SBIABackend.dto.TypeReportDto;
import com.dacrt.SBIABackend.dto.TypeResponseDto;
import com.dacrt.SBIABackend.dto.TypeResponseDto2;
import com.dacrt.SBIABackend.dto.TypesUnitDto;
import com.dacrt.SBIABackend.dto.requestDto.FacilitiesRequestDto;
import com.dacrt.SBIABackend.dto.responseDto.FacilitiesEntryDto;
import com.dacrt.SBIABackend.entity.Facilities;
import com.dacrt.SBIABackend.entity.Requesters;
import com.dacrt.SBIABackend.entity.Resources;
import com.dacrt.SBIABackend.entity.Serviceoffers;
import com.dacrt.SBIABackend.repository.RequestersRepository;
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.PrivilegesAllDto;
import com.dacrt.SBIABackend.security.dto.PrivilegesDto;
import com.dacrt.SBIABackend.security.dto.RespuestaMsgDto;
import com.dacrt.SBIABackend.security.dto.RespuestaValueDto;
import com.dacrt.SBIABackend.security.entity.Params;
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.PrivilegesRepository;
import com.dacrt.SBIABackend.security.repository.UsersRepository;
import com.dacrt.SBIABackend.security.service.MenuService;
import com.dacrt.SBIABackend.security.service.SecurityService;
import com.dacrt.SBIABackend.security.service.UsersService;
import com.dacrt.SBIABackend.utils.HttpReqRespUtils;

@RestController
@CrossOrigin(origins = "*")
public class RequestersController {
	@PersistenceContext
	private EntityManager entityManager;

	@Autowired
	private PrivilegesRepository privilegesRepository;

	@Autowired
	private ParamsRepository paramsRepository;

	@Autowired
	private AuditRepository auditRepository;

	@Autowired
	private UsersRepository usersRepository;

	@Autowired
	MenuService menuService;

	@Autowired
	SecurityService securityService;

	@Autowired
	UsersService usersService;

	@Autowired
	RequestersRepository requestersRepository;

	Logger logger = LoggerFactory.getLogger(RequestersController.class);

	@PostMapping("/requesters")
	public ResponseEntity<?> listarRequesters(HttpServletRequest request, @RequestBody RequestersListDto tiposfiltros)
			throws ParseException {
		RespuestaMsgDto respuesta = new RespuestaMsgDto("");
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		long cuantosregistro = 0;

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

		String searchIn = "";
		int statusIn = 0;
		int typeIn = 0;
		int channelIdIn = 0;
		int formatList = 0;

		String searchModule = "";
		String searchUsr = "";
		String contentIn = "";
		int orderIn = 0;
		int offsetIn = 0;
		int numofrecordsIn = 0;
		int rolisvalid = 0;

		Optional<Params> deSessDuration = paramsRepository.findByParamname("SESSION_DURATION");
		String SessionDuration = deSessDuration.get().getValue();
		int duracionSession = Integer.parseInt(SessionDuration);
		Date fecha2 = new Date();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(fecha2); // tuFechaBase es un Date;
		// calendar.add(Calendar.MINUTE, minutosASumar); //minutosASumar es int.
		calendar.add(Calendar.MINUTE, duracionSession); // horasASumar es int.
		// lo que más quieras sumar
		Date ValidThrufechaSalida = calendar.getTime(); // Y ya tienes la fecha sumada.
		SimpleDateFormat salida = new SimpleDateFormat("yyyy-MM-dd HH:mm"); // 2024-12-23 23:00
		String fechaComoCadena = salida.format(ValidThrufechaSalida);
		System.out.println(fechaComoCadena);

		// Verifico la session
		if (sessionid == null) {
			respuesta.setMsg("Llamada al servicio malformado");
			estatus = HttpStatus.BAD_REQUEST;
			return new ResponseEntity(respuesta, estatus);
		} else {
			sessionid = sessionid.substring(7);
			// verifico si la sesión del usuario existe.
			Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(sessionid);
			if (encontreSessionUsuario.isPresent()) { // si la sesión del usuario existe
				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,
						encontreSessionUsuario.get().getId());

				if (fechaComoCadena == "") {
					RespuestaMsgDto respuestaDto2;
					String var2 = "";
					boolean bloked2 = false;
					respuestaDto2 = new RespuestaMsgDto(var2);
					respuestaDto2.setMsg("Sesión expirada o inválida");
					return new ResponseEntity(respuestaDto2, HttpStatus.UNAUTHORIZED);
				}

				// Obtengo el rol de usuario y verifico si corresponde al privilegio del usuario
				rolisvalid = auditRepository.getCantbyRolAndPrivi(encontreSessionUsuario.get().getRolid().getId(), 450);
				if (rolisvalid == 0) {
					respuesta.setMsg("No tiene los Privilegios");
					estatus = HttpStatus.FORBIDDEN;
					return new ResponseEntity(respuesta, estatus);
				}

				// Obtengo los datos del Body
				formatList = tiposfiltros.getFormat();
				searchIn = tiposfiltros.getFilters().getSearch();// dato de busqueda por nombre

				String Salida1 = usersService.verificarCaracteresValidosConRegex(searchIn);

				if (Salida1 == "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);
				}

				typeIn = tiposfiltros.getFilters().getType();// dato de busqueda por type
				statusIn = tiposfiltros.getFilters().getStatus();// dato de busqueda por status
				orderIn = tiposfiltros.getOrder(); // Orden Ascedente o Descendente
				offsetIn = tiposfiltros.getOffset();// Primer registro a mostrar
				numofrecordsIn = tiposfiltros.getNumofrecords();// Número de registros a mostrar
				// Verifico los Shorcouts
				if (contentIn != null && contentIn != "")
					menuService.iscontentdiffnull(contentIn, encontreSessionUsuario.get().getId());

			} else { // Si la sesión que viene es inválida
				respuesta.setMsg("Sesión expirada o inválida");
				estatus = HttpStatus.BAD_REQUEST;
				return new ResponseEntity(respuesta, estatus);
			}

			try {
				// Sentencia General
				String QueryTotal = "";
				Query query;
				String ids = "r.id"; // id de procesos
				String name = "r.name"; // buscar por nombre
				String status = "r.status"; // buscar por status

				String lowername = "LOWER(r.name)"; // se convierte en minúscula
				String lowername2 = "LOWER(pt.descr)"; // se convierte en minúscula
				String lowername3 = "LOWER(r.dsc)"; // se convierte en minúscula
				String LowerSearch = searchIn.toLowerCase(); // se convierte en minúscula
				String SentenciaBase = "";

				if (formatList == 1) {
					SentenciaBase = "SELECT r.id, r.name, r.status,  "
							+ "						CASE WHEN r.status = 1 THEN 'Activo' ELSE 'Inactivo' END AS descStatus, "
							+ "						r.dsc, " + "						r.requestertypepar, "
							+ "						pt.descr, " + "                    (select count(re.requesterid) "
							+ "                     from main.regreports re "
							+ "                     where re.requesterid = r.id) cantidad "
							+ "				FROM main.requesters r  "
							+ "					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 = 'REQUESTERS_TYPE' ) pt ON r.requestertypepar = CAST(pt.valor AS integer) ";

				} else {
					SentenciaBase = "SELECT  r.id,  r.name, r.status, "
							+ "	     CASE WHEN r.status = 1 THEN 'Activo' ELSE 'Inactivo' END AS estatus"
							+ "	     FROM main.requesters r "
							+ "		 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 = 'REQUESTERS_TYPE' ) pt ON r.requestertypepar = CAST(pt.valor AS integer) ";

				}

				System.out.println(SentenciaBase);

				// Se verifica si viene dato en el campo search para efectuar la búsqueda
				switch (searchIn) {
				case "":
					QueryTotal = SentenciaBase + "WHERE " + " 1=1 ";
					break;
				default: // viene con el parametro para buscar por el like
					QueryTotal = SentenciaBase + "WHERE (" + lowername + " LIKE  " + "'%" + LowerSearch + "%'" + " OR "
							+ lowername2 + " LIKE  " + "'%" + LowerSearch + "%'" + " OR " + lowername3 + " LIKE  "
							+ "'%" + LowerSearch + "%'" + " ) ";
					break;
				}

				switch (typeIn) {
				case 0:
					QueryTotal = QueryTotal + " AND 1=1 ";
					break;
				default:
					QueryTotal = QueryTotal + " AND r.requestertypepar = " + typeIn;
					break;
				}

				switch (statusIn) {
				case 0:
					QueryTotal = QueryTotal + " AND 1=1 ";
					break;
				case 1:
					QueryTotal = QueryTotal + " AND r.status = 1 ";
					break;
				case 2:
					QueryTotal = QueryTotal + " AND r.status = 0 ";
					break;
				default:
					respuesta.setMsg("Error el ordenamiento no es el correcto");
					estatus = HttpStatus.BAD_REQUEST;
					return new ResponseEntity(respuesta, estatus);
				}

				switch (orderIn) {
				case 1: // ordena por name
					QueryTotal = QueryTotal + " ORDER BY " + name + " ASC ";
					break;

				case 2:// ordena por status
					QueryTotal = QueryTotal + " ORDER BY " + status + " ASC ";
					break;

				case 3:// ordena por dsc
					QueryTotal = QueryTotal + " ORDER BY " + " r.dsc " + " ASC ";
					break;

				case 4:// ordena por requestertypepar
					QueryTotal = QueryTotal + " ORDER BY " + " r.requestertypepar " + " ASC ";
					break;

				case 5:// ordena por cantidad reportes
					QueryTotal = QueryTotal + " ORDER BY " + " cantidad " + " ASC ";
					break;

				case 99:// ordena por id
					QueryTotal = QueryTotal + " ORDER BY " + " r.id " + " ASC ";
					break;

				case -1:// ordena por name descendente
					QueryTotal = QueryTotal + " ORDER BY " + name + " DESC ";
					break;

				case -2:// ordena por estatus descendente
					QueryTotal = QueryTotal + " ORDER BY " + status + " DESC ";
					break;

				case -3:// ordena por dsc
					QueryTotal = QueryTotal + " ORDER BY " + " r.dsc " + " DESC ";
					break;

				case -4:// ordena por requestertypepar
					QueryTotal = QueryTotal + " ORDER BY " + " r.requestertypepar " + " DESC ";
					break;

				case -5:// ordena por cantidad reportes
					QueryTotal = QueryTotal + " ORDER BY " + " cantidad " + " DESC ";
					break;

				case -99:// ordena por id
					QueryTotal = QueryTotal + " ORDER BY " + " r.id " + " DESC ";
					break;

				default:
					respuesta.setMsg("Error el ordenamiento no es el correcto");
					estatus = HttpStatus.BAD_REQUEST;
					return new ResponseEntity(respuesta, estatus);
				}

				query = entityManager.createNativeQuery(QueryTotal);
				cuantosregistro = (long) query.getResultList().size();
				if (formatList != 2) {
					query.setFirstResult(offsetIn);
					query.setMaxResults(numofrecordsIn);
				}

				List<Object[]> resultados = query.getResultList();
				RequestersRecordsDto2 requestersRecordsDto = new RequestersRecordsDto2();
				RequestersResponseDto requestersResponseDto = new RequestersResponseDto();
				RequestersResponseDto3 requestersResponseDto3 = new RequestersResponseDto3();
				RequestersRecordsDto4 requestersResponseDto4 = new RequestersRecordsDto4();
				List<RequestersRecordsDto2> requestersRecordsDtoList = new ArrayList();
				List<RequestersRecordsDto4> requestersRecordsDtoList4 = new ArrayList();
				PrivilegesAllDto detallePrivilege = new PrivilegesAllDto();
				TypeResponseDto2 tipo = new TypeResponseDto2();
				StatusDto statusDto = new StatusDto();
				TypeReportDto detalleTypes = new TypeReportDto();
				List<TypeReportDto> detalleTypesList = new ArrayList();

				if (formatList != 2) {
					if (cuantosregistro > 0) {
						for (Object[] fila : resultados) {
							requestersRecordsDto.setId((int) fila[0]);
							requestersRecordsDto.setName((String) fila[1]);
							statusDto.setId((int) fila[2]);
							statusDto.setName((String) fila[3]);
							requestersRecordsDto.setDsc((String) fila[4] == null ? "" : (String) fila[4]);
							tipo.setId((BigDecimal) fila[5] == null ? new BigDecimal(0) : (BigDecimal) fila[5]);
							tipo.setDsc((String) fila[6] == null ? "" : (String) fila[6]);
							requestersRecordsDto.setType(tipo);
							requestersRecordsDto.setStatus(statusDto);
							BigInteger bigIntegerCount = (BigInteger) fila[7];
							requestersRecordsDto.setReportscount(bigIntegerCount.longValue());
							requestersRecordsDtoList.add(requestersRecordsDto);
							requestersRecordsDto = new RequestersRecordsDto2();
							statusDto = new StatusDto();
							tipo = new TypeResponseDto2();
						}

						// Se construye el Dto de Roles de Respuesta según los privilegios que
						// tenga el usuario
						rolisvalid = 0;
						detallePrivilege = new PrivilegesAllDto();
						rolisvalid = auditRepository
								.getCantbyRolAndPrivi(encontreSessionUsuario.get().getRolid().getId(), 451);
						if (rolisvalid > 0)
							detallePrivilege.setUpdate(true);
						else
							detallePrivilege.setUpdate(false);

						rolisvalid = 0;
						rolisvalid = auditRepository
								.getCantbyRolAndPrivi(encontreSessionUsuario.get().getRolid().getId(), 450);
						if (rolisvalid > 0)
							detallePrivilege.setView(true);
						else
							detallePrivilege.setView(false);

						rolisvalid = 0;
						rolisvalid = auditRepository
								.getCantbyRolAndPrivi(encontreSessionUsuario.get().getRolid().getId(), 452);
						if (rolisvalid > 0)
							detallePrivilege.setAdd(true);
						else
							detallePrivilege.setAdd(false);

						rolisvalid = 0;
						rolisvalid = auditRepository
								.getCantbyRolAndPrivi(encontreSessionUsuario.get().getRolid().getId(), 453);
						if (rolisvalid > 0)
							detallePrivilege.setDelete(true);
						else
							detallePrivilege.setDelete(false);

						String SetenciaTypes = "";

						SetenciaTypes = "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 = 'REQUESTERS_TYPE' ORDER BY valor ASC";

						Query queryTypes = entityManager.createNativeQuery(SetenciaTypes);
						List<Object[]> listatipos = queryTypes.getResultList();
						for (Object[] types : listatipos) {
							detalleTypes = new TypeReportDto();

							detalleTypes.setDsc((String) types[0]);
							detalleTypes.setValue((String) types[1]);
							detalleTypesList.add(detalleTypes);
						}

						requestersResponseDto.setTypes(detalleTypesList);

						requestersResponseDto.setNumofrecords(cuantosregistro);
						requestersResponseDto.setRecords(requestersRecordsDtoList);
						requestersResponseDto.setSessionvalidthru(fechaComoCadena);
						requestersResponseDto.setPrivileges(detallePrivilege);
					} else {

						// Se construye el Dto de Roles de Respuesta según los privilegios que
						// tenga el usuario
						rolisvalid = 0;
						detallePrivilege = new PrivilegesAllDto();
						rolisvalid = auditRepository
								.getCantbyRolAndPrivi(encontreSessionUsuario.get().getRolid().getId(), 451);
						if (rolisvalid > 0)
							detallePrivilege.setUpdate(true);
						else
							detallePrivilege.setUpdate(false);

						rolisvalid = 0;
						rolisvalid = auditRepository
								.getCantbyRolAndPrivi(encontreSessionUsuario.get().getRolid().getId(), 450);
						if (rolisvalid > 0)
							detallePrivilege.setView(true);
						else
							detallePrivilege.setView(false);

						rolisvalid = 0;
						rolisvalid = auditRepository
								.getCantbyRolAndPrivi(encontreSessionUsuario.get().getRolid().getId(), 452);
						if (rolisvalid > 0)
							detallePrivilege.setAdd(true);
						else
							detallePrivilege.setAdd(false);

						rolisvalid = 0;
						rolisvalid = auditRepository
								.getCantbyRolAndPrivi(encontreSessionUsuario.get().getRolid().getId(), 453);
						if (rolisvalid > 0)
							detallePrivilege.setDelete(true);
						else
							detallePrivilege.setDelete(false);

						String SetenciaTypes = "";

						SetenciaTypes = "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 = 'REQUESTERS_TYPE' ORDER BY valor ASC";

						Query queryTypes = entityManager.createNativeQuery(SetenciaTypes);
						List<Object[]> listatipos = queryTypes.getResultList();
						for (Object[] types : listatipos) {
							detalleTypes = new TypeReportDto();

							detalleTypes.setDsc((String) types[0]);
							detalleTypes.setValue((String) types[1]);
							detalleTypesList.add(detalleTypes);
						}

						requestersResponseDto.setNumofrecords(cuantosregistro);
						requestersResponseDto.setRecords(requestersRecordsDtoList);
						requestersResponseDto.setSessionvalidthru(fechaComoCadena);
						requestersResponseDto.setTypes(detalleTypesList);
						requestersResponseDto.setPrivileges(detallePrivilege);
					}
					return new ResponseEntity(requestersResponseDto, HttpStatus.OK);
				} else { // Formato 2
					if (cuantosregistro > 0) {
						for (Object[] fila : resultados) {
							requestersResponseDto4.setId((int) fila[0]);
							requestersResponseDto4.setName((String) fila[1]);
							statusDto.setId((int) fila[2]);
							statusDto.setName((String) fila[3]);
							requestersResponseDto4.setStatus(statusDto);
							requestersRecordsDtoList4.add(requestersResponseDto4);
							requestersResponseDto4 = new RequestersRecordsDto4();
							statusDto = new StatusDto();
						}

						requestersResponseDto3.setRecords(requestersRecordsDtoList4);
						requestersResponseDto3.setSessionvalidthru(fechaComoCadena);

						return new ResponseEntity(requestersResponseDto3, HttpStatus.OK);
					} else {

						requestersResponseDto3.setRecords(requestersRecordsDtoList4);
						requestersResponseDto3.setSessionvalidthru(fechaComoCadena);

						return new ResponseEntity(requestersResponseDto3, HttpStatus.OK);

					}

				}

			} catch (Exception e) {
				respuesta.setMsg("Error interno del servidor " + e.getMessage());
				estatus = HttpStatus.INTERNAL_SERVER_ERROR;
			} finally {
				if (entityManager != null && entityManager.isOpen()) {
					entityManager.close();
				}
			}
		}
		return new ResponseEntity(respuesta, HttpStatus.OK);
	}

	@GetMapping("/requesters/{requesterid}")
	public ResponseEntity<?> getOneRequesters(HttpServletRequest request,
			@PathVariable("requesterid") final Integer requesterid) throws ParseException {
		RespuestaMsgDto respuesta = new RespuestaMsgDto("");
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		long cuantosregistro = 0;

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

		String contentIn = "";
		int typeIn = 0;
		int idrol;

		TypeResponseDto2 detalleTypes;
		List<TypeResponseDto2> listasTypes = new ArrayList<>();
		Optional<Params> deSessDuration = paramsRepository.findByParamname("SESSION_DURATION");
		String SessionDuration = deSessDuration.get().getValue();
		int duracionSession = Integer.parseInt(SessionDuration);
		Date fecha2 = new Date();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(fecha2); // tuFechaBase es un Date;
		// calendar.add(Calendar.MINUTE, minutosASumar); //minutosASumar es int.
		calendar.add(Calendar.MINUTE, duracionSession); // horasASumar es int.
		// lo que más quieras sumar
		Date ValidThrufechaSalida = calendar.getTime(); // Y ya tienes la fecha sumada.
		SimpleDateFormat salida = new SimpleDateFormat("yyyy-MM-dd HH:mm"); // 2024-12-23 23:00
		String fechaComoCadena = salida.format(ValidThrufechaSalida);
		System.out.println(fechaComoCadena);

		// Verifico la session
		if (sessionid == null) {
			respuesta.setMsg("Llamada al servicio malformado");
			estatus = HttpStatus.BAD_REQUEST;
			return new ResponseEntity(respuesta, estatus);
		} else {
			sessionid = sessionid.substring(7);
			// verifico si la sesión del usuario existe.
			Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(sessionid);
			if (encontreSessionUsuario.isPresent()) { // si la sesión del usuario existe
				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,
						encontreSessionUsuario.get().getId());

				if (fechaComoCadena == "") {
					RespuestaMsgDto respuestaDto2;
					String var2 = "";
					boolean bloked2 = false;
					respuestaDto2 = new RespuestaMsgDto(var2);
					respuestaDto2.setMsg("Sesión expirada o inválida");
					return new ResponseEntity(respuestaDto2, HttpStatus.UNAUTHORIZED);
				}

				// Este proceso permite obtener un listado de los procesos. (Priv 120)
				// formatList = tiposfiltros.getFormat();
				int rolisvalid = 0;
				Roles roles = encontreSessionUsuario.get().getRolid();
				idrol = roles.getId();
				rolisvalid = auditRepository.getCantbyRolAndPrivi(encontreSessionUsuario.get().getRolid().getId(), 450);

				if (rolisvalid == 0) {
					respuesta.setMsg("No tiene los Privilegios");
					estatus = HttpStatus.FORBIDDEN;
					return new ResponseEntity(respuesta, estatus);
				}

				// Verifico los Shorcouts
				if (contentIn != null && contentIn != "") {
					menuService.iscontentdiffnull(contentIn, encontreSessionUsuario.get().getId());
				}

			} else { // Si la sesión que viene es inválida
				respuesta.setMsg("Sesión expirada o inválida");
				estatus = HttpStatus.BAD_REQUEST;
				return new ResponseEntity(respuesta, estatus);
			}

			TypeResponseDto2 tipo = new TypeResponseDto2();
			StatusDto stat = new StatusDto();
			List<FacilitiesResponseDto2> facilitiesResultado2 = new ArrayList();
			Query query = null;
			try {
				// Sentencia General

				String SentenciaBase = "SELECT r.id, r.name, r.status,  "
						+ "						CASE WHEN r.status = 1 THEN 'Activo' ELSE 'Inactivo' END AS descStatus, "
						+ "						r.dsc, " + "						r.requestertypepar, "
						+ "						pt.descr, " + "						r.contactname, "
						+ "                     r.contactphone, " + "                     r.contactemail, "
						+ "                     r.contactother, "
						+ "                     (select count(re.requesterid) "
						+ "                     from main.regreports re "
						+ "                     where re.requesterid = r.id) cantidad "
						+ "             FROM main.requesters r "
						+ "					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 = 'REQUESTERS_TYPE' ) pt ON r.requestertypepar = CAST(pt.valor AS integer) "
						+ "             WHERE r.id = " + requesterid;

				String QueryTotal = SentenciaBase;

				EntryRequestersDto entryRequestersDto = new EntryRequestersDto();
				EntryRequestersDto2 entryRequestersDto2 = new EntryRequestersDto2();

				query = entityManager.createNativeQuery(QueryTotal);
				cuantosregistro = (long) query.getResultList().size();
				List<Object[]> listacompleta = query.getResultList();
				StatusDto2 statusDto2 = new StatusDto2();
				ContactDto contactDto = new ContactDto();

				if (cuantosregistro > 0) {
					for (Object[] req : listacompleta) {
						statusDto2.setId((int) req[2]);
						statusDto2.setName((String) req[3]);

						entryRequestersDto2.setId((int) req[0]);
						entryRequestersDto2.setName((String) req[1]);
						entryRequestersDto2.setDsc((String) req[4] == null ? "" : (String) req[4]);
						entryRequestersDto2.setStatus(statusDto2);

						tipo.setDsc((String) req[6] == null ? "" : (String) req[6]);
						tipo.setId((BigDecimal) req[5] == null ? new BigDecimal(0) : (BigDecimal) req[5]);
						entryRequestersDto2.setType(tipo);

						contactDto.setEmail((String) req[9] == null ? "" : (String) req[9]);
						contactDto.setName((String) req[7] == null ? "" : (String) req[7]);
						contactDto.setOther((String) req[10] == null ? "" : (String) req[10]);
						contactDto.setPhone((String) req[8] == null ? "" : (String) req[8]);

						entryRequestersDto2.setContact(contactDto);
						BigInteger bigIntegerCount = (BigInteger) req[11];
						entryRequestersDto2.setReportscount(bigIntegerCount.longValue());

						statusDto2 = new StatusDto2();
						tipo = new TypeResponseDto2();

					}

					entryRequestersDto.setEntry(entryRequestersDto2);

					return new ResponseEntity(entryRequestersDto, HttpStatus.OK);
				} else {
					respuesta.setMsg("Registro no encontrado");
					return new ResponseEntity(respuesta, HttpStatus.NOT_FOUND);
				}
			} catch (Exception e) {
				respuesta.setMsg("Error interno del servidor ");
				estatus = HttpStatus.INTERNAL_SERVER_ERROR;
			} finally {
				if (entityManager != null && entityManager.isOpen()) {
					entityManager.close();
				}
			}
		}
		return new ResponseEntity(respuesta, HttpStatus.OK);
	}

	@PostMapping("/requesters/{requesterid}")
	public ResponseEntity<?> requestersUpdate(HttpServletRequest request,
			@RequestBody RequestersRequestDto requestersRequestDto,
			@PathVariable("requesterid") final Integer requesterid) throws ParseException {

		RespuestaValueDto respuestaValueDto;
		RespuestaMsgDto respuesta = new RespuestaMsgDto("");
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		ParamsResponseDto paramsResponseDto = new ParamsResponseDto();
		ParamsDto detalleParams;
		PrivilegesDto detallePrivilege;
		List<ParamsDto> listasParams = new ArrayList<>();
		List<PrivilegesDto> listasPrivelege = new ArrayList<>();

		int idparametro = requesterid;

		int valor = idparametro;
		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;
		Date fecha2 = new Date();
		Calendar calendar = Calendar.getInstance();

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

					}

				} else {

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

					}

					boolean existeFac = requestersRepository.existsById(idparametro);

					if (!existeFac) {

						String var = "";
						RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
						// respuestaDto.setBlocked(bloked);
						respuestaDto.setMsg("Registro No encontrado");
						// Error 400
						return new ResponseEntity(respuestaDto, HttpStatus.BAD_REQUEST);

					}
				}

				if (idparametro == 0) {

					Optional<Requesters> requesters = requestersRepository.findByName(requestersRequestDto.getName());
					if (requesters.isPresent()) {
						String var = "";
						RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
						respuestaDto.setMsg("Registro Duplicado");
						return new ResponseEntity(respuestaDto, HttpStatus.CONFLICT);
					}

				}

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

		try {

			String Salida1 = usersService.verificarCaracteresValidosConRegex(requestersRequestDto.getName());
			String Salida2 = usersService.verificarCaracteresValidosConRegex(requestersRequestDto.getDsc());
			String Salida3 = usersService
					.verificarCaracteresValidosConRegex(requestersRequestDto.getContact().getEmail());
			String Salida4 = usersService
					.verificarCaracteresValidosConRegex(requestersRequestDto.getContact().getName());
			String Salida5 = usersService
					.verificarCaracteresValidosConRegex(requestersRequestDto.getContact().getPhone());
			String Salida6 = usersService
					.verificarCaracteresValidosConRegex(requestersRequestDto.getContact().getOther());

			if (Salida1 == "NOOK" || Salida2 == "NOOK" || Salida3 == "NOOK" || Salida4 == "NOOK" || Salida5 == "NOOK"
					|| Salida6 == "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 (idparametro == 0) {
				Requesters requesters = new Requesters();
				Requesters requesters2 = new Requesters();
				if (requestersRepository.existsByName(requestersRequestDto.getName())) {
					String var = "";
					RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
					respuestaDto.setMsg("Registro Duplicado");
					return new ResponseEntity(respuestaDto, HttpStatus.CONFLICT);
				}

				requesters.setStatus(requestersRequestDto.getStatus());
				requesters.setModifiedat(fechaDate);
				requesters.setCreatedat(fechaDate);
				requesters.setName(requestersRequestDto.getName());
				requesters.setDsc(requestersRequestDto.getDsc().trim().compareTo("") == 0 ? null
						: requestersRequestDto.getDsc().trim());
				requesters.setRequestertypepar(
						requestersRequestDto.getType() == null ? null : requestersRequestDto.getType());
				requesters.setContactemail(requestersRequestDto.getContact().getEmail().trim().compareTo("") == 0 ? null
						: requestersRequestDto.getContact().getEmail().trim());
				requesters.setContactname(requestersRequestDto.getContact().getName().trim().compareTo("") == 0 ? null
						: requestersRequestDto.getContact().getName().trim());
				requesters.setContactphone(requestersRequestDto.getContact().getPhone().trim().compareTo("") == 0 ? null
						: requestersRequestDto.getContact().getPhone().trim());
				requesters.setContactother(requestersRequestDto.getContact().getOther().trim().compareTo("") == 0 ? null
						: requestersRequestDto.getContact().getOther().trim());
				requesters2 = requestersRepository.save(requesters);
				if (requesters2 != null) {
					////////////////////////// INSERCION BLOQUE DE AUDITORIA///////////////////
					String module = "Entidades Solicitantes";
					String Descmodule = "Se agregó la Entidad Solicitante: " + requesters2.getName() + " con Id:"
							+ requesters2.getId();

					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);
					auditDto.setCreatedat(fechaDate);
					usersService.registrarAuditSesion(auditDto);

					respuestaValueDto = new RespuestaValueDto(requesters2.getId());
					URI location = URI.create("/requesters/" + requesters2.getId());

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

				}

			} else {

				Optional<Requesters> requesters1 = requestersRepository.encontrarId(requesterid);

				if (!requesters1.isPresent()) {
					String var = "";
					RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
					respuestaDto.setMsg("Registro No Encontrado");
					return new ResponseEntity(respuestaDto, HttpStatus.NOT_FOUND);
				}

				if (requestersRepository.existsByName(requestersRequestDto.getName()) && requestersRepository
						.getByName(requestersRequestDto.getName()).get().getId().compareTo(requesterid) != 0) {
					respuesta.setMsg("Registro Duplicado");
					return new ResponseEntity(respuesta, HttpStatus.CONFLICT);
				}

				Requesters requesters = requesters1.get();
				Requesters requesters2 = new Requesters();
				requesters.setStatus(requestersRequestDto.getStatus());
				requesters.setModifiedat(fechaDate);
				requesters.setName(requestersRequestDto.getName());
				requesters.setDsc(requestersRequestDto.getDsc().trim().compareTo("") == 0 ? null
						: requestersRequestDto.getDsc().trim());
				requesters.setRequestertypepar(
						requestersRequestDto.getType() == null ? null : requestersRequestDto.getType());
				requesters.setContactemail(requestersRequestDto.getContact().getEmail().trim().compareTo("") == 0 ? null
						: requestersRequestDto.getContact().getEmail().trim());
				requesters.setContactname(requestersRequestDto.getContact().getName().trim().compareTo("") == 0 ? null
						: requestersRequestDto.getContact().getName().trim());
				requesters.setContactphone(requestersRequestDto.getContact().getPhone().trim().compareTo("") == 0 ? null
						: requestersRequestDto.getContact().getPhone().trim());
				requesters.setContactother(requestersRequestDto.getContact().getOther().trim().compareTo("") == 0 ? null
						: requestersRequestDto.getContact().getOther().trim());

				requesters2 = requestersRepository.save(requesters);
				if (requesters2 != null) {
					////////////////////////// INSERCION BLOQUE DE AUDITORIA///////////////////
					String module = "Entidades Solicitantes";
					String Descmodule = "Se actualizó la Entidad Solicitante: " + requesters2.getName() + " con Id:"
							+ requesters2.getId();

					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);
					auditDto.setCreatedat(fechaDate);
					usersService.registrarAuditSesion(auditDto);

					respuestaValueDto = new RespuestaValueDto(requesters2.getId());
					URI location = URI.create("/requesters/" + requesters2.getId());
					return ResponseEntity.created(location).body(respuestaValueDto);
				}

			}

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

		return new ResponseEntity(respuesta, estatus);

	}

	@DeleteMapping("/requesters/{requesterid}")
	public ResponseEntity<?> borrarRequest(HttpServletRequest request,
			@PathVariable("requesterid") final Integer requesterid) throws ParseException {

		RespuestaMsgDto respuesta = new RespuestaMsgDto("");
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		long cuantosregistro = 0;

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

		AuditRequestDto auditDto = new AuditRequestDto();
		String module = "";
		String Descmodule = "";

		Date fecha3 = new Date();
		SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String dataFormattata2 = formatter.format(fecha3);
		Date fechaDate2 = formatter.parse(dataFormattata2);

		Optional<Params> deSessDuration = paramsRepository.findByParamname("SESSION_DURATION");
		String SessionDuration = deSessDuration.get().getValue();
		int duracionSession = Integer.parseInt(SessionDuration);
		Date fecha2 = new Date();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(fecha2); // tuFechaBase es un Date;
		// calendar.add(Calendar.MINUTE, minutosASumar); //minutosASumar es int.
		calendar.add(Calendar.MINUTE, duracionSession); // horasASumar es int.
		// lo que más quieras sumar
		Date ValidThrufechaSalida = calendar.getTime(); // Y ya tienes la fecha sumada.
		SimpleDateFormat salida = new SimpleDateFormat("yyyy-MM-dd HH:mm"); // 2024-12-23 23:00
		String fechaComoCadena = salida.format(ValidThrufechaSalida);
		System.out.println(fechaComoCadena);

		// Verifico la session
		if (sessionid == null) {
			respuesta.setMsg("Llamada al servicio malformado");
			estatus = HttpStatus.BAD_REQUEST;
			return new ResponseEntity(respuesta, estatus);
		} else {
			sessionid = sessionid.substring(7); // verifico si la sesión del usuario existe.

			Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(sessionid);
			if (encontreSessionUsuario.isPresent()) { // si la sesión del usuario existe
				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,
						encontreSessionUsuario.get().getId());
				if (fechaComoCadena == "") {
					RespuestaMsgDto respuestaDto2;
					String var2 = "";
					boolean bloked2 = false;
					respuestaDto2 = new RespuestaMsgDto(var2);
					respuestaDto2.setMsg("Sesión expirada o inválida");
					return new ResponseEntity(respuestaDto2, HttpStatus.UNAUTHORIZED);
				}

				int rolisvalid = 0;

				try {
					// verifico si tiene el privilegio
					rolisvalid = auditRepository.getCantbyRolAndPrivi(encontreSessionUsuario.get().getRolid().getId(),
							453);
					if (rolisvalid == 0) {
						respuesta.setMsg("No tiene los Privilegios");
						estatus = HttpStatus.FORBIDDEN;
						return new ResponseEntity(respuesta, estatus);
					}

					// Verifico si existe el id de la Entidad Solicitante
					Optional<Requesters> requesters = requestersRepository.encontrarId(requesterid);

					// Verifico si encontre la Entidad Solicitante
					if (!requesters.isPresent()) {
						respuesta.setMsg("Registro no encontrado");
						return new ResponseEntity(respuesta, HttpStatus.NOT_FOUND);
					}

					try {
						// Se borra la Entidad Solicitante
						if (requestersRepository.findRequesters(requesterid) == 0)
							requestersRepository.deleteById(requesterid);
						else {
							respuesta.setMsg(
									"No se pudo borrar porque la entidad solicitante está asociada a reporte(s) regulatorio(s)");
							estatus = HttpStatus.CONFLICT;
							return new ResponseEntity(respuesta, estatus);
						}

						module = "Entidades Solicitantes";
						Descmodule = "Se borró la Entidad Solicitante: " + requesters.get().getName() + " con id: "
								+ requesterid;
						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);
						auditDto.setCreatedat(fechaDate2);
						usersService.registrarAuditSesion(auditDto);

						RespuestaValueDto respuestaValueDto = new RespuestaValueDto(requesterid);
						URI location = URI.create("/requesters/" + requesterid); // O la URL correcta para // tu
						// recurso

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

					} catch (Exception e) {
						respuesta.setMsg("No se pudo borrar por alguna razón");
						estatus = HttpStatus.CONFLICT;
						return new ResponseEntity(respuesta, estatus);
					}
				} catch (Exception e) {
					respuesta.setMsg("Error interno. Descripción del error " + e.getMessage());
					estatus = HttpStatus.INTERNAL_SERVER_ERROR;
					return new ResponseEntity(respuesta, estatus);
				} finally {
					if (entityManager != null && entityManager.isOpen()) {
						entityManager.close();
					}
				}

			}

			return new ResponseEntity(respuesta, HttpStatus.OK);

		}

	}

}
