package com.dacrt.SBIABackend.security.controler;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.data.jpa.repository.Query;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.BindingResult;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import com.dacrt.SBIABackend.security.dto.AccesoDto;
import com.dacrt.SBIABackend.security.dto.SessionDto;
import com.dacrt.SBIABackend.security.dto.ShortcutsDto;
import com.dacrt.SBIABackend.security.dto.UsersListDto;
import com.dacrt.SBIABackend.security.dto.UsersUnitDto;
import com.dacrt.SBIABackend.security.dto.AuditDtoMod;
import com.dacrt.SBIABackend.security.dto.ComprobadorAcceso;
//import com.dacrt.SBIABackend.security.dto.DetalleUsuarioRequestDto;
//import com.dacrt.SBIABackend.security.dto.DetalleUsuarioResponseDto;
import com.dacrt.SBIABackend.security.dto.JwtDto;
import com.dacrt.SBIABackend.security.dto.HashPwdDto;
import com.dacrt.SBIABackend.security.dto.LoginUsuario;
//import com.dacrt.SBIABackend.security.dto.MenuDto;
//import com.dacrt.SBIABackend.security.dto.UsuarioSesionRequestDto;
import com.dacrt.SBIABackend.security.dto.RolAccesoDto;
import com.dacrt.SBIABackend.security.entity.Roles;
import com.dacrt.SBIABackend.security.entity.Users;
import com.dacrt.SBIABackend.security.enums.RolNombre;
import com.dacrt.SBIABackend.security.jwt.JwtProvider;
//import com.dacrt.SBIABackend.security.repository.UsuarioRepository;
//import com.dacrt.SBIABackend.security.service.UsuarioService;
import com.dacrt.SBIABackend.security.service.UsersService;
import com.dacrt.SBIABackend.service.GroupService;
import com.dacrt.SBIABackend.security.service.MenuService;
import com.dacrt.SBIABackend.security.service.RolesService;
import com.dacrt.SBIABackend.security.service.SecurityService;
import com.dacrt.SBIABackend.utils.HttpReqRespUtils;
import com.dacrt.SBIABackend.dto.ApplicationActualizarDto;
import com.dacrt.SBIABackend.dto.JsonoauthDto;
//import com.dacrt.SBIABackend.controler.ProcesoControler;
import com.dacrt.SBIABackend.dto.Mensaje;
import com.dacrt.SBIABackend.dto.MockUser;
import com.dacrt.SBIABackend.dto.OktaMetaRespDto;
import com.dacrt.SBIABackend.dto.OktaNameResponseDto;
import com.dacrt.SBIABackend.dto.OktaProvissionDto;
import com.dacrt.SBIABackend.dto.ScimGroup;
import com.dacrt.SBIABackend.dto.ScimListResponse;
import com.dacrt.SBIABackend.dto.ScimListResponse2;
import com.dacrt.SBIABackend.dto.ScimUserResource;
import com.dacrt.SBIABackend.dto.ScimUserResponseDto;
import com.dacrt.SBIABackend.dto.ScimUserUpdateDTO;
import com.dacrt.SBIABackend.dto.SuppliersDtoStatus;
import com.dacrt.SBIABackend.dto.UnitsDto;
import com.dacrt.SBIABackend.dto.UnitsUsersDto;
import com.dacrt.SBIABackend.dto.logoutOktaNormalDto;
import com.dacrt.SBIABackend.dto.oAuth2LoginDto;
import com.dacrt.SBIABackend.dto.oktaEmailDto;
import com.dacrt.SBIABackend.dto.requestDto.SchemaOktaCreateDto;
import com.dacrt.SBIABackend.entity.Units;
import com.dacrt.SBIABackend.entity.Userunits;
import com.dacrt.SBIABackend.entity.Workers;
import com.dacrt.SBIABackend.repository.UnitsRepository;
import com.dacrt.SBIABackend.repository.UserunitsRepository;
import com.dacrt.SBIABackend.security.dto.RespuestaDto;
import com.dacrt.SBIABackend.security.dto.RespuestaMsgDto;
import com.dacrt.SBIABackend.security.dto.RespuestaParamsDto;
import com.dacrt.SBIABackend.security.dto.RespuestaValidThruDto;
import com.dacrt.SBIABackend.security.dto.RespuestaValueDto;
import com.dacrt.SBIABackend.security.dto.AuditRequestDto;
import com.dacrt.SBIABackend.security.dto.MenuResponseDto;
import com.dacrt.SBIABackend.security.dto.ParamsDto;
import com.dacrt.SBIABackend.security.dto.ParamsResponseDto;
import com.dacrt.SBIABackend.security.dto.PrivilegesDto;
import com.dacrt.SBIABackend.security.dto.PwdcomplexityDto;
import com.dacrt.SBIABackend.security.dto.PwdoldnewDto;
import com.dacrt.SBIABackend.security.dto.AuditDto;
import com.dacrt.SBIABackend.security.dto.AuditResponseDto;
import com.dacrt.SBIABackend.security.dto.AuditModResponseDto;
import com.dacrt.SBIABackend.security.dto.AuditAllResponseDto;
import com.dacrt.SBIABackend.security.dto.AuditAllDto;
import com.dacrt.SBIABackend.security.entity.Access;
import com.dacrt.SBIABackend.security.entity.Audit;
import com.dacrt.SBIABackend.security.entity.Params;
import com.dacrt.SBIABackend.security.entity.Menu;
//import com.dacrt.SBIABackend.repository.ParametrosRepository;
import com.dacrt.SBIABackend.security.repository.UsersRepository;
import com.dacrt.SBIABackend.security.repository.ParamsRepository;
import com.dacrt.SBIABackend.security.repository.RolesRepository;
import com.dacrt.SBIABackend.security.repository.AuditRepository;
import com.dacrt.SBIABackend.security.repository.MenuRepository;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

@RestController
@RequestMapping("/security")
//@CrossOrigin(origins = "http://vpskromasys2.hostnetcom.com:8081")
@CrossOrigin(origins = "*")
//@CrossOrigin(origins = "https://vpskromasys2.hostnetcom.com/~daconsult/dev")
//@CrossOrigin(origins = "*")

public class SecurityController {
	@Autowired
	PasswordEncoder passworEncoder;
	
	@Autowired
	AuthenticationManager autheticationManager;
	
	@Autowired
	UsersService usersService;
	
	@Autowired
	MenuService menuService;
	
	@Autowired
	GroupService groupService; 
	
	@Autowired
	SecurityService securityService;
	
	@Autowired
	AuditRepository auditRepository;
	
	@Autowired
	UsersRepository usersRepository;
	
	@Autowired
	ParamsRepository paramsRepository;
	
	@Autowired
	MenuRepository menuRepository;
	
	@Autowired
	UserunitsRepository userunitsRepository;
	
	@Autowired
	UnitsRepository unitsRepository;
	
	@Autowired
	RolesRepository rolesRepository;
	
	@PersistenceContext
    private EntityManager entityManager;
	
	@Autowired
	RolesService rolesService;
	
	@Autowired
	JwtProvider jwtProvider;
	
	@Autowired
    private JdbcTemplate jdbcTemplate;
	
	@Autowired
    private RestTemplate restTemplate;
	
	// @Value("$(var.ambiente)")
	@Value("${var.ambiente}")
	private String urlAmbiente;
	
	@Value("${spring.security.oauth2.client.registration.okta.client-id}")
	private String clientId;
	
	@Value("${spring.security.oauth2.client.registration.okta.redirect-uri}")
	private String redirect_uri;
	
	@Value("${app.oauth.scopes}")
	private String scope;
	
	@Value("${spring.security.oauth2.client.provider.okta.issuer-uri}")
	private String issuerUri;
	
	@Value("${app.oauth.v1.token}")
	private String vtoken;
	
	@Value("${spring.security.oauth2.client.registration.okta.client-secret}")
	private String clienteSec;
	
	@Value("${spring.security.oauth2.client.registration.okta.authorization-endpoint}")
	private String vauth;
	
	@Value("${app.oauth2.v1.userinfo}")
	private String vuserinfo;
	
	@Value("${direccionlocal}")
	private String dirlocal;
	
	@Value("${isOkta}")
	private int isOkta;
	
	@Value("${app.user.exist.url}")
	private String urlOktaExist;
	
	@Value("${cors.allowed.origin}")
	private String urlSystemLogout;
	
	@Value("${app.api.token}")
	private String varTokenprovissioning; 
	
	@Value("${app.email.helpdesk.active}")
	private String vemailhelpdesk; 
	
	Logger logger = LoggerFactory.getLogger(SecurityController.class);
	
	java.util.Date fechaActual = new java.util.Date();
	
    private static final String SCIM_BASE_URL = "https://bistable-madonna-carbonous.ngrok-free.dev/security/scim/v2/Users";

   // private final GroupService groupService;
	@GetMapping("/scim/v2/Users")
	public ResponseEntity<?> ListUsersprovissioning(HttpServletRequest request, HttpServletResponse response,
			@RequestParam(required = false) String filter) throws ParseException, IOException {
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		// HttpSession sessionuserid = request.getSession();
		RespuestaDto respuesta = new RespuestaDto("", false);
		String tokendef = varTokenprovissioning;
		String emailToSearch = null;
		String SentenciaBase = "";
		String idtokenrequest = request.getHeader("Authorization");
		
		 if (idtokenrequest.contains("Bearer")) {
			  idtokenrequest = idtokenrequest.substring(7);
		  } else {
			  idtokenrequest = idtokenrequest;
		  }
		// idtokenrequest = idtokenrequest.substring(7);
		OktaProvissionDto detailOktaProvissionDto = new OktaProvissionDto();
       //   if (tokendef.equals(idtokenrequest)) {
         if (idtokenrequest == null || !tokendef.equals(idtokenrequest)) {
        	 List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
             detailOktaProvissionDto.setDetail("Sin autorización");
             detailOktaProvissionDto.setSchemas(scimSchema);
             detailOktaProvissionDto.setStatus("401");
             
   			return new ResponseEntity(detailOktaProvissionDto, HttpStatus.UNAUTHORIZED);  
        	 
		} else {
        	  
        	  if (filter != null && filter.contains("userName eq")) {
        	        // Ejemplo de filtro: 'userName eq "javieroropezacompras@gmail.com"'
        	        
				// Expresión regular para extraer el valor entre comillas después de 'userName
				// eq'
        	        Pattern pattern = Pattern.compile("userName\\s+eq\\s+\"([^\"]+)\"");
        	        Matcher matcher = pattern.matcher(filter);

        	        if (matcher.find()) {
        	            emailToSearch = matcher.group(1); // Captura el email/userName
					SentenciaBase = "SELECT cast(u.id as text) as id,u.usr,u.name,u.email,u.rolid,u.workerid,u.supplierid,u.status FROM main.users u WHERE u.email = "
							+ "'" + emailToSearch + "'";
        	        }
        	        
			} else {
        	    	 SentenciaBase = "SELECT cast(u.id as text) as id,u.usr,u.name,u.email,u.rolid,u.workerid,u.supplierid,u.status FROM main.users u WHERE u.status = 1 and pwd is null";
        	    }
        	  
			String givenName = "";
			String familyName = "";
        	  List<ScimUserResource> scimResources = new ArrayList<>();
        	  String now = ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT);
        	  String mensaje = "valor";
        	//  ScimListResponse responseData = new ScimListResponse();
        	  List<Map<String, Object>> lista = jdbcTemplate.queryForList(SentenciaBase);
        	  
			for (Map<String, Object> mapa : lista) {
        		  ScimUserResource resource = new ScimUserResource();
      		   
        		//  int id = (int) mapa.get("id");
        		  String id = (String) mapa.get("id");
				 // String usr = (String) mapa.get("usr");
        		  String usr = (String) mapa.get("email");
				  int status = (int) mapa.get("status");
				    resource.setId(id);
	      		    resource.setUserName(usr);
				if (status == 1) {
	      		            resource.setActive(true);
	      		       } else {
	      			        resource.setActive(false);
	      		       }
	      		    
				  if (mapa.get("name") != null && !((String) mapa.get("name")).trim().isEmpty()) {
					    String name = (String) mapa.get("name");
						  String[] partes = name.trim().split("\\s+", 2);
						  if (partes.length > 0) {
					            givenName = partes[0]; // Primer trozo es el Nombre
					        }
					        if (partes.length > 1) {
					            familyName = partes[1]; // El resto es el Apellido
					        } else {
					            // Caso borde: Si solo viene "Pedro", el apellido se deja vacío o se repite
					            familyName = ""; 
					        }
						  System.out.print(partes);
					}
			    	// Datos de 'name'
				  ScimUserResource.Name name = new ScimUserResource.Name();
		            name.setGivenName(givenName);
		            name.setFamilyName(familyName);
		            name.setFormatted(givenName + " " + familyName);
		            resource.setName(name);
				  
		            // Datos de 'emails'
		            ScimUserResource.Email email = new ScimUserResource.Email();
		            email.setValue(usr);
		            email.setType("work");
		            email.setPrimary(true);
		            resource.setEmails(Arrays.asList(email));
		            
		         // Datos de 'meta'
		            ScimUserResource.Meta meta = new ScimUserResource.Meta();
		            meta.setResourceType("User");
		            meta.setCreated(now);
		            meta.setLastModified(now);
		            meta.setLocation(SCIM_BASE_URL + "/" + id);
		            resource.setMeta(meta);
		            scimResources.add(resource);
	        		       	 			  
				 }
        	
              // 3. Construcción de la respuesta definitiva SCIM (ListResponse)
              ScimListResponse responseData = new ScimListResponse();
              responseData.setTotalResults(scimResources.size());
              responseData.setStartIndex(1);
              responseData.setItemsPerPage(scimResources.size());
              responseData.setResources(scimResources);

              // 4. ENVÍO DE LA RESPUESTA (HTTP 200 OK)
              return ResponseEntity.ok(responseData);
          }
         // return new ResponseEntity(respuesta, estatus);
   }
	
	@PostMapping("/scim/v2/Users")
	//public ResponseEntity<?> CreateUsersprovissioning(HttpServletRequest request,HttpServletResponse response) throws ParseException, IOException {
	public ResponseEntity<?> CreateUsersprovissioning(HttpServletRequest request,@RequestBody SchemaOktaCreateDto schemaOktaCreateDto) throws ParseException, IOException {
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		// HttpSession sessionuserid = request.getSession();
		RespuestaDto respuesta = new RespuestaDto("", false);
		String tokendef=varTokenprovissioning;
		 Optional<Users> encontreSessionUsuario;
		 Roles objetoRoles=null;
		 String valorroles="";
		   String selectedRole = ""; // Default
		   OktaProvissionDto detailOktaProvissionDto = new OktaProvissionDto();
		   
		   try {
		       selectedRole =  schemaOktaCreateDto.getCustomExtension().getRoles();
		   } catch (Exception e) { 
			   selectedRole = "";
		   }
		   
		   
			 if (selectedRole=="") {
				    valorroles = "Sin rol";
			   } else {
				   boolean  existerol = rolesRepository.existsByName(selectedRole);
				      if (existerol) {
				    	  //objetoRoles = rolesRepository.findByNameString(selectedRole);
				    	   objetoRoles = rolesService.getRolesByName(selectedRole);
				    	 // rolesService.getRolesByid(datosUsuario.getRoleid());
				      } else {
				    	   List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
			               detailOktaProvissionDto.setDetail("Error - El rol asignado no pertenece a la aplicación");
			               detailOktaProvissionDto.setSchemas(scimSchema);
			               detailOktaProvissionDto.setStatus("409");
			               return new ResponseEntity(detailOktaProvissionDto, HttpStatus.CONFLICT); 
					   
				      }
				         
				   
			   }
			             
			         						  		   
		String idtokenrequest = request.getHeader("Authorization");
		  if (idtokenrequest.contains("Bearer")) {
			  idtokenrequest = idtokenrequest.substring(7);
		  } else {
			  idtokenrequest = idtokenrequest;
		  }
		        
		
		
         if (idtokenrequest == null || !tokendef.equals(idtokenrequest)) { 
        	 List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
             detailOktaProvissionDto.setDetail("Sin autorización");
             detailOktaProvissionDto.setSchemas(scimSchema);
             detailOktaProvissionDto.setStatus("401");
             
        
   			return new ResponseEntity(detailOktaProvissionDto, HttpStatus.UNAUTHORIZED);  
        	 
        	  
          } else
          {
        	  
        	  // validacion de la existencia del usuario
        	  boolean existeuser;
        	  String concatNameApellido;
              existeuser = usersRepository.existsByEmail(schemaOktaCreateDto.getEmails().get(0).getValue());
              if (existeuser) {
            	  List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
                  detailOktaProvissionDto.setDetail("Error - El usuario ya se encuentra registrado");
                  detailOktaProvissionDto.setSchemas(scimSchema);
                  detailOktaProvissionDto.setStatus("409");
                  return new ResponseEntity(detailOktaProvissionDto, HttpStatus.CONFLICT); 
             
              }
        	
              
              boolean isGivenNameMissing = schemaOktaCreateDto.getName().getGivenName() == null || schemaOktaCreateDto.getName().getGivenName().isEmpty();
              boolean isFamilyNameMissing = schemaOktaCreateDto.getName().getFamilyName() == null || schemaOktaCreateDto.getName().getFamilyName().isEmpty();

              // Entra al IF si AL MENOS UNO de los dos está ausente (es null O es vacío)
              if (isGivenNameMissing || isFamilyNameMissing) {
            	    // Lanzar el Error 400
            	    List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
            	    detailOktaProvissionDto.setDetail("Campo Nulo");
            	    detailOktaProvissionDto.setSchemas(scimSchema);
            	    detailOktaProvissionDto.setStatus("400");
            	    return new ResponseEntity(detailOktaProvissionDto, HttpStatus.BAD_REQUEST); 
            	} else {
            	    // Si ambos existen (NO son nulos), proceder a la concatenación
            	    concatNameApellido = schemaOktaCreateDto.getName().getGivenName().toLowerCase() + schemaOktaCreateDto.getName().getFamilyName().toLowerCase();
            	}
              if (concatNameApellido!=null) {
            	       Optional<Params> deCarateresPer=paramsRepository.findByParamname("TEXTBOX_ALLOWED");
   			           String caracterespermi=deCarateresPer.get().getValue();
   				       
   				    for (int i = 0; i < concatNameApellido.length(); i++) {
						   
						   char currentChar = concatNameApellido.charAt(i);
				            // Verificar si el carácter no está en el conjunto de permitidos
						   if (caracterespermi.indexOf(currentChar) == -1) {
				                
				         
				                String var = "";
								boolean bloked = false;
								RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
								//respuestaDto.setBlocked(bloked);
								respuestaDto.setMsg("Caracteres no permitidos en el Nombre o Apellido del Usuario"); 
								return new ResponseEntity(respuestaDto, HttpStatus.BAD_REQUEST);
				            }
				        }
            	
              } else {
            	       List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
		               detailOktaProvissionDto.setDetail("Nombre es Nulo");
		               detailOktaProvissionDto.setSchemas(scimSchema);
		               detailOktaProvissionDto.setStatus("403");
		             
		        
		   			   return new ResponseEntity(detailOktaProvissionDto, HttpStatus.FORBIDDEN);  
              }
              
              if (schemaOktaCreateDto.getExternalId() != null) {
				Optional<Params> deCarateresPer = paramsRepository.findByParamname("OKTA_ALLOWED_CHAR");
				String caracterespermi = deCarateresPer.get().getValue();
            	  for (int i = 0; i < schemaOktaCreateDto.getExternalId().length(); i++) {
					   
					   char currentChar = schemaOktaCreateDto.getExternalId().charAt(i);
			            // Verificar si el carácter no está en el conjunto de permitidos
					   if (caracterespermi.indexOf(currentChar) == -1) {
			                
			         
			                String var = "";
							boolean bloked = false;
							RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
							//respuestaDto.setBlocked(bloked);
							respuestaDto.setMsg("Caracteres no permitidos en el Externalid"); 
							return new ResponseEntity(respuestaDto, HttpStatus.BAD_REQUEST);
			            }
			        }
       	
              } else { 
            	  List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
              detailOktaProvissionDto.setDetail("Externalid es Nulo");
              detailOktaProvissionDto.setSchemas(scimSchema);
              detailOktaProvissionDto.setStatus("403");
            
       
  			   return new ResponseEntity(detailOktaProvissionDto, HttpStatus.FORBIDDEN); 
  			   }
              
               // selectedRole =  schemaOktaCreateDto.getCustomExtension().getRoles();
 
			    String SalidaName= schemaOktaCreateDto.getName().getGivenName();
			    String SalidaApellido = schemaOktaCreateDto.getName().getFamilyName();
			    String Salidaemail = usersService.verificarCaracteresValidosConRegex(schemaOktaCreateDto.getEmails().get(0).getValue());
			    Date fecha = new Date();
			    SimpleDateFormat  formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		        String dataFormattata = formatter.format(fecha);
			    Date fechaDate = formatter.parse(dataFormattata);
			    if (SalidaName=="NOOK" || SalidaApellido=="NOOK" || Salidaemail=="NOOK") {
			    	 List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
		             detailOktaProvissionDto.setDetail("Caracteres no Permitidos en email");
		             detailOktaProvissionDto.setSchemas(scimSchema);
		             detailOktaProvissionDto.setStatus("403");
		             
		        
		   			return new ResponseEntity(detailOktaProvissionDto, HttpStatus.FORBIDDEN);  
				  }
				// aqui comenzamos a insertar el usuario hacia la tabla de Users de nuestra aplicacion///
			    Users tipoUsersNew = new Users();
			    /*if (schemaOktaCreateDto.isActive()) {
			    	
			    } else {
			    	tipoUsersNew.setStatus(0);
			    }*/
			    Users tipoUsersNew2=null;
			    tipoUsersNew.setName(SalidaName + " , " + SalidaApellido);
			    tipoUsersNew.setUsr(schemaOktaCreateDto.getUserName());
			    tipoUsersNew.setRef(schemaOktaCreateDto.getExternalId());
			    tipoUsersNew.setEmail(schemaOktaCreateDto.getEmails().get(0).getValue());
			    tipoUsersNew.setStatus(1);
			    tipoUsersNew.setModifiedat(fechaDate);
				tipoUsersNew.setCreatedat(fechaDate);  //tipoUsers.setLastpwdchange(fechaDate);
				tipoUsersNew.setLastpwdchange(fechaDate);
				tipoUsersNew.setFails(0);
				tipoUsersNew.setLastsession(fechaDate);
				
				if  (valorroles.equals("Sin rol")) {
					selectedRole = "Solo Ver";
					objetoRoles = rolesService.getRolesByName(selectedRole);
					tipoUsersNew.setRolid(objetoRoles);
					
				} else {
					
					//tipoUsersNew.setRolid(objetoRoles.getId());
					
					Roles tipoRol = rolesService.getRolesByName(selectedRole);
					tipoUsersNew.setRolid(tipoRol);
				}
				
				//Roles tipoRol = rolesService.getRolesByid(0);
				//tipoUsersNew.setRolid(tipoRol);
				//Workers tipoWorkers = workersService.getWorkersByid(datosUsuario.getWorkerid());
            	//tipoUsersNew.setWorkerid(tipoWorkers);
            	 tipoUsersNew2=usersService.addIdUsers(tipoUsersNew);
 	         //   tipoUsers2 = tipoUsersNew2;
            	 encontreSessionUsuario =usersRepository.getByEmail(schemaOktaCreateDto.getEmails().get(0).getValue());
            	 int idregistrado=encontreSessionUsuario.get().getId();
            	 
        	  String SentenciaBase = "SELECT cast(u.id as text) as id,u.usr,u.name,u.email,u.rolid,u.workerid,u.supplierid,u.status FROM main.users u WHERE u.id = " + idregistrado;
        	  String givenName="";
        	  String familyName="";
        	  List<ScimUserResource> scimResources = new ArrayList<>();
        	  String now = ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT);
        	  String mensaje = "valor";
        	//  ScimListResponse responseData = new ScimListResponse();
        	  List<Map<String, Object>> lista = jdbcTemplate.queryForList(SentenciaBase);
        	  ScimUserResponseDto scimUserResponseDto = new ScimUserResponseDto();
        	  List<oktaEmailDto> listoktaEmailDto = new ArrayList<>();
        	  for (Map<String, Object> mapa : lista) 
				 {
        		  ScimUserResource resource = new ScimUserResource();
        		  OktaNameResponseDto name =  new OktaNameResponseDto();
        		  oktaEmailDto email = new oktaEmailDto();
        		  OktaMetaRespDto meta = new OktaMetaRespDto();
				  //ScimUserResource.Name name = new ScimUserResource.Name();

        		//  int id = (int) mapa.get("id");
        		  String id = (String) mapa.get("id");
        		  String external = (String) mapa.get("usr");
				 // String usr = (String) mapa.get("usr");
        		  String usr = (String) mapa.get("email");
				  int status = (int) mapa.get("status");
				    //resource.setId(id);
				    scimUserResponseDto.setSchemas(Arrays.asList("urn:ietf:params:scim:schemas:core:2.0:User"));
				    scimUserResponseDto.setId(id);
				    scimUserResponseDto.setUserName(usr);
	      		   // resource.setUserName(usr);
	      	     	  if (status==1) {
	      	     		  scimUserResponseDto.setActive(true);
	      		       } else {
	      		    	  scimUserResponseDto.setActive(false);
	      		       }
	      	    
				 
				  if (mapa.get("name") != null && !((String) mapa.get("name")).trim().isEmpty()) {
					    String nameIn = (String) mapa.get("name");
						  String[] partes = nameIn.trim().split("\\s+", 2);
						  if (partes.length > 0) {
					            givenName = partes[0]; // Primer trozo es el Nombre
					        }
					        if (partes.length > 1) {
					            familyName = partes[1]; // El resto es el Apellido
					        } else {
					            // Caso borde: Si solo viene "Pedro", el apellido se deja vacío o se repite
					            familyName = ""; 
					        }
						  System.out.print(partes);
					}
			    	// Datos de 'name'
				  
		            name.setGivenName(givenName);
		            name.setFamilyName(familyName);
		            scimUserResponseDto.setName(name);
		            //resource.setName(name);
		            scimUserResponseDto.setExternalId(external);

		            // Datos de 'emails'
		           // ScimUserResource.Email email = new ScimUserResource.Email();
		            email.setValue(usr);
		            email.setType("work");
		            email.setPrimary(true);
		            listoktaEmailDto.add(email);
		            scimUserResponseDto.setEmails(listoktaEmailDto);
		           // resource.setEmails(Arrays.asList(email));
		            
		         // Datos de 'meta'
		           // ScimUserResource.Meta meta = new ScimUserResource.Meta();
		            meta.setResourceType("User");
		            meta.setCreated(now);
		            meta.setLastModified(now);
		            meta.setLocation(SCIM_BASE_URL + "/" + id);
		            scimUserResponseDto.setMeta(meta);
		          //  resource.setMeta(meta);
		           // scimResources.add(resource);
	        		         	        	    	  								 				 
				  
				 }
        	
              // 3. Construcción de la respuesta definitiva SCIM (ListResponse)
             // ScimListResponse responseData = new ScimListResponse();
             // responseData.setTotalResults(scimResources.size());
             // responseData.setStartIndex(1);
            //  responseData.setItemsPerPage(scimResources.size());
           //   responseData.setResources(scimResources);

              // 4. ENVÍO DE LA RESPUESTA (HTTP 200 OK)
              return ResponseEntity.ok(scimUserResponseDto);
          }
         // return new ResponseEntity(respuesta, estatus);
   }
  

	@GetMapping("/scim/v2/Groups")
    public ResponseEntity<ScimListResponse2<ScimGroup>> listGroups() {
		// GroupService groupService;
        // 1. Consulta el servicio para obtener la lista de grupos (roles)
        List<ScimGroup> groups = groupService.findAllGroups();

        // 2. Envuelve la lista en la estructura SCIM ListResponse
        ScimListResponse2<ScimGroup> response = new ScimListResponse2<>(groups);

        // 3. Devuelve la respuesta con el código de estado 200 OK
        return ResponseEntity.ok(response);
    }

	 private static final String CUSTOM_SCHEMA_URN = "urn:ietf:params:scim:schemas:extension:custom:2.0:User";
	 @GetMapping("/scim/v2/Schemas")
	    public ResponseEntity<List<Map<String, Object>>> getSchemas() {
	        // Lista de roles dinámicos (esto podría venir de tu base de datos)
	       // List<String> dbRoles = Arrays.asList("Admin", "Supervisor", "Operador", "Auditor");
	        List<String> dbRoles = rolesRepository.findAllRoleNames();
	        
	        Map<String, Object> coreUserSchema = new HashMap<>();
	        coreUserSchema.put("id", "urn:ietf:params:scim:schemas:core:2.0:User");
	        coreUserSchema.put("name", "User");
	        coreUserSchema.put("description", "Core User Schema");
	        // SCIM permite omitir la lista completa de atributos del core si es estándar
	        coreUserSchema.put("attributes", Collections.emptyList()); 
	        // Si quieres ser totalmente explícito, aquí irían los atributos del esquema core.
	        
	        // Construcción de la definición del atributo 'roles'
	        Map<String, Object> rolesAttribute = new HashMap<>();
	        rolesAttribute.put("name", "roles");
	        rolesAttribute.put("type", "string");
	        rolesAttribute.put("multiValued", true); // O true si permites múltiples roles
	        rolesAttribute.put("description", "Rol del usuario en la aplicación");
	        rolesAttribute.put("required", false);
	        rolesAttribute.put("caseExact", false);
	        rolesAttribute.put("mutability", "readWrite");
	        rolesAttribute.put("returned", "default");
	        rolesAttribute.put("uniqueness", "none");
	        
	        // AQUÍ ESTÁ LA CLAVE: canonicalValues le dice a Okta qué mostrar en el Dropdown
	        rolesAttribute.put("canonicalValues", dbRoles);

	        // Definición del Esquema de Extensión
	        Map<String, Object> extensionSchema = new HashMap<>();
	        extensionSchema.put("id", CUSTOM_SCHEMA_URN);
	        extensionSchema.put("name", "CustomUserExtension");
	        extensionSchema.put("description", "Extension personalizada para roles");
	        extensionSchema.put("attributes", Collections.singletonList(rolesAttribute));

	        // Respuesta debe ser una lista de esquemas (incluyendo el Core de User y tu Extensión)
	        // Para brevedad, aquí solo muestro la estructura de la extensión que es lo que importa
	        List<Map<String, Object>> schemas = new ArrayList<>();
	        schemas.add(coreUserSchema);
	        schemas.add(extensionSchema);
	        return new ResponseEntity<>(schemas, HttpStatus.OK);
	       // return new ResponseEntity<>(Collections.singletonList(extensionSchema), HttpStatus.OK);
	    }

	    /**
	     * PASO 2: Crear el usuario con el rol seleccionado.
	     */
	 
	    @PostMapping("/Users")
	    public ResponseEntity<Map<String, Object>> createUser(@RequestBody Map<String, Object> payload) {
	        
	        // 1. Extraer datos básicos (Core Schema)
	        String userName = (String) payload.get("userName");
	        
	        // 2. Extraer el rol de la extensión personalizada
	        String selectedRole = "Sin Rol"; // Default
	        
	        if (payload.containsKey(CUSTOM_SCHEMA_URN)) {
	            Map<String, Object> customAttributes = (Map<String, Object>) payload.get(CUSTOM_SCHEMA_URN);
	            if (customAttributes != null && customAttributes.containsKey("roles")) {
	                selectedRole = (String) customAttributes.get("roles");
	            }
	        }

	        // 3. Lógica de negocio: Guardar en Base de Datos
	        // userService.save(userName, selectedRole);
	        System.out.println("Creando usuario: " + userName + " con Rol: " + selectedRole);

	        // 4. Retornar respuesta SCIM estándar (Usuario creado)
	        Map<String, Object> response = new HashMap<>(payload);
	        response.put("id", UUID.randomUUID().toString()); // ID generado por tu BD
	        
	        return new ResponseEntity<>(response, HttpStatus.CREATED);
	    }
	

	@GetMapping("/scim/v2/Users/{id}")
	public ResponseEntity<?> ObtenerUno(HttpServletRequest request, HttpServletResponse response,
			@PathVariable("id") String userId) throws ParseException, IOException {
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		// HttpSession sessionuserid = request.getSession();
		RespuestaDto respuesta = new RespuestaDto("", false);
		String tokendef = varTokenprovissioning;
		String emailToSearch = null;
		String SentenciaBase = "";
		String idtokenrequest = request.getHeader("Authorization");
		// idtokenrequest = idtokenrequest.substring(7);
		OktaProvissionDto detailOktaProvissionDto = new OktaProvissionDto();
		// if (tokendef.equals(idtokenrequest)) {
		if (idtokenrequest == null || !tokendef.equals(idtokenrequest)) {
			List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
			detailOktaProvissionDto.setDetail("Sin autorización");
			detailOktaProvissionDto.setSchemas(scimSchema);
			detailOktaProvissionDto.setStatus("401");

			return new ResponseEntity(detailOktaProvissionDto, HttpStatus.UNAUTHORIZED);

		} else {

			// emailToSearch = matcher.group(1); // Captura el email/userName
			SentenciaBase = "SELECT cast(u.id as text) as id,u.usr,u.name,u.email,u.rolid,u.workerid,u.supplierid,u.status FROM main.users u WHERE cast(u.id as text) = "
					+ "'" + userId + "'";

			String givenName = "";
			String familyName = "";
			List<ScimUserResource> scimResources = new ArrayList<>();
			String now = ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT);
			String mensaje = "valor";
			// ScimListResponse responseData = new ScimListResponse();
			List<Map<String, Object>> lista = jdbcTemplate.queryForList(SentenciaBase);

			for (Map<String, Object> mapa : lista) {
				ScimUserResource resource = new ScimUserResource();

				// int id = (int) mapa.get("id");
				String id = (String) mapa.get("id");
				// String usr = (String) mapa.get("usr");
				String usr = (String) mapa.get("email");
				int status = (int) mapa.get("status");
				resource.setId(id);
				resource.setUserName(usr);
				if (status == 1) {
					resource.setActive(true);
				} else {
					resource.setActive(false);
				}

				if (mapa.get("name") != null && !((String) mapa.get("name")).trim().isEmpty()) {
					String name = (String) mapa.get("name");
					String[] partes = name.trim().split("\\s+", 2);
					if (partes.length > 0) {
						givenName = partes[0]; // Primer trozo es el Nombre
					}
					if (partes.length > 1) {
						familyName = partes[1]; // El resto es el Apellido
					} else {
						// Caso borde: Si solo viene "Pedro", el apellido se deja vacío o se repite
						familyName = "";
					}
					System.out.print(partes);
				}
				// Datos de 'name'
				ScimUserResource.Name name = new ScimUserResource.Name();
				name.setGivenName(givenName);
				name.setFamilyName(familyName);
				name.setFormatted(givenName + " " + familyName);
				resource.setName(name);

				// Datos de 'emails'
				ScimUserResource.Email email = new ScimUserResource.Email();
				email.setValue(usr);
				email.setType("work");
				email.setPrimary(true);
				resource.setEmails(Arrays.asList(email));

				// Datos de 'meta'
				ScimUserResource.Meta meta = new ScimUserResource.Meta();
				meta.setResourceType("User");
				meta.setCreated(now);
				meta.setLastModified(now);
				meta.setLocation(SCIM_BASE_URL + "/" + id);
				resource.setMeta(meta);
				scimResources.add(resource);

			}
	
			// 3. Construcción de la respuesta definitiva SCIM (ListResponse)
			ScimListResponse responseData = new ScimListResponse();
			responseData.setTotalResults(scimResources.size());
			responseData.setStartIndex(1);
			responseData.setItemsPerPage(scimResources.size());
			responseData.setResources(scimResources);
	
			// 4. ENVÍO DE LA RESPUESTA (HTTP 200 OK)
			return ResponseEntity.ok(responseData);
		}
		// return new ResponseEntity(respuesta, estatus);
	}
	
	
	@RequestMapping(value = "/scim/v2/Users/{id}", method = RequestMethod.PUT)
	public ResponseEntity<?> updateUser(HttpServletRequest request, HttpServletResponse response,
			@PathVariable("id") String userId, @RequestBody SchemaOktaCreateDto schemaOktaCreateDto) {
		try {
			HttpStatus estatus = HttpStatus.FORBIDDEN;
			RespuestaDto respuesta = new RespuestaDto("", false);
			String tokendef = varTokenprovissioning;
			Optional<Users> encontreSessionUsuario;
			String concatNameApellido;
			//String idtokenrequest = request.getHeader("Authorization");
			// idtokenrequest = idtokenrequest.substring(7);Roles objetoRoles=null;
			Roles objetoRoles = null;
			String valorroles = "";
			String selectedRole = ""; // Default
			OktaProvissionDto detailOktaProvissionDto = new OktaProvissionDto();
            
			// --- Declaraciones y Lógica de Roles (MODIFICADA) ---
            String selectedRoleName = ""; 
            
            // 1. PRIORIDAD 1: Intentar leer roles del array 'groups' (SCIM estándar)
            /*if (schemaOktaCreateDto.getCustomExtension().getGroups()!= null && !schemaOktaCreateDto.getCustomExtension().getGroups().isEmpty()) {
                // Tomamos el 'display' (nombre legible) del primer grupo/rol
                selectedRoleName = schemaOktaCreateDto.getCustomExtension().getGroups();
            } 
            // 2. RETROCESO: Si no hay 'groups', intentar leer de la extensión personalizada (Tu código original)
            else {*/
                try {
                    // Si tu DTO tiene un getCustomExtension() para tu formato antiguo:
                    selectedRoleName = schemaOktaCreateDto.getCustomExtension().getRoles();
                } catch (Exception e) {
                    selectedRoleName = ""; // Sin rol detectado
                }
            //}
            
            // 3. VALIDACIÓN Y ASIGNACIÓN DEL ROL
            
            if (selectedRoleName.isEmpty() || selectedRoleName.equals("Sin rol")) {
                // Asigna el rol por defecto
                selectedRoleName = "Solo Ver";
                objetoRoles = rolesService.getRolesByName(selectedRoleName);
            } else {
                boolean existerol = rolesRepository.existsByName(selectedRoleName);
                if (existerol) {
                    objetoRoles = rolesService.getRolesByName(selectedRoleName);
                } else {
                    // Error 409 Conflict: El rol no existe
                    List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
                    detailOktaProvissionDto.setDetail("Error - El rol asignado no pertenece a la aplicación");
                    detailOktaProvissionDto.setSchemas(scimSchema);
                    detailOktaProvissionDto.setStatus("409");
                    return new ResponseEntity(detailOktaProvissionDto, HttpStatus.CONFLICT);
                }
            }
            
        	String idtokenrequest = request.getHeader("Authorization");
    		if (idtokenrequest.contains("Bearer")) {
    			idtokenrequest = idtokenrequest.substring(7);
    		} else {
    			idtokenrequest = idtokenrequest;
    		}


			// if (tokendef.equals(idtokenrequest)) {
			if (idtokenrequest == null || !tokendef.equals(idtokenrequest)) {
				List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
				detailOktaProvissionDto.setDetail("Sin autorización");
				detailOktaProvissionDto.setSchemas(scimSchema);
				detailOktaProvissionDto.setStatus("401");

				return new ResponseEntity(detailOktaProvissionDto, HttpStatus.UNAUTHORIZED);

			} else {
				// validacion de la existencia del usuario
				boolean existeuser;
				existeuser = usersRepository.existsById(Integer.parseInt(userId));
				if (!existeuser) {
					List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
					detailOktaProvissionDto.setDetail("Error - El usuario no se encuentra registrado");
					detailOktaProvissionDto.setSchemas(scimSchema);
					detailOktaProvissionDto.setStatus("404");
					return new ResponseEntity(detailOktaProvissionDto, HttpStatus.NOT_FOUND);
					
				}
				if (schemaOktaCreateDto.getEmails().get(0).getValue() == null) {
					List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
					detailOktaProvissionDto.setDetail("El email no puede ser vacío");
					detailOktaProvissionDto.setSchemas(scimSchema);
					detailOktaProvissionDto.setStatus("400");
					return new ResponseEntity(detailOktaProvissionDto, HttpStatus.BAD_REQUEST);
				}

				boolean isGivenNameMissing = schemaOktaCreateDto.getName().getGivenName() == null
						|| schemaOktaCreateDto.getName().getGivenName().isEmpty();
				boolean isFamilyNameMissing = schemaOktaCreateDto.getName().getFamilyName() == null
						|| schemaOktaCreateDto.getName().getFamilyName().isEmpty();

				// Entra al IF si AL MENOS UNO de los dos está ausente (es null O es vacío)
				if (isGivenNameMissing || isFamilyNameMissing) {
					// Lanzar el Error 400
					List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
					detailOktaProvissionDto.setDetail("Campo Nulo");
					detailOktaProvissionDto.setSchemas(scimSchema);
					detailOktaProvissionDto.setStatus("400");
					return new ResponseEntity(detailOktaProvissionDto, HttpStatus.BAD_REQUEST);
				} else {
					// Si ambos existen (NO son nulos), proceder a la concatenación
					concatNameApellido = schemaOktaCreateDto.getName().getGivenName().toLowerCase()
							+ schemaOktaCreateDto.getName().getFamilyName().toLowerCase();
				}
				if (concatNameApellido != null) {
					Optional<Params> deCarateresPer = paramsRepository.findByParamname("TEXTBOX_ALLOWED");
					String caracterespermi = deCarateresPer.get().getValue();

					for (int i = 0; i < concatNameApellido.length(); i++) {

						char currentChar = concatNameApellido.charAt(i);
						// Verificar si el carácter no está en el conjunto de permitidos
						if (caracterespermi.indexOf(currentChar) == -1) {

							String var = "";
							boolean bloked = false;
							RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
							// respuestaDto.setBlocked(bloked);
							respuestaDto.setMsg("Caracteres no permitidos en el Nombre o Apellido del Usuario");
							return new ResponseEntity(respuestaDto, HttpStatus.BAD_REQUEST);
						}
					}

				} else {
					List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
					detailOktaProvissionDto.setDetail("Nombre es Nulo");
					detailOktaProvissionDto.setSchemas(scimSchema);
					detailOktaProvissionDto.setStatus("403");

					return new ResponseEntity(detailOktaProvissionDto, HttpStatus.FORBIDDEN);
				}

				if (schemaOktaCreateDto.getExternalId() == null) {
					List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
					detailOktaProvissionDto.setDetail("Externalid es Nulo");
					detailOktaProvissionDto.setSchemas(scimSchema);
					detailOktaProvissionDto.setStatus("403");

					return new ResponseEntity(detailOktaProvissionDto, HttpStatus.FORBIDDEN);
				}

				Optional<Users> tipoUsersNew3 = usersRepository.findById(Integer.parseInt(userId));
				Users tipoUsersNew = tipoUsersNew3.get();
				String SalidaName = schemaOktaCreateDto.getName().getGivenName();
				// String SalidaName= schemaOktaCreateDto.getProfile().getGivenName();
				String SalidaApellido = schemaOktaCreateDto.getName().getFamilyName();
				// String SalidaApellido = schemaOktaCreateDto.getProfile().getFamilyName();
				// String Salidaemail = schemaOktaCreateDto.getProfile().getEmail();
				String Salidaemail = schemaOktaCreateDto.getEmails().get(0).getValue();
				Date fecha = new Date();
				SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				String dataFormattata = formatter.format(fecha);
				Date fechaDate = formatter.parse(dataFormattata);
				if (SalidaName == "NOOK" || SalidaApellido == "NOOK" || Salidaemail == "NOOK") {
					List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
					detailOktaProvissionDto.setDetail("Caracteres no Permitidos");
					detailOktaProvissionDto.setSchemas(scimSchema);
					detailOktaProvissionDto.setStatus("403");

					return new ResponseEntity(detailOktaProvissionDto, HttpStatus.FORBIDDEN);
				}

				// aqui comenzamos a actualizar el usuario hacia la tabla de Users
				tipoUsersNew.setStatus(1);

				Users tipoUsersNew2 = null;
				tipoUsersNew.setName(SalidaApellido + ", " + SalidaName);
				tipoUsersNew.setUsr(schemaOktaCreateDto.getUserName());
				tipoUsersNew.setEmail(Salidaemail);
				tipoUsersNew.setModifiedat(fechaDate);
				
				tipoUsersNew.setLastpwdchange(fechaDate);
				tipoUsersNew.setFails(0);
				tipoUsersNew.setLastsession(fechaDate);
				
				tipoUsersNew.setRolid(objetoRoles);
				
				/*if (valorroles.equals("Sin rol")) {
					selectedRole = "Solo Ver";
					objetoRoles = rolesService.getRolesByName(selectedRole);
					tipoUsersNew.setRolid(objetoRoles);
				} else {
					Roles tipoRol = rolesService.getRolesByName(selectedRole);
					tipoUsersNew.setRolid(tipoRol);
				}*/
				
				tipoUsersNew2 = usersService.addIdUsers(tipoUsersNew);
				encontreSessionUsuario = usersRepository.getByEmail(Salidaemail);
				int idregistrado = encontreSessionUsuario.get().getId();

				String SentenciaBase = "SELECT cast(u.id as text) as id,u.usr,u.name,u.email,u.rolid,u.workerid,u.supplierid,u.status FROM main.users u WHERE u.id = "
						+ idregistrado;
				String givenName = "";
				String familyName = "";
				List<ScimUserResource> scimResources = new ArrayList<>();
				String now = ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT);
				String mensaje = "valor";
				// ScimListResponse responseData = new ScimListResponse();
				List<Map<String, Object>> lista = jdbcTemplate.queryForList(SentenciaBase);
				ScimUserResponseDto scimUserResponseDto = new ScimUserResponseDto();
				List<oktaEmailDto> listoktaEmailDto = new ArrayList<>();
				for (Map<String, Object> mapa : lista) {
					ScimUserResource resource = new ScimUserResource();
					OktaNameResponseDto name = new OktaNameResponseDto();
					oktaEmailDto email = new oktaEmailDto();
					OktaMetaRespDto meta = new OktaMetaRespDto();
					// ScimUserResource.Name name = new ScimUserResource.Name();

					// int id = (int) mapa.get("id");
					String id = (String) mapa.get("id");
					// String usr = (String) mapa.get("usr");
					String usr = (String) mapa.get("email");
					int status = (int) mapa.get("status");
					// resource.setId(id);
					scimUserResponseDto.setSchemas(Arrays.asList("urn:ietf:params:scim:schemas:core:2.0:User"));
					scimUserResponseDto.setId(id);
					scimUserResponseDto.setUserName(usr);
					// resource.setUserName(usr);
					if (status == 1) {
						scimUserResponseDto.setActive(true);
					} else {
						scimUserResponseDto.setActive(false);
					}

					if (mapa.get("name") != null && !((String) mapa.get("name")).trim().isEmpty()) {
						String nameIn = (String) mapa.get("name");
						String[] partes = nameIn.trim().split("\\s+", 2);
						if (partes.length > 0) {
							givenName = partes[0]; // Primer trozo es el Nombre
						}
						if (partes.length > 1) {
							familyName = partes[1]; // El resto es el Apellido
						} else {
							// Caso borde: Si solo viene "Pedro", el apellido se deja vacío o se repite
							familyName = "";
						}
						System.out.print(partes);
					}
					// Datos de 'name'

					name.setGivenName(givenName);
					name.setFamilyName(familyName);
					scimUserResponseDto.setName(name);
					// resource.setName(name);
					scimUserResponseDto.setExternalId(id);

					// Datos de 'emails'
					// ScimUserResource.Email email = new ScimUserResource.Email();
					email.setValue(usr);
					email.setType("work");
					email.setPrimary(true);
					listoktaEmailDto.add(email);
					scimUserResponseDto.setEmails(listoktaEmailDto);
					// resource.setEmails(Arrays.asList(email));

					// Datos de 'meta'
					// ScimUserResource.Meta meta = new ScimUserResource.Meta();
					meta.setResourceType("User");
					meta.setCreated(now);
					meta.setLastModified(now);
					meta.setLocation(SCIM_BASE_URL + "/" + id);
					scimUserResponseDto.setMeta(meta);
					// resource.setMeta(meta);
					// scimResources.add(resource);

				}

				return ResponseEntity.ok(scimUserResponseDto);
			}

		} catch (IllegalArgumentException e) {
			// Manejo de recursos no encontrados (debe ser lanzado desde el servicio)
			System.err.println("Recurso SCIM no encontrado o ID inválido: " + e.getMessage());
			// Devolver 404 Not Found
			return ResponseEntity.notFound().build();
		} catch (Exception e) {
			System.err.println("Error fatal al actualizar usuario SCIM: " + e.getMessage());
			// Devolver 500 Internal Server Error
			return ResponseEntity.internalServerError().build();
		}
	}


	@RequestMapping(value = "/scim/v2/Users/{id}", method = RequestMethod.PATCH)
	public ResponseEntity<?> borrarUsuario(HttpServletRequest request, @PathVariable("id") String userId)
			throws ParseException {

		String tokendef = varTokenprovissioning;
		String idtokenrequest = request.getHeader("Authorization");
		OktaProvissionDto detailOktaProvissionDto = new OktaProvissionDto();
		if (idtokenrequest == null || !tokendef.equals(idtokenrequest)) {
			List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
			detailOktaProvissionDto.setDetail("No tiene privilegios");
			detailOktaProvissionDto.setSchemas(scimSchema);
			detailOktaProvissionDto.setStatus("401");
			return new ResponseEntity(detailOktaProvissionDto, HttpStatus.UNAUTHORIZED);
		}

		// Buscar usuario
		Optional<Users> u = usersRepository.findById(Integer.parseInt(userId));
		detailOktaProvissionDto = new OktaProvissionDto();
		if (!u.isPresent()) {
			List<String> scimSchema = Arrays.asList("urn:ietf:params:scim:api:messages:2.0:Error");
			detailOktaProvissionDto.setDetail("El id de usuario no existe");
			detailOktaProvissionDto.setSchemas(scimSchema);
			detailOktaProvissionDto.setStatus("400");
			return new ResponseEntity(detailOktaProvissionDto, HttpStatus.BAD_REQUEST);
		}

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

		// Desacctivar el usuario
		u.get().setStatus(0);
		u.get().setModifiedat(fechaDate);
		// guarda el usuario
		usersRepository.save(u.get());

		String SentenciaBase = "SELECT cast(u.id as text) as id,u.usr,u.name,u.email,u.rolid,u.workerid,u.supplierid,u.status FROM main.users u WHERE cast(u.id as text) = "
				+ "'" + userId + "'";

		String givenName = "";
		String familyName = "";
		List<ScimUserResource> scimResources = new ArrayList<>();
		String now = ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT);
		String mensaje = "valor";
		// ScimListResponse responseData = new ScimListResponse();
		List<Map<String, Object>> lista = jdbcTemplate.queryForList(SentenciaBase);

		for (Map<String, Object> mapa : lista) {
			ScimUserResource resource = new ScimUserResource();

			// int id = (int) mapa.get("id");
			String id = (String) mapa.get("id");
			// String usr = (String) mapa.get("usr");
			String usr = (String) mapa.get("email");
			int status = (int) mapa.get("status");
			resource.setId(id);
			resource.setUserName(usr);
			if (status == 1) {
				resource.setActive(true);
			} else {
				resource.setActive(false);
			}

			if (mapa.get("name") != null && !((String) mapa.get("name")).trim().isEmpty()) {
				String name = (String) mapa.get("name");
				String[] partes = name.trim().split("\\s+", 2);
				if (partes.length > 0) {
					givenName = partes[0]; // Primer trozo es el Nombre
				}
				if (partes.length > 1) {
					familyName = partes[1]; // El resto es el Apellido
				} else {
					// Caso borde: Si solo viene "Pedro", el apellido se deja vacío o se repite
					familyName = "";
				}
				System.out.print(partes);
			}
			// Datos de 'name'
			ScimUserResource.Name name = new ScimUserResource.Name();
			name.setGivenName(givenName);
			name.setFamilyName(familyName);
			name.setFormatted(givenName + " " + familyName);
			resource.setName(name);

			// Datos de 'emails'
			ScimUserResource.Email email = new ScimUserResource.Email();
			email.setValue(usr);
			email.setType("work");
			email.setPrimary(true);
			resource.setEmails(Arrays.asList(email));

			// Datos de 'meta'
			ScimUserResource.Meta meta = new ScimUserResource.Meta();
			meta.setResourceType("User");
			meta.setCreated(now);
			meta.setLastModified(now);
			meta.setLocation(SCIM_BASE_URL + "/" + id);
			resource.setMeta(meta);
			scimResources.add(resource);

		}

		// 3. Construcción de la respuesta definitiva SCIM (ListResponse)
		ScimListResponse responseData = new ScimListResponse();
		responseData.setTotalResults(scimResources.size());
		responseData.setStartIndex(1);
		responseData.setItemsPerPage(scimResources.size());
		responseData.setResources(scimResources);

		return ResponseEntity.ok(responseData);
	}

	@GetMapping("/oAuth2/login")
	public ResponseEntity<String> btenerUnoApplications(HttpServletRequest request, HttpServletResponse response)
			throws ParseException, IOException {
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		// HttpSession sessionuserid = request.getSession();
		RespuestaDto respuesta = new RespuestaDto("", false);

		String var = "";
		String state = UUID.randomUUID().toString();
		HttpSession session = request.getSession();
		HttpSession sessionLogin = request.getSession();
		session.setAttribute("state", state);

		String sessionid2 = (String) sessionLogin.getAttribute("sessionidGl");
		String entrypoint2 = (String) sessionLogin.getAttribute("entrypointGl");
		String validthru2 = (String) sessionLogin.getAttribute("validthruGl");
		String fullname2 = (String) sessionLogin.getAttribute("fullnameGl");
		String correoEmail = (String) session.getAttribute("emailuser");

		String redirectUrl;
		Optional<Users> optionalUsuario;
		String fechabien = "";
		Date validtrhuString;

		if (session.getAttribute("iduser") != null) {

			// hacer una redireccion al acces con las variables de session del entry point
			// session id y validthru
			boolean existeuser = usersRepository.existsByEmail(correoEmail);
			if (existeuser) {
				optionalUsuario = usersService.getByEmail(correoEmail);
				String pwd = "no";
				// aqui deberia llamar el metodo actual de Login pasandole el Usernickname o
				// correo y la clave
				LoginUsuario loginUsuario = new LoginUsuario();
				loginUsuario.setUsr(optionalUsuario.get().getUsr());
				loginUsuario.setPwd(pwd);
				loginUsuario.setTipo("oauth2");
				HttpHeaders headers = new HttpHeaders();
				headers.setContentType(MediaType.APPLICATION_JSON);
				headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
				HttpEntity<LoginUsuario> requestEntity = new HttpEntity<>(loginUsuario, headers);
				ResponseEntity<JwtDto> loginResponse = restTemplate.exchange(dirlocal + "/login", HttpMethod.POST,
						requestEntity, JwtDto.class);

				JwtDto jwtDto = loginResponse.getBody();
				sessionid2 = jwtDto.getSessionid();
				validthru2 = jwtDto.getValidthru().toString();
				entrypoint2 = jwtDto.getEntrypoint();
				fullname2 = jwtDto.getFullname();
				Instant instant = jwtDto.getValidthru().toInstant();
				ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
				DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
				fechabien = zonedDateTime.format(formatter);
				validtrhuString = jwtDto.getValidthru();
				sessionLogin.setAttribute("sessionidGl", sessionid2);
				sessionLogin.setAttribute("validthruGl", fechabien);
				sessionLogin.setAttribute("entrypointGl", entrypoint2);
				sessionLogin.setAttribute("fullnameGl", fullname2);
				sessionLogin.setAttribute("validtrhuDateGl", validtrhuString);

			}
			String externalUrl = urlAmbiente + "content/access.php";

			String postRedirectHtml = createPostRedirectForm(externalUrl, sessionid2, entrypoint2, fullname2,
					validthru2);

			HttpHeaders headersResult = new HttpHeaders();
			headersResult.setContentType(MediaType.TEXT_HTML);
			return new ResponseEntity<>(postRedirectHtml, HttpStatus.OK);

		} else {
			String url = issuerUri + vauth + "?response_type=code&client_id=" + clientId + "&redirect_uri="
					+ redirect_uri + "&state=" + state + "&scope=" + scope;
			String encoding2 = StandardCharsets.UTF_8.toString();
			String caracteresCodificados2 = URLEncoder.encode(url, encoding2);
			response.sendRedirect(url);
		
		}

		return new ResponseEntity(respuesta, estatus);
	}
	
	
	
	@GetMapping("/oAuth2/callback")
	public ResponseEntity<String> btenercallback(HttpServletRequest request, @RequestParam("code") final String code,
			@RequestParam("state") final String state) throws Exception {
		// HttpStatus estatus = HttpStatus.FORBIDDEN;
		
		 JsonoauthDto valorhttp; 
      //   String var = "Hola Mundo callback2";
         HttpSession session = request.getSession();
         HttpSession sessionLogin = request.getSession();
         String code2 = code;
         String stateRec = state;
         String response;
         String error;     
         String state2 = session.getAttribute("state").toString();
		if (code == null) {
        	 error = "No se recibio el codigo de autorizacion ";
           	 
         }
         
		if (session.getAttribute("state").toString().compareTo(stateRec) == 0) {
        	error = "estado valido";
        
        	// granttype
        	
        	String url = issuerUri + vtoken;
        	String urlinfo = issuerUri + vuserinfo;
        	String encoding2 = StandardCharsets.UTF_8.toString();
        	
			String params = "grant_type=" + "authorization_code&client_id=" + clientId + "&client_secret=" + clienteSec
					+ "&redirect_uri=" + URLEncoder.encode(redirect_uri, encoding2) + "&code=" + code;
		
			
			 response= sendPostRequest(url, params);
        	boolean esjson = isValidJson(response);
        	
        	//String response = "d";
        	//error = response;
        	if (esjson) {
        		
       
        	ObjectMapper objectMapper = new ObjectMapper();
        	
        	JsonNode rootNode = objectMapper.readTree(response);
        	
        	System.out.print(rootNode);
        	
            String accessToken = rootNode.path("access_token").asText();
            String id_token = rootNode.path("id_token").asText();
        
            // Llamada al endpoint de okta userinfo
			String responseInfo = sendRequest(urlinfo, accessToken);
            JsonNode rootNodeinfo = objectMapper.readTree(responseInfo);
            String iduser = rootNodeinfo.path("sub").asText();
			String nameuser = rootNodeinfo.path("name").asText();
            String emailuser = rootNodeinfo.path("email").asText();
            Optional<Users> optionalUsuario;
            boolean existeuser;
            existeuser = usersRepository.existsByEmail(emailuser);
			final String baseurl = dirlocal;
			// existeuser = false;
            if (existeuser) {
            	optionalUsuario = usersService.getByEmail(emailuser);
            	String pwd = "no";
				// aqui deberia llamar el metodo actual de Login pasandole el Usernickname o
				// correo y la clave
            	LoginUsuario loginUsuario = new LoginUsuario();
            	loginUsuario.setUsr(optionalUsuario.get().getUsr());
            	loginUsuario.setPwd(pwd);
            	loginUsuario.setTipo("oauth2");
            	
            	HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
                HttpEntity<LoginUsuario> requestEntity = new HttpEntity<>(loginUsuario, headers);
				String sessionid = "";
				String validthru = "";
				String entrypoint = "";
				String fullname = "";
				String fechabien = "";
                Date validtrhuString;
                try {
                	// aqui invoco el metodo login con el request body de login usuario
					ResponseEntity<JwtDto> loginResponse = restTemplate.exchange(baseurl + "/login", HttpMethod.POST,
							requestEntity, JwtDto.class);
                   
                    // tomando al respuesta del login
                    if (loginResponse.getStatusCode() == HttpStatus.OK) {
                        JwtDto jwtDto = loginResponse.getBody();
                         sessionid = jwtDto.getSessionid();
                         validthru = jwtDto.getValidthru().toString();
						entrypoint = jwtDto.getEntrypoint();
                         fullname = jwtDto.getFullname();
                         Instant instant = jwtDto.getValidthru().toInstant();
                         ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
                         DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
                         fechabien = zonedDateTime.format(formatter);
                         validtrhuString = jwtDto.getValidthru();
                         
                        String externalUrl = urlAmbiente + "content/access.php";
						String redirectUrl = externalUrl + "?sessionid="
								+ URLEncoder.encode(sessionid, StandardCharsets.UTF_8.toString()) + "&entrypoint="
								+ URLEncoder.encode(entrypoint, StandardCharsets.UTF_8.toString()) + "&fullname="
								+ URLEncoder.encode(fullname, StandardCharsets.UTF_8.toString()) + "&validthru="
								+ fechabien;
                        sessionLogin.setAttribute("sessionidGl", sessionid);
                        sessionLogin.setAttribute("validthruGl", fechabien);
                        sessionLogin.setAttribute("entrypointGl", entrypoint);
                        sessionLogin.setAttribute("fullnameGl", fullname);
                        sessionLogin.setAttribute("validtrhuDateGl", validtrhuString);
                        
                    	session.setAttribute("iduser", iduser);
                    	session.setAttribute("nameuser", nameuser);
                    	session.setAttribute("emailuser", emailuser);
                    	session.setAttribute("accessToken", accessToken);
						// aqui debo retornar lo que indique Javier llamo a nuevo endpoint access.php
						// con Recibe estos 3 parámetros: "sessionid","entrypoint","validthru"
                    	System.out.print(redirectUrl);
						String postRedirectHtml = createPostRedirectForm(externalUrl, sessionid, entrypoint, fullname,
								fechabien);
                    	
                    	HttpHeaders headersResult = new HttpHeaders();
                        headersResult.setContentType(MediaType.TEXT_HTML);
                        return new ResponseEntity<>(postRedirectHtml, HttpStatus.OK);
                    	
					
                    
                    } else {
                       
                        
                        String externalUrl = urlAmbiente + "content/access.php";
                        String redirectUrl = externalUrl + 
                            // ... (Construcción de la URL de redirección) ...
								"?sessionid=" + URLEncoder.encode(sessionid, StandardCharsets.UTF_8.toString())
								+ "&entrypoint=" + URLEncoder.encode("LOGIN_FAILED", StandardCharsets.UTF_8.toString())
								+ "&fullname=" + URLEncoder.encode(fullname, StandardCharsets.UTF_8.toString()) +
                           // "&validthruDate=" + validtrhuDate +
                            "&validthru=" + fechabien;
                        
						String postRedirectHtml = createPostRedirectForm(externalUrl, sessionid, entrypoint, fullname,
								fechabien);
                    
                        return new ResponseEntity<>(postRedirectHtml, HttpStatus.BAD_REQUEST);
                       
                    }

                } catch (Exception e) {
					
                    System.out.println("Error en la llamada interna al /login: " + e.getMessage());
                    
					return new ResponseEntity<>(
							"Error con el servicio de login. Acceso denegado.",
							HttpStatus.FORBIDDEN);
                }
                
            	
            } else {
            	
            	String sessionidNoexiste = "";
            	String entrypointNoexiste = "";
            	String fullnameNoexiste = "";
            	String fechabienNoexiste = "";
				String postRedirectHtml = createPostRedirectForm(urlOktaExist, sessionidNoexiste, entrypointNoexiste,
						fullnameNoexiste, fechabienNoexiste);
            	
            	HttpHeaders headersResult = new HttpHeaders();
                headersResult.setContentType(MediaType.TEXT_HTML);
                return new ResponseEntity<>(postRedirectHtml, HttpStatus.CONFLICT);
            	
            }
        	} else {
    			
    			System.out.print(response);
    			 return new ResponseEntity<>(response,  HttpStatus.BAD_REQUEST);
    			 }      	        	
		} else {
        	error = "estado invalido";
        	
			// reenviar al index
         }
		    
        return new ResponseEntity<>("Enrrutado a Access exitosamente.", HttpStatus.OK);
		
   }
	
	public static String sendPostRequest(String urlString, String jsonBody) throws Exception {
	    URL url = new URL(urlString);
	    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
	    
	    // 1. Configurar la conexión (DEBE IR ANTES DE CUALQUIER OTRA OPERACIÓN)
	    conn.setRequestMethod("POST");
	    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
	    conn.setRequestProperty("Accept", "application/json");
	    conn.setDoOutput(true); // Indica que vamos a enviar un cuerpo
	    // conn.getResponseMessage(); <--- ¡ELIMINADO! Esto se hace al final.
	    
	    // 2. Enviar el cuerpo de la solicitud (los datos)
	    try (OutputStream os = conn.getOutputStream()) {
	        // Convertimos el JSON a bytes usando la codificación UTF-8
	        byte[] input = jsonBody.getBytes("utf-8");
	        os.write(input, 0, input.length);
	    } // El recurso OutputStream se cierra automáticamente aquí
	    
	    // 3. Obtener el Código y el Mensaje de Respuesta (AHORA se inicia la conexión)
	    int responseCode = conn.getResponseCode(); // Inicia la conexión
	    String responseMessage = conn.getResponseMessage(); 

	    System.out.print("jsonBody: " + jsonBody + "\n");
	    System.out.print("urlString: " + urlString + "\n");
	    System.out.print("Response Code: " + responseCode + "\n");

	    // 4. Leer la respuesta del servidor
	    if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED) {
	        // Lectura si la respuesta es exitosa
	        try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"))) {
	            StringBuilder response = new StringBuilder();
	            String responseLine;
	            while ((responseLine = br.readLine()) != null) {
	                response.append(responseLine.trim());
	            }
	            return response.toString();
	        }
	    } else {
	        // Manejo de errores 
	        try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getErrorStream(), "utf-8"))) {
	            StringBuilder errorResponse = new StringBuilder();
	            String errorLine;
	            while ((errorLine = br.readLine()) != null) {
	                errorResponse.append(errorLine.trim());
	            }
	            // En lugar de lanzar una RuntimeException, usted está regresando un String
	            return "error else " + responseMessage + " " +  responseCode + " - Detalles: " + errorResponse.toString();
	        } catch (Exception e) {
	            // Si getErrorStream() falla o es nulo
	            return "error else " + responseMessage + " " +  responseCode + " - No se pudo leer el stream de error.";
	        }
	    }
	}
	
	public static String sendRequest(String urlString, String access_token) throws Exception {
        URL url = new URL(urlString);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
       
        // 1. Configurar la conexión para POST
       // conn.setRequestMethod("POST");
        conn.setRequestProperty("Accept", "application/json");
        conn.setRequestProperty("Authorization", "Bearer " + access_token);
        
        conn.setDoOutput(true); // Indica que vamos a enviar un cuerpo
    
        int responseCode = conn.getResponseCode();
       
        if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED) {
            // Lectura si la respuesta es exitosa
            try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"))) {
                StringBuilder response = new StringBuilder();
                String responseLine;
                while ((responseLine = br.readLine()) != null) {
                    response.append(responseLine.trim());
                }
                return response.toString();
            }
        } else {
            // Manejo de errores (puedes leer conn.getErrorStream() para más detalles)
            throw new RuntimeException("Fallo la petición POST. Código de estado: " + responseCode);
        }
    }
	
	private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * Valida si una cadena de texto es un JSON válido.
     * @param jsonString La cadena a validar.
     * @return true si es JSON válido, false en caso contrario.
     */
    public static boolean isValidJson(String jsonString) {
        if (jsonString == null || jsonString.trim().isEmpty()) {
            return false;
        }
        try {
            // Intenta leer la cadena como un objeto JSON genérico (JsonNode)
            // Si el parsing falla, lanza JsonProcessingException
            objectMapper.readTree(jsonString);
            return true;
        } catch (JsonProcessingException e) {
            // El parsing falló, no es un JSON válido
            return false;
        }
    }
    
    
	@PostMapping("/login")
	public ResponseEntity<JwtDto> login(@Valid @RequestBody LoginUsuario loginUsuario,BindingResult bindingResult) throws ParseException {
		boolean sesionActiva=false;
		Date fecha = new Date();
		
		
		Optional<Users> optionalUsuario;
		String userLogin;
		if (bindingResult.hasErrors())
			return new ResponseEntity(new Mensaje("Campos mal puestos o Email inválido"),HttpStatus.BAD_REQUEST);
		//Optional<Users> optionalUsuario = usersService.getByUsr(loginUsuario.getUsuario());
		   optionalUsuario = usersService.getByUsr(loginUsuario.getUsr());
	       
		if (optionalUsuario.isPresent()) {
			sesionActiva=usersService.consultarSesionEstatus(optionalUsuario.get().getId()); 
			userLogin = optionalUsuario.get().getUsr();
			int activo = optionalUsuario.get().getStatus();
			
			///Validacion por eststus de usuario
			if (activo != 1 && activo != 3) {
				   String var = "Usuario Inactivo";
			         boolean bloked = true;
				     RespuestaDto respuestaDto=new RespuestaDto(var, bloked);
			         respuestaDto.setBlocked(bloked);
			         respuestaDto.setMsg(var);
				//throw new RuntimeException("Su usuario se encuentra inactivo");
			         return new ResponseEntity(respuestaDto, HttpStatus.UNAUTHORIZED);
			  } 
				
			
			
		} else {
			
			 optionalUsuario = usersService.getByEmail(loginUsuario.getUsr());
			
			 if (optionalUsuario.isPresent()) {
				 userLogin = optionalUsuario.get().getUsr();
					sesionActiva=usersService.consultarSesionEstatus(optionalUsuario.get().getId()); 
					
					int activo = optionalUsuario.get().getStatus();
					
					///Validacion por eststus de usuario
					if (activo != 1 && activo != 3) {
						   String var = "Usuario Inactivo";
					         boolean bloked = true;
						     RespuestaDto respuestaDto=new RespuestaDto(var, bloked);
					         respuestaDto.setBlocked(bloked);
					         respuestaDto.setMsg(var);
					         return new ResponseEntity(respuestaDto, HttpStatus.UNAUTHORIZED);
					  } 
						
					
					
				} else {
			     String var = "Usuario/Clave Inválidos";
		         boolean bloked = false;
			     RespuestaDto respuestaDto=new RespuestaDto(var, bloked);
		         respuestaDto.setBlocked(bloked);
		         respuestaDto.setMsg(var);
		       
		         return new ResponseEntity(respuestaDto, HttpStatus.UNAUTHORIZED);
				}
		}
	
		
		  try {
	
		String jwt;
		UserDetails userDetails;
		UserDetails userDetails2;
		//authentication
		//Valido al Session Activa
	     
		 Date fecha2 = new Date();
		 Optional<Params> dePwdDuration=paramsRepository.findByParamname("PWD_DURATION");
		   String PasswordDuration=dePwdDuration.get().getValue();
		 
		   Optional<Params> deSessDuration=paramsRepository.findByParamname("SESSION_DURATION");
		   String SessionDuration=deSessDuration.get().getValue();
		   
		   
		   int duracionPass = Integer.parseInt(PasswordDuration);
		   int duracionSession = Integer.parseInt(SessionDuration);
		
		          
		        if (loginUsuario.getTipo()==null) {
		    	    Authentication authentication=
			     	autheticationManager.authenticate(new UsernamePasswordAuthenticationToken(userLogin,loginUsuario.getPwd()));
		    	    
	              	SecurityContextHolder.getContext().setAuthentication(authentication);
		            jwt = jwtProvider.generateToken(authentication);
		            userDetails = (UserDetails)authentication.getPrincipal();
		        }  else {
		        	 jwt = jwtProvider.generateTokenoaauth(userLogin);
		        	 String tipologin = "login por el okta";
		        	 System.out.print(tipologin);
		        }      
		            
		           
		            
		            Calendar calendar = Calendar.getInstance();
		            calendar.setTime(fecha2); //tuFechaBase es un Date;
		            calendar.add(Calendar.MINUTE,   duracionSession); //horasASumar es int.
		            Date ValidThrufechaSalida = calendar.getTime(); //Y ya tienes la fecha sumada.
		            		            		            	          
		
		///**********************Aqui valido la vigencia del password********************************************************///
		//Date fecha2 = new Date();
	    SimpleDateFormat  fechactual = new SimpleDateFormat("yyyy-MM-dd");
        String dataFormatfechactual = fechactual.format(fecha2);
  
        SimpleDateFormat Lastpwdchange = new SimpleDateFormat("yyyy-MM-dd");
        String dataFormatLastpwdchange = Lastpwdchange.format(optionalUsuario.get().getLastpwdchange());
        
        DateTimeFormatter formatternuevo = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        LocalDate fechaactual = LocalDate.parse(dataFormatfechactual, formatternuevo);
        LocalDate fechavalida = LocalDate.parse(dataFormatLastpwdchange, formatternuevo);
       
        long startTime = fecha2.getTime();
        long endTime = optionalUsuario.get().getLastpwdchange().getTime();
        long diasDesde = (long) Math.floor(startTime / (1000*60*60*24)); // convertimos a dias, para que no afecten cambios de hora 
        long diasHasta = (long) Math.floor(endTime / (1000*60*60*24)); // convertimos a dias, para que no afecten cambios de hora
        long dias = diasDesde - diasHasta;
        
        if (dias<0) {
        	
        	   boolean bloked = false;
        	   
			   Optional<Params> deMinLength=paramsRepository.findByParamname("PWD_MINLENGTH");
			   String minlongitud=deMinLength.get().getValue();
			   Optional<Params> deSimbolos=paramsRepository.findByParamname("PWD_SYMBOLS");
			   String cantSimbolos=deSimbolos.get().getValue();
			   Optional<Params> deCantMayus=paramsRepository.findByParamname("PWD_UPPERCASE");
			   String cantMayusculas=deCantMayus.get().getValue();
			   Optional<Params> deCantMinus=paramsRepository.findByParamname("PWD_LOWERCASE");
			   String cantMinusculas=deCantMinus.get().getValue();
			   Optional<Params> desimbolosPer=paramsRepository.findByParamname("PWD_ALLOWEDSYM");
			   String simbolospermi=desimbolosPer.get().getValue();
			   String encoding = StandardCharsets.UTF_8.toString();
			   String caracteresCodificados = URLEncoder.encode(simbolospermi, encoding);
			   //String ref = "www.duranyasociados.com";
			   String tokenurl = "=";
			   String token2url = "&";
			   String token3url = "|";
			   
			   // Authentication
			   //String ref="https://vpskromasys2.hostnetcom.com/~daconsult/dev/?sid='" + jwt + "'";
			  // String tokenurl = "&";
				String sid = "changepwd";
				String palabrahash = "hash";
				String palabraemail = "email";
				String conditions = "conditions";
				String hash = jwt;
				String idcampo = "?sid=";
				String ConcatAmbiente = urlAmbiente.concat(idcampo);
				String https = ConcatAmbiente;
				//String https="http://vpskromasys2.hostnetcom.com/~daconsult/dev/?sid=";
				
				
			    String url = https + sid + token2url + "hash" + tokenurl + jwt + token2url + palabraemail + tokenurl + optionalUsuario.get().getEmail() + token2url + conditions + tokenurl +
			    		deMinLength.get().getParamname() + minlongitud + "|" + deSimbolos.get().getParamname() + cantSimbolos + 
                "|" + deCantMayus.get().getParamname() + cantMayusculas + "|" + deCantMinus.get().getParamname() + cantMinusculas + "|" + desimbolosPer.get().getParamname() + caracteresCodificados;

			   
			  // String url = ref.concat(tokenurl).concat(jwt).concat(tokenurl).concat("LongitudMinina=").concat(minlongitud).concat(tokenurl).concat("CantidadSimbolos=").concat(cantSimbolos).concat(tokenurl).concat("CantidadMayusculas=").concat(cantMayusculas).concat(tokenurl).concat("CantidadMinusculas=").concat(cantMinusculas).concat(tokenurl).concat("SimbolosPermitidos=").concat(simbolospermi);
			   RespuestaDto respuestaDto=new RespuestaDto(url, bloked);
			   respuestaDto.setBlocked(bloked);
	           respuestaDto.setMsg(url);
	           int id= optionalUsuario.get().getId();
	           int idestatus= optionalUsuario.get().getStatus();
	           int fail=optionalUsuario.get().getFails();
	           usersService.asociarSessionidUsers(id,jwt,optionalUsuario.get().getLastsession(),fail,idestatus);
	           String module = "Seguridad";
	           String Descmodule = "Login exitoso Password no Vigente" ;
	           
	           AuditRequestDto  auditDto=new AuditRequestDto();
	           auditDto.setIpaddr(HttpReqRespUtils.getClientIpAddressIfServletRequestExist());
	           SimpleDateFormat  formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	           String dataFormattata = formatter.format(fecha);
	           Date fechaDate = formatter.parse(dataFormattata);
	           
	           String singo1 = "(";
	           String singo2 = ")";
	           String usryemail = loginUsuario.getUsr().concat(" ").concat(singo1).concat(optionalUsuario.get().getEmail().concat(singo2));
	           auditDto.setUserref(usryemail);
	           auditDto.setModule(module);
	           auditDto.setDesc(Descmodule);
	           auditDto.setCreatedat(fechaDate);
	   		usersService.registrarAuditSesion(auditDto); 
			   
          return new ResponseEntity(respuestaDto, HttpStatus.OK);
        	
        }
        
        if (dias>duracionPass) {
            boolean bloked = false;
	         
			   Optional<Params> deMinLength=paramsRepository.findByParamname("PWD_MINLENGTH");
			   String minlongitud=deMinLength.get().getValue();
			   Optional<Params> deSimbolos=paramsRepository.findByParamname("PWD_SYMBOLS");
			   String cantSimbolos=deSimbolos.get().getValue();
			   Optional<Params> deCantMayus=paramsRepository.findByParamname("PWD_UPPERCASE");
			   String cantMayusculas=deCantMayus.get().getValue();
			   Optional<Params> deCantMinus=paramsRepository.findByParamname("PWD_LOWERCASE");
			   String cantMinusculas=deCantMinus.get().getValue();
			   Optional<Params> desimbolosPer=paramsRepository.findByParamname("PWD_ALLOWEDSYM");
			   String simbolospermi=desimbolosPer.get().getValue();
			   String encoding = StandardCharsets.UTF_8.toString();
				String caracteresCodificados = URLEncoder.encode(simbolospermi, encoding);
			   //String ref = "www.duranyasociados.com";
			   String tokenurl = "=";
			   String token2url = "&";
			   String token3url = "|";
			   
			   // Authentication
			   //String ref="https://vpskromasys2.hostnetcom.com/~daconsult/dev/?sid='" + jwt + "'";
			  // String tokenurl = "&";
				String sid = "changepwd";
				String palabrahash = "hash";
				String palabraemail = "email";
				String conditions = "conditions";
				String hash = jwt;
				String idcampo = "?sid=";
				String ConcatAmbiente = urlAmbiente.concat(idcampo);
				String https = ConcatAmbiente;
				//String https="http://vpskromasys2.hostnetcom.com/~daconsult/dev/?sid=";
				   String module = "Seguridad";
		           String Descmodule = "Login exitoso Password no Vigente" ;
		           
		           AuditRequestDto  auditDto=new AuditRequestDto();
		           auditDto.setIpaddr(HttpReqRespUtils.getClientIpAddressIfServletRequestExist());
		           SimpleDateFormat  formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		           String dataFormattata = formatter.format(fecha);
		           Date fechaDate = formatter.parse(dataFormattata);
		           
		           String singo1 = "(";
		           String singo2 = ")";
		           String usryemail = loginUsuario.getUsr().concat(" ").concat(singo1).concat(optionalUsuario.get().getEmail().concat(singo2));
		           auditDto.setUserref(usryemail);
		           auditDto.setModule(module);
		           auditDto.setDesc(Descmodule);
		           auditDto.setCreatedat(fechaDate);
		   		usersService.registrarAuditSesion(auditDto); 
		   		
			    String url = https+ sid + token2url + palabrahash + tokenurl + jwt + token2url + palabraemail + tokenurl + optionalUsuario.get().getEmail() + token2url + conditions +
			    		tokenurl + deMinLength.get().getParamname() + ":%20" + minlongitud + "|" + deSimbolos.get().getParamname() + ":%20" + cantSimbolos + "|" + 
			    		deCantMayus.get().getParamname() + ":%20" + cantMayusculas + "|" + deCantMinus.get().getParamname() + ":%20" + cantMinusculas +
			    		"|" + desimbolosPer.get().getParamname() + ":%20" + caracteresCodificados;
 
			   
			  // String url = ref.concat(tokenurl).concat(jwt).concat(tokenurl).concat("LongitudMinina=").concat(minlongitud).concat(tokenurl).concat("CantidadSimbolos=").concat(cantSimbolos).concat(tokenurl).concat("CantidadMayusculas=").concat(cantMayusculas).concat(tokenurl).concat("CantidadMinusculas=").concat(cantMinusculas).concat(tokenurl).concat("SimbolosPermitidos=").concat(simbolospermi);
			   RespuestaDto respuestaDto=new RespuestaDto(url, bloked);
			   respuestaDto.setBlocked(bloked);
	           respuestaDto.setMsg(url);
	           int id= optionalUsuario.get().getId();
	           int idestatus= optionalUsuario.get().getStatus();
	           int fail=optionalUsuario.get().getFails();
	           usersService.asociarSessionidUsers(id,jwt,optionalUsuario.get().getLastsession(),fail,idestatus);
	         
          return new ResponseEntity(respuestaDto, HttpStatus.OK);
        }

        		
	    
        
         int fail = 0;
		 String entryDesc = optionalUsuario.get().getRolid().getEntrypoint();
		 
		 
	     JwtDto jwtDto = new JwtDto(jwt , optionalUsuario.get().getName(),ValidThrufechaSalida,entryDesc,ValidThrufechaSalida.toString());

        SimpleDateFormat  formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat  formatter2 = new SimpleDateFormat("HH:mm:ss");
        String dataFormattata = formatter.format(fecha);
        String dataFormattata2 = formatter2.format(fecha);
        Date fechaDate = formatter.parse(dataFormattata);
        Date horaI = formatter2.parse(dataFormattata2);
        int sesionActiva2=0;
        int id= optionalUsuario.get().getId();
        int idestatus= optionalUsuario.get().getStatus();
        usersService.asociarSessionidUsersValid(id,jwt,fechaDate,fail,idestatus,ValidThrufechaSalida);
     
        String module = "Seguridad";
        String Descmodule = "Login exitoso" ;
        
        AuditRequestDto  auditDto=new AuditRequestDto();
        auditDto.setIpaddr(HttpReqRespUtils.getClientIpAddressIfServletRequestExist());
    
        
        String singo1 = "(";
        String singo2 = ")";
        String usryemail = loginUsuario.getUsr().concat(" ").concat(singo1).concat(optionalUsuario.get().getEmail().concat(singo2));
        auditDto.setUserref(usryemail);
        auditDto.setModule(module);
        auditDto.setDesc(Descmodule);
        auditDto.setCreatedat(fechaDate);
		usersService.registrarAuditSesion(auditDto); 
		/*HttpServletRequest request = null;
		String uri = request.getRequestURI(); 
		if (uri.contains("/login") || uri.contains("/oAuth2/callback")) {
		    // Permitir el paso
		   // filterChain.doFilter(request, response);
			String fff= "paso";
		   // return;
		}*/
  		return new ResponseEntity(jwtDto, HttpStatus.OK);	
        
     
		 } catch (Exception e) {
		        // logger.error(null, e);
			 int maxIntentosMaster;
			 int IntentosFallidos = 0;
			  IntentosFallidos = optionalUsuario.get().getFails() + 1;
			   Optional<Params> deMaxIntentos=paramsRepository.findByParamname("PWD_MAXFAILS");
			   maxIntentosMaster=Integer.parseInt(deMaxIntentos.get().getValue());
			   
		        
			// Date fecha = new Date();
			 SimpleDateFormat  formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			 String dataFormattata = formatter.format(fecha);
			 Date fechaDate = formatter.parse(dataFormattata);
			  String module = "Seguridad";
		        //String Descmodule = "Modulo de Autorizacion de Acceso al Sistema -Login Error Usuario : ".concat(loginUsuario.getUsr()) ;
			    String Descmodule = "Login fallido";
		        String jwt = "";
		        int id= optionalUsuario.get().getId();
		        int fail = 0;
		        boolean bloked;
		        int idestatus;
		        if (IntentosFallidos>=maxIntentosMaster) {
		              	 idestatus= 0;
		              	// fechaDate=null;
		              	 bloked = true;
					   
				   } else {
					     idestatus= optionalUsuario.get().getStatus();
					      bloked = false;
					   
				   }
		        
		        
		        usersService.asociarSessionidUsers(id,jwt,optionalUsuario.get().getLastsession(),IntentosFallidos,idestatus);
		        
		        AuditRequestDto  auditDto=new AuditRequestDto();
		        auditDto.setIpaddr(HttpReqRespUtils.getClientIpAddressIfServletRequestExist());
		    

		        auditDto.setUserref(loginUsuario.getUsr());
		        auditDto.setModule(module);
		        auditDto.setDesc(Descmodule);
		        auditDto.setCreatedat(fechaDate);
				usersService.registrarAuditSesion(auditDto); 
		         String var = e.getMessage();
		         
		         RespuestaDto respuestaDto=new RespuestaDto(var, bloked);
		         respuestaDto.setBlocked(bloked);
		         respuestaDto.setMsg("Usuario/Clave Inválidos");
		      
		         return new ResponseEntity(respuestaDto, HttpStatus.UNAUTHORIZED);
        }
				
		
	
	}
	


    @PostMapping("/forgot")
	//public ResponseEntity<RespuestaDto> forgotemail(@PathVariable("email") String email) throws ParseException, IOException {
    public ResponseEntity<RespuestaDto> forgotemail(@RequestBody final Users email) throws ParseException, UnsupportedEncodingException {
		/* Verificar si el id del canal existe */
    	
    	RespuestaParamsDto respuesta= new RespuestaParamsDto("");
    	RespuestaMsgDto respuestahelp= new RespuestaMsgDto("");
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		if (!usersService.existsByEmail(email.getEmail())) {
			
		
			 if (vemailhelpdesk.equals(email.getEmail())) {
				 
				 respuestahelp= new RespuestaMsgDto("En linea");
					estatus=HttpStatus.OK;
					return new ResponseEntity(respuestahelp,estatus);
	         	} else {
			     logger.warn("No existe el id de la campaña solicitado: "+email);
			     return new ResponseEntity(new Mensaje("No existe ningún usuario registrado con ese email: " + email.getEmail()), HttpStatus.UNAUTHORIZED);
	          	} 
		}
		
		       
	
		
		//List<RespuestaDto> datosCampana= campanaService.datosCampana(idCampana);	
		Optional<Users> encontreSessionUsuario = usersRepository.findByEmail(email.getEmail());
		  Optional<Params> deMinLength=paramsRepository.findByParamname("PWD_MINLENGTH");
		   String minlongitud=deMinLength.get().getValue();
		   Optional<Params> deSimbolos=paramsRepository.findByParamname("PWD_SYMBOLS");
		   String cantSimbolos=deSimbolos.get().getValue();
		   Optional<Params> deCantMayus=paramsRepository.findByParamname("PWD_UPPERCASE");
		   String cantMayusculas=deCantMayus.get().getValue();
		   Optional<Params> deCantMinus=paramsRepository.findByParamname("PWD_LOWERCASE");
		   String cantMinusculas=deCantMinus.get().getValue();
		   Optional<Params> desimbolosPer=paramsRepository.findByParamname("PWD_ALLOWEDSYM");
		   String simbolospermi=desimbolosPer.get().getValue();
		  // String ref = "www.duranyasociados.com";
		
		   String tokenurl = "=";
		   String token2url = "&";
		   String token3url = "|";
		   
			String jwt = UUID.randomUUID().toString();
	     
			String sid = "changepwd";
			String palabrahash = "hash";
			String palabraemail = "email";
			String conditions = "conditions";
			String hash = jwt;
			String idcampo = "?sid=";
			String ConcatAmbiente = urlAmbiente.concat(idcampo);
			String https = ConcatAmbiente;
			String encoding = StandardCharsets.UTF_8.toString();
			String caracteresCodificados = URLEncoder.encode(simbolospermi, encoding);

			//String https="http://vpskromasys2.hostnetcom.com/~daconsult/dev/?sid=";
			
			
		 //   String url = https.concat(sid).concat(token2url).concat(palabrahash).concat(tokenurl).concat(jwt).concat(token2url).concat(palabraemail).concat(tokenurl).concat(email.getEmail()).concat(token2url).concat(conditions).concat(tokenurl).concat("Longitud%20Mínima:%20").concat(minlongitud).concat("|").concat("Cantidad%20Símbolos:%20").concat(cantSimbolos).concat("|").concat("Cantidad%20Mayúsculas:%20").concat(cantMayusculas).concat("|").concat("Cantidad%20Mínúsculas:%20").concat(cantMinusculas).concat("|").concat("Símbolos%20Permitidos:%20").concat(simbolospermi);
		    String url = https + sid + "&" + "hash" + "=" + jwt + "&" + "email" + "=" + email.getEmail() + "&" + "conditions" + "="
              + deMinLength.get().getParamname() + ":%20" + minlongitud +"|" + deSimbolos.get().getParamname() + ":%20" + cantSimbolos + "|" + deCantMayus.get().getParamname() + ":%20" + cantMayusculas + "|" +
                 deCantMinus.get().getParamname() + ":%20" + cantMinusculas + "|" + desimbolosPer.get().getParamname() + ":%20" + caracteresCodificados;

			
		    Date fecha = new Date();
		    SimpleDateFormat  formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	        SimpleDateFormat  formatter2 = new SimpleDateFormat("HH:mm:ss");
	        String dataFormattata = formatter.format(fecha);
	        String dataFormattata2 = formatter2.format(fecha);
	        Date fechaDate = formatter.parse(dataFormattata);
	        Date horaI = formatter2.parse(dataFormattata2);
		    //String ruta = "https://i.postimg.cc/Gt1rWjyY/imgemail.jpg";
	     
	        String idcampoLogo = "img/logo.png";
			String ConcatAmbienteLogo = urlAmbiente + (idcampoLogo);
			String ruta = ConcatAmbienteLogo;
			
	        //String ruta= "http://vpskromasys2.hostnetcom.com/~daconsult/dev/img/logo.png";
	       // 
	        ///String rutatotal = directorioImages.toFile().getAbsolutePath();
	         String saludo = " Para recuperar su clave por favor diríjase a la dirección indicada a continuación:";
	         String accion = "Recuperar";
	        // String htmlContent = "<html><body><img src='data:image/png;base64," + base64Image + "'></body></html>";
		    //////////////////////////
	         //String contenidocompleto = String.format(""+
	         String contenido  = usersService.ArmarBodySendMailUser(ruta,encontreSessionUsuario.get().getName(),saludo,url,accion,minlongitud,cantMayusculas,cantMinusculas,cantSimbolos,simbolospermi);
	     try {                                               	
		    int fail = 0;
		    String module = "Seguridad";
		    String Descmodule = "Envio de correo exitoso" ;
		     estatus = HttpStatus.FORBIDDEN;
		   
	      //  auditDto.setIdUsuario(optionalUsuario.get().getId());
	       // auditDto.setActivo(1);
	        String singo1 = "(";
	        String singo2 = ")";
	        String usryemail = encontreSessionUsuario.get().getUsr().concat(" ").concat(singo1).concat(encontreSessionUsuario.get().getEmail().concat(singo2));
	       
			
			usersService.sendEmail(email.getEmail(), contenido , "Recuperación de Contraseña");
			usersService.asociarSessionidUsers(encontreSessionUsuario.get().getId(),jwt,encontreSessionUsuario.get().getLastsession(),fail,encontreSessionUsuario.get().getStatus());
			 AuditRequestDto  auditDto=new AuditRequestDto();
		        auditDto.setIpaddr(HttpReqRespUtils.getClientIpAddressIfServletRequestExist());
			 auditDto.setUserref(usryemail);
		        auditDto.setModule(module);
		        auditDto.setDesc(Descmodule);
		        auditDto.setCreatedat(fechaDate);
			usersService.registrarAuditSesion(auditDto); 
			respuesta= new RespuestaParamsDto(contenido);
			estatus=HttpStatus.OK;
			
        } catch (Exception e) {
        	
        	System.out.println(e);
        
        }
			   
        return new ResponseEntity(respuesta,estatus);
		
		//return new ResponseEntity<>(datosCampana, HttpStatus.OK);
	}
	
	@PostMapping("/logout")
	public ResponseEntity<?> cerrarSesion(HttpServletRequest request,@RequestBody final SessionDto sessionid
			,HttpServletResponse response) throws ParseException {
		RespuestaDto respuesta = new RespuestaDto("", false);
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		logoutOktaNormalDto detlogoutOktaNormalDto = new logoutOktaNormalDto();
		HttpSession session = request.getSession();
		HttpSession sessionLogin = request.getSession();
		//session.setAttribute("state", state);

		String sessionid2 = (String) sessionLogin.getAttribute("sessionidGl");
		
		String var="";
		try {
						
			//HttpSession session = request.getSession();
			Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(sessionid.getSessionid());
			
			//if (isOkta==1) {
			if (encontreSessionUsuario.get().getRef()!=null) {
				System.out.print("Entro por logout de Okta");
				session.invalidate(); 
				 encontreSessionUsuario = usersRepository.getBySessionid(sessionid.getSessionid());
				//usersRepository.asociarSessionid(encontreSessionUsuario.get().getId(), "",null);
				String url = urlOktaExist;
				detlogoutOktaNormalDto.setId(encontreSessionUsuario.get().getId());
				detlogoutOktaNormalDto.setLoginpage(urlOktaExist);
				usersRepository.asociarSessionid(encontreSessionUsuario.get().getId(), "",null);
				SecurityContextHolder.clearContext();
			
                
                return new ResponseEntity<>(detlogoutOktaNormalDto, HttpStatus.OK);
				
			}else {
		

			if (encontreSessionUsuario.isPresent()) {
				//Eliminar la sesión del usuario
				usersRepository.asociarSessionid(encontreSessionUsuario.get().getId(), "",null);
				SecurityContextHolder.clearContext();
				respuesta= new RespuestaDto("Sesión cerrada correctamente", false);
				estatus=HttpStatus.OK;
				
				detlogoutOktaNormalDto.setId(encontreSessionUsuario.get().getId());
				detlogoutOktaNormalDto.setLoginpage(urlAmbiente);
				return new ResponseEntity<>(detlogoutOktaNormalDto, HttpStatus.OK);
				
			}else {
				respuesta= new RespuestaDto("Sesión inválida", false);
				estatus=HttpStatus.UNAUTHORIZED;
			}
			}
						
		  
		}catch (Exception e) {
            // Manejo de excepciones
			respuesta= new RespuestaDto("Error interno del servidor", false);
			estatus=HttpStatus.INTERNAL_SERVER_ERROR;            
        }
		
		return new ResponseEntity(respuesta, estatus);
	}
	
    
	/*@PostMapping("/logout")
	public ResponseEntity<?> cerrarSesion(HttpServletRequest request,@RequestBody final SessionDto sessionid) throws ParseException {
		RespuestaDto respuesta = new RespuestaDto("", false);
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		
		
		try {
						
			HttpSession session = request.getSession();
			if (session.getAttribute("iduser")!=null) {
				session.invalidate(); 
                HttpHeaders headers = new HttpHeaders();
                headers.add("Location", "/oAuth2/login");
                return new ResponseEntity<>(headers, HttpStatus.FOUND); // Código 302 Found
				
			}else {
		Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(sessionid.getSessionid());

			if (encontreSessionUsuario.isPresent()) {
				//Eliminar la sesión del usuario
				usersRepository.asociarSessionid(encontreSessionUsuario.get().getId(), "",null);
				SecurityContextHolder.clearContext();
				respuesta= new RespuestaDto("Sesión cerrada correctamente", false);
				estatus=HttpStatus.OK;
			}else {
				respuesta= new RespuestaDto("Sesión inválida", false);
				estatus=HttpStatus.UNAUTHORIZED;
			}
			}
						
		  
		}catch (Exception e) {
            // Manejo de excepciones
			respuesta= new RespuestaDto("Error interno del servidor", false);
			estatus=HttpStatus.INTERNAL_SERVER_ERROR;            
        }
		
		return new ResponseEntity(respuesta, estatus);
	} */
	
	@PostMapping("/pwdchange")
	public ResponseEntity<RespuestaParamsDto> passwordChange(HttpServletRequest request,@RequestBody final PwdoldnewDto passoldnew) throws ParseException {
		//RespuestaDto respuesta = new RespuestaDto("", false);
		RespuestaParamsDto respuesta= new RespuestaParamsDto("");
		
		Set<Params> complexity = new HashSet<>();
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		String oldpasswd=""; //Almacena toda las contraseñas
		boolean existe=false; //permite conocer si existe la contraseña
		
		// String sessionid = request.getHeader("Authorization");
		// String sessionid = hashpwd.getHash();
		
		 String sessionid = request.getHeader("Authorization");
		 sessionid = sessionid.substring(7);
			if (sessionid==null) {
				respuesta= new RespuestaParamsDto("Session id es Null");
				estatus=HttpStatus.UNAUTHORIZED;
				return new ResponseEntity(respuesta, estatus);
				
			}
			
			Optional<Users> encontreSessionUsuariovalid = usersRepository.getBySessionid(sessionid);

			if (encontreSessionUsuariovalid.isPresent()) {
				//Eliminar la sesión del usuario
			   String r = "Session correcta";
			}else {
				respuesta= new RespuestaParamsDto("Sesión inválida");
				estatus=HttpStatus.UNAUTHORIZED;
				return new ResponseEntity(respuesta, estatus);
				
		   	}
	    
		
				
		try {
			
			//String passwodConvertidoOld=passworEncoder.encode(passoldnew.getOldpwd());
			
			Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(sessionid);
			try {
				  Authentication authentication=
					     	autheticationManager.authenticate(new UsernamePasswordAuthenticationToken(encontreSessionUsuario.get().getUsr(),passoldnew.getOldpwd()));
			
			/*   RespuestaDto respuestaDto=new RespuestaDto(var, bloked);
		         respuestaDto.setBlocked(bloked);
		         respuestaDto.setMsg("Usuario/Clave Inválidos");
		      
		         return new ResponseEntity(respuestaDto, HttpStatus.UNAUTHORIZED);
			*/
		
			}  catch (Exception e) {
				respuesta= new RespuestaParamsDto("Usuario/Clave Inválidos");
				existe=true;
				estatus=HttpStatus.UNAUTHORIZED;
			
		         return new ResponseEntity(respuesta,estatus);   
	        }
				
				
						
			//extraer todos los parametros de validación de la contraseña
			//extraer todos los parametros de validación de la contraseña
		  	  Optional<Params> Minupper=paramsRepository.findByParamname("PWD_UPPERCASE");
		 		  String minupper=Minupper.get().getValue();
		 		  int longitudMayuscula = Integer.parseInt(Minupper.get().getValue());
		 		  Optional<Params> Minsymbols=paramsRepository.findByParamname("PWD_SYMBOLS");
		 		  String minsymbols=Minsymbols.get().getValue();
		 		 int longitudSimbolos = Integer.parseInt(Minsymbols.get().getValue());
		 		  Optional<Params> Minlower=paramsRepository.findByParamname("PWD_LOWERCASE");
		 		  String minlower=Minlower.get().getValue();
		 		 int longitudMinuscula = Integer.parseInt(Minlower.get().getValue());
		 		  Optional<Params> Minlengthn=paramsRepository.findByParamname("PWD_MINLENGTH");
		 		  String minlengthn=Minlengthn.get().getValue();
		 		  int longitudMinima = Integer.parseInt(Minlengthn.get().getValue());
		 		  Optional<Params> Allowedsimbols=paramsRepository.findByParamname("PWD_ALLOWEDSYM");
		 		  String allowedsimbols=Allowedsimbols.get().getValue();
			
			/*Params params = minima.get();
			complexity.add(params);
			
			params = mayuscula.get();
			complexity.add(params);
			
			params = minuscula.get();
			complexity.add(params);
			
			params = simbolos.get();
			complexity.add(params);*/
		 		  
		 			PwdcomplexityDto pwdcomplexityDto = new PwdcomplexityDto();
					RespuestaParamsDto respuesta2 = null;
				 		pwdcomplexityDto.setMinlength(minlengthn);
				 		
				 		pwdcomplexityDto.setMinupper(minupper);
				 		pwdcomplexityDto.setMinlower(minlower);
				 		pwdcomplexityDto.setMinsymbols(minsymbols);
				 		pwdcomplexityDto.setAllowedsimbols(allowedsimbols);
			
			
			//Verificar que la contraseña cumpla con los requerimientos/
			//Si es menor a la longitud minima
			String pwd= passoldnew.getNewpwd();
			//Contar mayusculas/
			int contadorMayusculas = 0;
	        for (char caracter : pwd.toCharArray()) {
	            if (Character.isUpperCase(caracter)) {
	            	contadorMayusculas++;
	            }
	        }
	        
	       //Contar mayusculas/
			int contadorMinusculas = 0;
	        for (char caracter : pwd.toCharArray()) {
	            if (Character.isLowerCase(caracter)) {
	            	contadorMinusculas++;
	            }
	        }
	        
	        //Contar simbolos/
	        int contadorSimbolos = 0;
	        ArrayList<Character> misCaracteres = new ArrayList<>();
	        for (char caracter : pwd.toCharArray()) {
	            if (!Character.isLetterOrDigit(caracter)) {
	            	misCaracteres.add(caracter);
	                contadorSimbolos++;
	            }
	        }
	        
	        boolean encontreSimboloErroneo= false;
	        for (char simbolo : misCaracteres) {
	        	if (!Character.isLetterOrDigit(simbolo)) {
	        		if (allowedsimbols.indexOf(simbolo)==-1) {
	        			encontreSimboloErroneo=true;
	        			break;
	        		}
	            }
	        }
        
	        //Validar contraseña
			if (passoldnew.getNewpwd().length()<longitudMinima 
				|| encontreSimboloErroneo 
				|| contadorSimbolos<longitudSimbolos 
				|| contadorMinusculas<longitudMinuscula
				|| contadorMayusculas<longitudMayuscula) {
				respuesta= new RespuestaParamsDto("Complejidad de la clave incorrecta");	
				//respuesta.setComplexity(complexity);
				respuesta.setComplexity(pwdcomplexityDto);
				estatus=HttpStatus.BAD_REQUEST;
			}else {
			
			//Obtengo la contraseña reconvertida
			String passwodConvertido=passworEncoder.encode(passoldnew.getNewpwd());
			
		
			

			String[] contrasenas = new String[5];
			boolean isMatch=false;
			int contadorLleno=0;
				if (encontreSessionUsuario.isPresent()) { // verifico si obtengo el session id
					if (encontreSessionUsuario.get().getOldpwds()==null){ //verifico si el campo que almacena las contraseñas tiene toda la información.
						oldpasswd=passwodConvertido; //coloco el nuevo password
					}else{
						//Obtengo un array completo de Contraseñas
						if (encontreSessionUsuario.get().getOldpwds().indexOf("||")!=-1) {
							contrasenas =encontreSessionUsuario.get().getOldpwds().split("\\|\\|");
						}else {
							contrasenas[0]=encontreSessionUsuario.get().getOldpwds();
						}
							
						//Verifico si la contraseña es igual a las últimas introducidas por el usuario
						for (String contra: contrasenas) {
							isMatch = passworEncoder.matches(pwd, contra);
							if (contra!=null && isMatch) {
								respuesta= new RespuestaParamsDto("La contraseña no puede ser igual a las registradas anteriormente");
								existe=true;
								estatus=HttpStatus.BAD_REQUEST;
								break;
							}
						}
							
						if (!existe) {	
							//verifica si esta lleno el arreglo
							for (String cont : contrasenas) {
					            if (cont != null && !cont.isEmpty()) {
					                contadorLleno++;
					            }
					        }
							
							//si el campo oldpasswd no esta vacio, verifico la cantidad de contraseñas que obtengo
							if (contadorLleno==5) {//si es igual a 5 entonces coloco el nuevo password
								oldpasswd=passwodConvertido;
							}else {
								oldpasswd=encontreSessionUsuario.get().getOldpwds()+"||"+passwodConvertido;
							}
						}
						
					}
					if (!existe) {
						AuditRequestDto auditDto = new AuditRequestDto();
						Date fecha = new Date();
						usersRepository.cambiarContrasenaSinSession(encontreSessionUsuario.get().getId(), passwodConvertido,oldpasswd,fecha);
						SecurityContextHolder.clearContext();
						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);
						//Guardar en la tabla de auditoria
						Audit audit = new Audit(fecha,"Seguridad","Cambio de contraseña exitoso",auditDto.getIpaddr(),usryemail);
						auditRepository.save(audit);
						respuesta= new RespuestaParamsDto("Contraseña cambiada satisfactoriamente");
						estatus=HttpStatus.OK;
					}
					
				}else {
					AuditRequestDto auditDto = new AuditRequestDto();
					Date fecha = new Date();
					//usersRepository.cambiarContrasenaSinSession(encontreSessionUsuario.get().getId(), passwodConvertido,oldpasswd,fecha);
					SecurityContextHolder.clearContext();
					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);
					//Guardar en la tabla de auditoria
					Audit audit = new Audit(fecha,"Seguridad","Cambio de contraseña fallido",auditDto.getIpaddr(),usryemail);
					auditRepository.save(audit);
					respuesta= new RespuestaParamsDto("Hash incorrecto");
					estatus=HttpStatus.UNAUTHORIZED;
				}
			}
		}catch (Exception e) {
			Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(sessionid);
			AuditRequestDto auditDto = new AuditRequestDto();
			Date fecha = new Date();
			//usersRepository.cambiarContrasenaSinSession(encontreSessionUsuario.get().getId(), passwodConvertido,oldpasswd,fecha);
			SecurityContextHolder.clearContext();
			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);
			//Guardar en la tabla de auditoria
			Audit audit = new Audit(fecha,"Seguridad","Cambio de contraseña fallido",auditDto.getIpaddr(),usryemail);
			auditRepository.save(audit);
            // Manejo de excepciones
			respuesta= new RespuestaParamsDto("Error interno del servidor");
			estatus=HttpStatus.INTERNAL_SERVER_ERROR;            
        }
		
		return new ResponseEntity(respuesta, estatus);
	}
	
	
	@PostMapping("/recover")
	public ResponseEntity<RespuestaParamsDto> cambiarContrasena(@RequestBody final HashPwdDto hashpwd) throws ParseException {
		//RespuestaDto respuesta = new RespuestaDto("", false);
		RespuestaParamsDto respuesta= new RespuestaParamsDto("");
		Set<Params> complexity = new HashSet<>();
		//Set<Params> complexity = new HashSet<>();
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		String oldpasswd=""; //Almacena toda las contraseñas
		boolean existe=false; //permite conocer si existe la contraseña
		
		// String sessionid = request.getHeader("Authorization");
		 String sessionid = hashpwd.getHash();
			if (sessionid==null) {
				respuesta= new RespuestaParamsDto("Session id es Null");
				estatus=HttpStatus.UNAUTHORIZED;
				return new ResponseEntity(respuesta, estatus);
				
			}
			
			Optional<Users> encontreSessionUsuariovalid = usersRepository.getBySessionid(sessionid);

			if (encontreSessionUsuariovalid.isPresent()) {
				//Eliminar la sesión del usuario
			   String r = "Session correcta";
			}else {
				respuesta= new RespuestaParamsDto("Sesión inválida");
				estatus=HttpStatus.UNAUTHORIZED;
				return new ResponseEntity(respuesta, estatus);
		   	}
	    
		
				
		try {
			
		
						
			//extraer todos los parametros de validación de la contraseña
		  	  Optional<Params> Minupper=paramsRepository.findByParamname("PWD_UPPERCASE");
		 		  String minupper=Minupper.get().getValue();
		 		  int longitudMayuscula = Integer.parseInt(Minupper.get().getValue());
		 		  Optional<Params> Minsymbols=paramsRepository.findByParamname("PWD_SYMBOLS");
		 		  String minsymbols=Minsymbols.get().getValue();
		 		 int longitudSimbolos = Integer.parseInt(Minsymbols.get().getValue());
		 		  Optional<Params> Minlower=paramsRepository.findByParamname("PWD_LOWERCASE");
		 		  String minlower=Minlower.get().getValue();
		 		 int longitudMinuscula = Integer.parseInt(Minlower.get().getValue());
		 		  Optional<Params> Minlengthn=paramsRepository.findByParamname("PWD_MINLENGTH");
		 		  String minlengthn=Minlengthn.get().getValue();
		 		  int longitudMinima = Integer.parseInt(Minlengthn.get().getValue());
		 		  Optional<Params> Allowedsimbols=paramsRepository.findByParamname("PWD_ALLOWEDSYM");
		 		  String allowedsimbols=Allowedsimbols.get().getValue();
		 	//	 String simbolosPermitidos = simbolos_permitidos.get().getValue();
			
	
			
			PwdcomplexityDto pwdcomplexityDto = new PwdcomplexityDto();
			RespuestaParamsDto respuesta2 = null;
		 		pwdcomplexityDto.setMinlength(minlengthn);
		 		
		 		pwdcomplexityDto.setMinupper(minupper);
		 		pwdcomplexityDto.setMinlower(minlower);
		 		pwdcomplexityDto.setMinsymbols(minsymbols);
		 		pwdcomplexityDto.setAllowedsimbols(allowedsimbols);
		 		
			
			
			//Verificar que la contraseña cumpla con los requerimientos/
			//Si es menor a la longitud minima
			String pwd= hashpwd.getPwd();
			//Contar mayusculas/
			int contadorMayusculas = 0;
	        for (char caracter : pwd.toCharArray()) {
	            if (Character.isUpperCase(caracter)) {
	            	contadorMayusculas++;
	            }
	        }
	        
	       //Contar mayusculas/
			int contadorMinusculas = 0;
	        for (char caracter : pwd.toCharArray()) {
	            if (Character.isLowerCase(caracter)) {
	            	contadorMinusculas++;
	            }
	        }
	        
	        //Contar simbolos/
	        int contadorSimbolos = 0;
	        ArrayList<Character> misCaracteres = new ArrayList<>();
	        for (char caracter : pwd.toCharArray()) {
	            if (!Character.isLetterOrDigit(caracter)) {
	            	misCaracteres.add(caracter);
	                contadorSimbolos++;
	            }
	        }
	        
	        boolean encontreSimboloErroneo= false;
	        for (char simbolo : misCaracteres) {
	        	if (!Character.isLetterOrDigit(simbolo)) {
	        		
	        		//if (simbolosPermitidos.indexOf(simbolo)==-1) {
	        		if (allowedsimbols.indexOf(simbolo)==-1) {
	        			encontreSimboloErroneo=true;
	        			break;
	        		}
	            }
	        }
        
	        //Validar contraseña
			if (hashpwd.getPwd().length()<longitudMinima 
				|| encontreSimboloErroneo 
				|| contadorSimbolos<longitudSimbolos 
				|| contadorMinusculas<longitudMinuscula
				|| contadorMayusculas<longitudMayuscula) {
				respuesta= new RespuestaParamsDto("Complejidad de la clave incorrecta");	
				//respuesta.setComplexity(complexity);
				respuesta.setComplexity(pwdcomplexityDto);
				estatus=HttpStatus.BAD_REQUEST;
			}else {
			
			//Obtengo la contraseña reconvertida
			String passwodConvertido=passworEncoder.encode(hashpwd.getPwd());
			
			Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(hashpwd.getHash());
			String[] contrasenas = new String[5];
			boolean isMatch=false;
			int contadorLleno=0;
				if (encontreSessionUsuario.isPresent()) { // verifico si obtengo el session id
					if (encontreSessionUsuario.get().getOldpwds()==null){ //verifico si el campo que almacena las contraseñas tiene toda la información.
						oldpasswd=passwodConvertido; //coloco el nuevo password
					}else{
						//Obtengo un array completo de Contraseñas
						if (encontreSessionUsuario.get().getOldpwds().indexOf("||")!=-1) {
							contrasenas =encontreSessionUsuario.get().getOldpwds().split("\\|\\|");
						}else {
							contrasenas[0]=encontreSessionUsuario.get().getOldpwds();
						}
							
						//Verifico si la contraseña es igual a las últimas introducidas por el usuario
						for (String contra: contrasenas) {
							isMatch = passworEncoder.matches(pwd, contra);
							if (contra!=null && isMatch) {
								respuesta= new RespuestaParamsDto("La contraseña no puede ser igual a las registradas anteriormente");
								existe=true;
								estatus=HttpStatus.BAD_REQUEST;
								break;
							}
						}
							
						if (!existe) {	
							//verifica si esta lleno el arreglo
							for (String cont : contrasenas) {
					            if (cont != null && !cont.isEmpty()) {
					                contadorLleno++;
					            }
					        }
							
							//si el campo oldpasswd no esta vacio, verifico la cantidad de contraseñas que obtengo
							if (contadorLleno==5) {//si es igual a 5 entonces coloco el nuevo password
								oldpasswd=passwodConvertido;
							}else {
								oldpasswd=encontreSessionUsuario.get().getOldpwds()+"||"+passwodConvertido;
							}
						}
						
					}
					if (!existe) {
						AuditRequestDto auditDto = new AuditRequestDto();
						Date fecha = new Date();
						usersRepository.cambiarContrasena(encontreSessionUsuario.get().getId(), passwodConvertido,oldpasswd,fecha);
						SecurityContextHolder.clearContext();
						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);
						//Guardar en la tabla de auditoria
						Audit audit = new Audit(fecha,"Seguridad","Cambio de contraseña exitoso",auditDto.getIpaddr(),usryemail);
						auditRepository.save(audit);
						respuesta= new RespuestaParamsDto("Contraseña cambiada satisfactoriamente");
						estatus=HttpStatus.OK;
					}
					
				}else {
					
					AuditRequestDto auditDto = new AuditRequestDto();
					Date fecha = new Date();
					//usersRepository.cambiarContrasena(encontreSessionUsuario.get().getId(), passwodConvertido,oldpasswd,fecha);
					SecurityContextHolder.clearContext();
					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);
					//Guardar en la tabla de auditoria
					Audit audit = new Audit(fecha,"Seguridad","Cambio de contraseña fallido",auditDto.getIpaddr(),usryemail);
					auditRepository.save(audit);
					respuesta= new RespuestaParamsDto("Hash incorrecto");
					estatus=HttpStatus.UNAUTHORIZED;
				}
			}
		}catch (Exception e) {
			Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(hashpwd.getHash());
			AuditRequestDto auditDto = new AuditRequestDto();
			Date fecha = new Date();
			//usersRepository.cambiarContrasena(encontreSessionUsuario.get().getId(), passwodConvertido,oldpasswd,fecha);
			SecurityContextHolder.clearContext();
			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);
			//Guardar en la tabla de auditoria
			Audit audit = new Audit(fecha,"Seguridad","Cambio de contraseña fallido",auditDto.getIpaddr(),usryemail);
			auditRepository.save(audit);
            // Manejo de excepciones
			respuesta= new RespuestaParamsDto("Error interno del servidor");
			estatus=HttpStatus.INTERNAL_SERVER_ERROR;            
        }
		
		return new ResponseEntity(respuesta, estatus);
	}
	
	
	@PostMapping("/audit/users")
	public ResponseEntity<AuditResponseDto> usersaudit(HttpServletRequest request,@RequestBody UsersListDto tiposfiltros) throws ParseException {
		RespuestaDto respuesta = new RespuestaDto("", false);
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		AuditResponseDto auditoriaDto = new AuditResponseDto();
		 AuditDto detalleAudit;
	     List<AuditDto> listasAudit = new ArrayList<>();
	     
		 String sessionid = request.getHeader("Authorization");
		  Date fecha = new Date();
		    SimpleDateFormat  formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		    Long cuantosregistro = (long) 0;
	        String dataFormattata = formatter.format(fecha);
	        Date fechaDate = formatter.parse(dataFormattata);
	        AuditRequestDto  auditDto=new AuditRequestDto();
	   	 String searchIn = "";
	   	 String contentIn = "";
		 int orderIn = 0;
		 int offsetIn = 0;
		 int numofrecordsIn = 0;
		 String fechaComoCadena;
		 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);
	
		 
			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(); 
					   //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=="") {
						   
						   
						   
						   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 servicio obtiene una lista de los usuarios registrados en la auditoría en el campo "userref". (priv 600)

					   Roles roles = encontreSessionUsuario.get().getRolid();
					   int idrol = roles.getId();
					   int rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol, 600);
					   
					   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();
						  searchIn = tiposfiltros.getFilters().getSearch();
						  
						    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);
							  }
							  
						  searchIn = usersService.eliminarAcentosService(tiposfiltros.getFilters().getSearch());   
						  orderIn = tiposfiltros.getOrder();
						  offsetIn = tiposfiltros.getOffset();
						  numofrecordsIn = tiposfiltros.getNumofrecords();
						  
						  contentIn = tiposfiltros.getContent();
						  if (contentIn !=null) {
						  menuService.iscontentdiffnull(contentIn, encontreSessionUsuario.get().getId());
						  }
					   					
					
				 } else {
						String var = "";
						boolean bloked = false;
						RespuestaDto respuestaDto = new RespuestaDto(var, bloked);
						respuestaDto.setBlocked(bloked);
						respuestaDto.setMsg("Sesión expirada o inválida");
						//Error 400
						return new ResponseEntity(respuestaDto, HttpStatus.UNAUTHORIZED);
				 }
			}
		 
		
		try {
			
			
			
			//Se setean algunas palabras claves del Manejador de BD
			/*comienzo del comentario*/  
		
			String SentenciaBase = "SELECT DISTINCT new com.dacrt.SBIABackend.security.dto.AuditDto  (u.userref) FROM Audit u";		

			String QueryTotal = "";
			String useref = "u.userref";
			String group = "u.userref,u.id";
			String LowerSearch = searchIn.toLowerCase();
			String loweruseref = " main.sinacentos(LOWER(u.userref))";
			//String lowerdsc = "main.sinacentos(LOWER(ed.dsc))";
		
			 switch (searchIn) { 
			    case "":  // viene sin busqueda por el like
			    	QueryTotal = SentenciaBase + " GROUP BY " + group;
			     break;
			  
			    default:	// viene con el parametro para buscar por el like		   			    				    	
			    	QueryTotal = SentenciaBase  + " WHERE " + loweruseref +" LIKE " + "'%" + LowerSearch + "%'";
			    	
	         }
			 
			 TypedQuery<AuditDto> paramsCount= entityManager.createQuery(QueryTotal, AuditDto.class);
			 cuantosregistro = (long) paramsCount.getResultList().size();
		
			 
			 switch (orderIn) { 
			    case 1:  //ordena por group y name ascendente
			    	
			    	QueryTotal = QueryTotal + " ORDER BY " + useref + " ASC";
			     break;
			    case -1://ordena por group y name descendente
			    	
			    	QueryTotal = QueryTotal + " ORDER BY " + useref + " DESC";
			     break;
			    default:
			    	String var2 = "";
					boolean bloked = false;
					RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var2);
					respuestaDto= new RespuestaMsgDto("Error interno del servidor");
					estatus=HttpStatus.INTERNAL_SERVER_ERROR;   
					return new ResponseEntity(respuestaDto, estatus);
			     // Default secuencia de sentencias.
			   }
			 
			 //Se mapea la entidad se le pasa el query y lo bota como un tipo de objeto AuditDto-Buscar en los DTO 
			     TypedQuery<AuditDto> params= entityManager.createQuery(QueryTotal, AuditDto.class);
			      params.setFirstResult(offsetIn);
			      params.setMaxResults(numofrecordsIn);
			      List<AuditDto> listacompleta = params.getResultList();
			
		    	
		    	  	//Se le pasa el listado al DTO RESPONSE que contiene la estructura de Salida solicitada
		    	  	auditoriaDto.setNumofrecords(cuantosregistro);
		    	  	auditoriaDto.setSessionvalidthru(fechaComoCadena);		           
		    	  	auditoriaDto.setRecords(listacompleta);
																				
				    return ResponseEntity.ok(auditoriaDto);																					
       
		} catch (Exception e) {
            // Manejo de excepciones
			respuesta= new RespuestaDto("Error interno del servidor", false);
			estatus=HttpStatus.INTERNAL_SERVER_ERROR;            
        }finally {
	        if (entityManager != null && entityManager.isOpen()) {
	            entityManager.close();
	        }
        }
		
		return new ResponseEntity(respuesta, estatus);
	
	}
	
	
	@PostMapping("/audit/modules")
	public ResponseEntity<AuditModResponseDto> modulesaudit(HttpServletRequest request,@RequestBody UsersListDto tiposfiltros) throws ParseException {
		RespuestaDto respuesta = new RespuestaDto("", false);
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		AuditModResponseDto auditoriaModDto = new AuditModResponseDto();
		AuditDtoMod detalleAudit;
	     List<AuditDtoMod> listasAudit = new ArrayList<>();
		 
		 String sessionid = request.getHeader("Authorization");
		  Date fecha = new Date();
		  Long cuantosregistro = (long) 0;
		  
		    SimpleDateFormat  formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	        String dataFormattata = formatter.format(fecha);
	        Date fechaDate = formatter.parse(dataFormattata);
	        AuditRequestDto  auditDto=new AuditRequestDto()
	        		;
	   	 String searchIn = "";
	   	 String contentIn = "";
		 int orderIn = 0;
		 int offsetIn = 0;
		 int numofrecordsIn = 0;
		 
		 //Se calcula el validtrhu de la session trayendo de la BD el parametro session duration
		 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;
         String fechaComoCadena;
     
	
		 //Valida la nulidad de la session
			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('('); 
				   // Validacion de la existencia del usuario que hizo la peticion del servicio Jackson Rivero
				   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);
						   
					    }
                     // Este servicio obtiene una lista de los módulos registrados en la auditoría. (priv 600)

					   Roles roles = encontreSessionUsuario.get().getRolid();
					   int idrol = roles.getId();
					   int rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol, 600);
					   
					   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();
						  
						  
						  searchIn = tiposfiltros.getFilters().getSearch();
						  
						    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);
							  }
							  
					      searchIn = usersService.eliminarAcentosService(tiposfiltros.getFilters().getSearch());  
						  orderIn = tiposfiltros.getOrder();
						  offsetIn = tiposfiltros.getOffset();
						  numofrecordsIn = tiposfiltros.getNumofrecords();
						  
						  contentIn = tiposfiltros.getContent();
						  if (contentIn !=null) {
						  menuService.iscontentdiffnull(contentIn, encontreSessionUsuario.get().getId());
						  }						 						
										
				 } else {
						String var = "";
						boolean bloked = false;
						RespuestaDto respuestaDto = new RespuestaDto(var, bloked);
						respuestaDto.setBlocked(bloked);
						respuestaDto.setMsg("Sesión expirada o inválida");
						//Error 400
						return new ResponseEntity(respuestaDto, HttpStatus.UNAUTHORIZED);
				 }
			}
		 
		
		try {
			
		

			String SentenciaBase = "SELECT DISTINCT new com.dacrt.SBIABackend.security.dto.AuditDtoMod (u.module) FROM Audit u";		

			String QueryTotal = "";
			String module = "u.module";
			String group = "u.module,u.id";
			String lowermodule= " main.sinacentos(LOWER(u.module))";
			String LowerSearch = searchIn.toLowerCase();
		
			 switch (searchIn) { 
			    case "":  // viene sin busqueda por el like
			    	QueryTotal = SentenciaBase + " GROUP BY " + group;
			     break;
			  
			    default:	// viene con el parametro para buscar por el like		   			    				    	
			    	QueryTotal = SentenciaBase  + " WHERE " + lowermodule + " LIKE " + "'%" + LowerSearch + "%'";
			    	
	         }
			 
			 TypedQuery<AuditDtoMod> paramsCount= entityManager.createQuery(QueryTotal, AuditDtoMod.class);
			 cuantosregistro = (long) paramsCount.getResultList().size();
		
			 
			 switch (orderIn) { 
			    case 1:  //ordena por group y name ascendente
			    	
			    	QueryTotal = QueryTotal + " ORDER BY " + module + " ASC";
			     break;
			    case -1://ordena por group y name descendente
			    	
			    	QueryTotal = QueryTotal + " ORDER BY " + module + " DESC";
			     break;
			    default:
			    	String var2 = "";
					boolean bloked = false;
					RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var2);
					respuestaDto= new RespuestaMsgDto("Error interno del servidor");
					estatus=HttpStatus.INTERNAL_SERVER_ERROR;   
					return new ResponseEntity(respuestaDto, estatus);
			     // Default secuencia de sentencias.
			   }
			 
			 //Se mapea la entidad se le pasa el query y lo bota como un tipo de objeto AuditDto-Buscar en los DTO 
			     TypedQuery<AuditDtoMod> params= entityManager.createQuery(QueryTotal, AuditDtoMod.class);
			      params.setFirstResult(offsetIn);
			      params.setMaxResults(numofrecordsIn);
			      List<AuditDtoMod> listacompleta = params.getResultList();
			
		    	
		    	  	//Se le pasa el listado al DTO RESPONSE que contiene la estructura de Salida solicitada
			      auditoriaModDto.setNumofrecords(cuantosregistro);
			      auditoriaModDto.setSessionvalidthru(fechaComoCadena);		           
			      auditoriaModDto.setRecords(listacompleta);
											
			      return ResponseEntity.ok(auditoriaModDto);		     
						
       
		}catch (Exception e) {
            // Manejo de excepciones
			respuesta= new RespuestaDto("Error interno del servidor", false);
			estatus=HttpStatus.INTERNAL_SERVER_ERROR;            
        }finally {
	        if (entityManager != null && entityManager.isOpen()) {
	            entityManager.close();
	        }
        }
		
		return new ResponseEntity(respuesta, estatus);
	
	}
	
	
	@PostMapping("/audit")
	public ResponseEntity<AuditAllResponseDto> audit(HttpServletRequest request,@RequestBody UsersListDto tiposfiltros) throws ParseException {
		RespuestaDto respuesta = new RespuestaDto("", false);
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		AuditAllResponseDto auditoriaModDto = new AuditAllResponseDto();
		AuditAllDto detalleAudit;
	    List<AuditAllDto> listasAudit = new ArrayList<>();
	    Long cuantosregistro = (long) 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);
	        Date fechaDate = formatter.parse(dataFormattata);
	        AuditRequestDto  auditDto=new AuditRequestDto();
	        String searchStringfrom = tiposfiltros.getFilters().getDatefrom();
	        String searchStringto = tiposfiltros.getFilters().getDateto();
	       
	        String sinfecha="NO";
	        String sinfechaFrom="NO";
	        String sinfechaTo="NO";
	    
	        
	        
	   	  String searchIn = "";
	      String searchModule = "";
		  String searchUsr = "";
		  String contentIn = "";
		  //Date searchDatefrom;
		 // Date searchDateto;
		  String fechaComoCadena;
		 int orderIn = 0;
		 int offsetIn = 0;
		 int numofrecordsIn = 0;
		 Optional<Params> deSessDuration=paramsRepository.findByParamname("SESSION_DURATION");
		 String SessionDuration=deSessDuration.get().getValue();
		 int duracionSession = Integer.parseInt(SessionDuration);
		 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(); 
					   //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=="") {
						   						   						   
						   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 servicio obtiene una lista de los módulos registrados en la auditoría. (priv 600)

					   Roles roles = encontreSessionUsuario.get().getRolid();
					   int idrol = roles.getId();
					   int rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol, 600);
					   
					   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();
						  
						    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);
							  }
							  
						  searchIn = usersService.eliminarAcentosService(tiposfiltros.getFilters().getSearch());  
						  searchModule = usersService.eliminarAcentosService(tiposfiltros.getFilters().getModule());
						  searchUsr = usersService.eliminarAcentosService(tiposfiltros.getFilters().getUser());
					
						  orderIn = tiposfiltros.getOrder();
						  offsetIn = tiposfiltros.getOffset();
						  numofrecordsIn = tiposfiltros.getNumofrecords();
						  
						  contentIn = tiposfiltros.getContent();
						  if (contentIn !=null) {
						  menuService.iscontentdiffnull(contentIn, encontreSessionUsuario.get().getId());
						  }
						  						
					
				 } else {
						String var = "";
						boolean bloked = false;
						RespuestaDto respuestaDto = new RespuestaDto(var, bloked);
						respuestaDto.setBlocked(bloked);
						respuestaDto.setMsg("Sesión expirada o inválida");
						//Error 400
						return new ResponseEntity(respuestaDto, HttpStatus.UNAUTHORIZED);
				 }
			}
			
			
		
		try {
			
			
        //  SELECT * FROM main.audit a WHERE a.userref ILIKE ?4 AND a.module ILIKE ?3 AND a.createdat < ?5 ORDER BY a.createdat ASC LIMIT ?1 OFFSET ?2

			String SentenciaBase = "SELECT new com.dacrt.SBIABackend.security.dto.AuditAllDto (u.module,TO_CHAR(u.createdat, 'yyyy-mm-dd HH24:MI'),u.dsc,u.userref,u.ipaddr) FROM Audit u";
			
			String QueryTotal = "";
			String userref = "u.userref";
			String module = "u.module";
			String dsc = "u.dsc";
			String createdat = "u.createdat";
			String group = "u.module,u.id";
			String lowermodule= " main.sinacentos(LOWER(u.module))";
			String loweruserref= " main.sinacentos(LOWER(u.userref))";
			String lowerdsc= " main.sinacentos(LOWER(u.dsc))";
			String LowerSearch = searchIn.toLowerCase();
			
			 
			 switch (searchIn) { 
			    case "":  // viene sin busqueda por el like
			    	//QueryTotal = SentenciaBase  + " WHERE " + lowerdsc + " LIKE " + "'%" + "" + "%'";
			    	QueryTotal = SentenciaBase  + " WHERE " + "TRUE = TRUE ";
			     break;
			  
			    default:	// viene con el parametro para buscar por el like		   			    				    	
			    	QueryTotal = SentenciaBase  + " WHERE " + lowerdsc + " LIKE " + "'%" + LowerSearch + "%'" + " OR u.ipaddr LIKE " + "'%" + LowerSearch + "%'";
			    	
	         }
			 
			 switch (searchModule) { 
			    case "":  // viene sin busqueda por el like
			    	QueryTotal = QueryTotal;
			     break;
			  
			    default:	// viene con el parametro para buscar por el like		   			    				    	
			    	QueryTotal = QueryTotal  + " AND " + lowermodule + " LIKE " + "'%" + searchModule.toLowerCase() + "%'";
			    	
	         }
			 
			 switch (searchUsr) { 
			    case "":  // viene sin busqueda por el like
			    	QueryTotal = QueryTotal;
			     break;
			  
			    default:	// viene con el parametro para buscar por el like		   			    				    	
			    	QueryTotal = QueryTotal  + " AND " + loweruserref + " LIKE " + "'%" + searchUsr.toLowerCase() + "%'";
			    	
	         }
			 
			 Date searchDatefrom = new Date();
			 Date searchDateto= new Date();
			    
		        if (searchStringfrom==""  || searchStringto=="") {
		        	 if (searchStringfrom=="") {
		        		 
		        		 QueryTotal = QueryTotal;
		        	 } else {
		        		 QueryTotal = QueryTotal  + " AND " + "u.createdat > " + "'" + searchStringfrom + "'" ;
		        		 
		        	 }
		        		 
	                 if (searchStringto=="") {
	                	 QueryTotal = QueryTotal;
		        	 } else {
		        		 QueryTotal = QueryTotal  + " AND " + "u.createdat < " + "'" + searchStringto + "'" ;
		        	 }
		        	 
		        	 
		        } else {
		        	// AND a.module ILIKE ?3 AND a.createdat BETWEEN ?5 AND ?6 
		        	QueryTotal = QueryTotal  + " AND " + "u.createdat BETWEEN " + "'" +searchStringfrom + "'" + " AND " + "'" + searchStringto + "'";
		        	 searchDatefrom = formatter.parse(searchStringfrom);
			         searchDateto = formatter.parse(searchStringto);
			         
		        }
			 
			 TypedQuery<AuditAllDto> auditCount= entityManager.createQuery(QueryTotal, AuditAllDto.class);
			 cuantosregistro = (long) auditCount.getResultList().size();
			 
			  String ordena="";
			  if (orderIn == 1 || orderIn == 2 || orderIn == 3) {
				  ordena = " ASC";
			 }  else if (orderIn == -1 || orderIn == -2 || orderIn == -3) {
				  ordena = " DESC";
			 } else {
				 	String var2 = "";
					boolean bloked = false;
					RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var2);
					respuestaDto= new RespuestaMsgDto("Error interno del servidor");
					estatus=HttpStatus.INTERNAL_SERVER_ERROR;   
					return new ResponseEntity(respuestaDto, estatus);
			 }
		
			 int absolutoOrden = Math.abs(orderIn);
			 
			 switch (absolutoOrden) { 
			    case 1:  //ordena por FECHA DE CREACION ascendente
			    	
			    	QueryTotal = QueryTotal + " ORDER BY " + "u.createdat" + ordena;
			     break;
                case 2:  //ordena por MODULO ascendente
			    	
			    	QueryTotal = QueryTotal + " ORDER BY " + "u.module" + ordena;
			     break;
                case 3:  //ordena por USUARIO ascendente
 	
 	                QueryTotal = QueryTotal + " ORDER BY " + "u.userref" + ordena;
                 break;
		  }
			 
			   TypedQuery<AuditAllDto> audito= entityManager.createQuery(QueryTotal, AuditAllDto.class);
			       audito.setFirstResult(offsetIn);
			       audito.setMaxResults(numofrecordsIn);
			      List<AuditAllDto> listacompleta = audito.getResultList();
			      
			      auditoriaModDto.setNumofrecords(cuantosregistro);
			       auditoriaModDto.setSessionvalidthru(fechaComoCadena);
			       auditoriaModDto.setRecords(listacompleta);
			       return ResponseEntity.ok(auditoriaModDto);
       
		}catch (Exception e) {
            // Manejo de excepciones
			respuesta= new RespuestaDto("Error interno del servidor", false);
			estatus=HttpStatus.INTERNAL_SERVER_ERROR;            
        }finally {
	        if (entityManager != null && entityManager.isOpen()) {
	            entityManager.close();
	        }
        }
		
		return new ResponseEntity(respuesta, estatus);
	
	}
	
	//@GetMapping("/menus)
		//public ResponseEntity<MenuResponseDto> menu(@PathVariable final String sessionid) throws ParseException {
	    @GetMapping("/extendsession")
		public ResponseEntity<ParamsResponseDto> extendSession(HttpServletRequest request) throws ParseException {
			RespuestaValidThruDto respuestaValidThruDto;
			RespuestaMsgDto respuestaMsgDto;
			RespuestaDto respuesta = new RespuestaDto("", false);
			HttpStatus estatus = HttpStatus.FORBIDDEN;
			ParamsResponseDto paramsResponseDto = new ParamsResponseDto();
			ParamsDto detalleParams;
			PrivilegesDto detallePrivilege;
			String fechaComoCadena;
			String sessionid = request.getHeader("Authorization");
			Long cuantosregistro = (long) 0;
		     List<ParamsDto> listasParams = new ArrayList<>();
		     List<PrivilegesDto> listasPrivelege = new ArrayList <>();

		     
		     try {
				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()) {
						   
						   
						
						   //Este proceso permite obtener un listado de los parámetros (tabla "params") (Priv 610)
						   Roles roles = encontreSessionUsuario.get().getRolid();
						   int idrol = roles.getId();
						   int rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol, 610);
						   rolisvalid = 1;
						   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 {
						    	  
						    	
						    	  
						    	  Optional<Params> deSessDuration=paramsRepository.findByParamname("SESSION_DURATION");
						 		  String SessionDuration=deSessDuration.get().getValue();
						 	      int duracionSession = Integer.parseInt(SessionDuration);
						 	      Calendar calendar = Calendar.getInstance();
						 		  calendar.add(Calendar.MINUTE,duracionSession); //horasASumar es int.
					        	  Date ValidThrufechaSalida = calendar.getTime(); //Y ya tienes la fecha sumada.
					              SimpleDateFormat salida = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //2024-12-23 23:00
					              String resp = salida.format(ValidThrufechaSalida);
					              
					               usersRepository.asociarcambioValidthru(encontreSessionUsuario.get().getId(),ValidThrufechaSalida);
									
					               //respuestaMsgDto= new RespuestaMsgDto(resp);
					               respuestaValidThruDto= new RespuestaValidThruDto(resp);
									estatus=HttpStatus.OK;
									return new ResponseEntity(respuestaValidThruDto, estatus);
						    
						    	  
						      }			
				
					
						
				   	 } 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);
					 }
				}
				
				
	    } catch (Exception e) {
	            // Manejo de excepciones
				 respuesta = new RespuestaDto("Error interno del servidor", false);
				estatus=HttpStatus.INTERNAL_SERVER_ERROR;            
	        }
		 return new ResponseEntity(respuesta, estatus);
				
		}
	    
	  //@GetMapping("/menus)
	  		//public ResponseEntity<MenuResponseDto> menu(@PathVariable final String sessionid) throws ParseException {
	  	    @GetMapping("/pwdcomplexity")
	  		public ResponseEntity<Object> pwdcomplexity(HttpServletRequest request) throws ParseException {
	  			RespuestaValidThruDto respuestaValidThruDto;
	  			RespuestaMsgDto respuestaMsgDto;
	  			RespuestaDto respuesta = new RespuestaDto("", false);
	  			HttpStatus estatus = HttpStatus.FORBIDDEN;
	  			ParamsResponseDto paramsResponseDto = new ParamsResponseDto();
	  			ParamsDto detalleParams;
	  			PrivilegesDto detallePrivilege;
	  			String fechaComoCadena;
	  			String sessionid = request.getHeader("Authorization");
	  			Long cuantosregistro = (long) 0;
	  			 Date fecha2 = new Date();
	  		     List<ParamsDto> listasParams = new ArrayList<>();
	  		     List<PrivilegesDto> listasPrivelege = new ArrayList <>();

	  		   try {
	  		     
	  				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(); 
	  					   //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);
	  						   
	  					    }
	  					   
	  						   
	  						
	  						   //Este proceso permite obtener un listado de los parámetros (tabla "params") (Priv 610)
	  						   Roles roles = encontreSessionUsuario.get().getRolid();
	  						   int idrol = roles.getId();
	  						   int rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol, 610);
	  						   rolisvalid = 1;
	  						   
	  						   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 {
	  						    	  
	  						    /*	String SentenciaBase = "SELECT u.paramname,u.value  FROM  main.params  u where u.paramname like '%PWD%'";
	  						    	List<Map<String, Object>> lista = jdbcTemplate.queryForList(SentenciaBase);
	  						    	
	  				    			
	  				    			 for (Map<String, Object> mapa : lista) {
	  				    				 String name = (String) mapa.get("paramname"); 
	  				    				 String value = (String) mapa.get("value");
	  				    				 
	  				    				 String valie2 = value;
	  				    			 }*/
	  				    			 
	  				    			
	  				    			/* //TypedQuery<Object> params= entityManager.createQuery(SentenciaBase, Object.class);
	  				    			List<Object> resultados;
	  				    			Object salida;
	  				    			resultados = params.getResultList();
	  				    			 * for (Object obj : resultados) {
	  				    				if (obj instanceof Params) {
	  				    					Params param = (Params) obj;
	  				    					String paramname = param.getParamname();
	  				    					String valor = param.getValue();
	  				    					salida = new Object(paramname,valor);
	  				    				}
	  				    			}*/
	  				    			
	  				    			
	  				    			
	  				    			
	  						    	  
	  						    	  Optional<Params> Minupper=paramsRepository.findByParamname("PWD_UPPERCASE");
	  						 		  String minupper=Minupper.get().getValue();
	  						 		  Optional<Params> Minsymbols=paramsRepository.findByParamname("PWD_SYMBOLS");
	  						 		  String minsymbols=Minsymbols.get().getValue();
	  						 		  Optional<Params> Minlower=paramsRepository.findByParamname("PWD_LOWERCASE");
	  						 		  String minlower=Minlower.get().getValue();
	  						 		  Optional<Params> Minlengthn=paramsRepository.findByParamname("PWD_MINLENGTH");
	  						 		  String minlengthn=Minlengthn.get().getValue();
	  						 		  Optional<Params> Allowedsimbols=paramsRepository.findByParamname("PWD_ALLOWEDSYM");
	  						 		  String allowedsimbols=Allowedsimbols.get().getValue();
	  						 		  
	  						 		PwdcomplexityDto pwdcomplexityDto = new PwdcomplexityDto();
	  						 	
	  						 		pwdcomplexityDto.setMinlength(minlengthn);
	  						 		
	  						 		pwdcomplexityDto.setMinupper(minupper);
	  						 		pwdcomplexityDto.setMinlower(minlower);
	  						 		pwdcomplexityDto.setMinsymbols(minsymbols);
	  						 		pwdcomplexityDto.setAllowedsimbols(allowedsimbols);
	  						 	     
	  									
	  					               //respuestaMsgDto= new RespuestaMsgDto(resp);
	  					              /// respuestaValidThruDto= new RespuestaValidThruDto(resp);
	  								//	estatus=HttpStatus.OK;
	  									return new ResponseEntity(pwdcomplexityDto, HttpStatus.OK);
	  						    
	  						    	  
	  						      }			
	  				
	  					
	  						
	  				   	 } 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);
	  					 }
	  				}
	  			} catch (Exception e) {
	  	            // Manejo de excepciones
	  				 respuesta = new RespuestaDto("Error interno del servidor", false);
	  				estatus=HttpStatus.INTERNAL_SERVER_ERROR;            
	  	        }
	  		 return new ResponseEntity(respuesta, estatus);
	  		}
	  	    
private String createPostRedirectForm(
	  	        String url, 
	  	        String sessionid, 
	  	        String entrypoint, 
	  	        String fullname, 
	  	        String validthru) throws UnsupportedEncodingException {
         	String encodedSessionId="";
         	String encodedEntrypoint="";
         	String encodedFullname="";
         	String encodedValidthru="";
	  	    // Codificar los valores antes de inyectarlos en el HTML para evitar problemas
	  if (entrypoint!=null) {
	  	     encodedSessionId = URLEncoder.encode(sessionid, StandardCharsets.UTF_8.toString());
	  	     encodedEntrypoint = URLEncoder.encode(entrypoint, StandardCharsets.UTF_8.toString());
	  	     encodedFullname = URLEncoder.encode(fullname, StandardCharsets.UTF_8.toString());
	  	     encodedValidthru = URLEncoder.encode(validthru, StandardCharsets.UTF_8.toString());
	  }
	  	    String html = String.format(
	  	        "<html>" +
	  	            "<head>" +
	  	                "<title>Redirigiendo a pagina Okta .....</title>" +
	  	            "</head>" +
	  	            // La clave es el onload para ejecutar el POST automáticamente
	  	            "<body onload=\"document.forms[0].submit()\" style=\"font-family: sans-serif; text-align: center; padding-top: 50px;\">" +
	  	                "<p>Acceso verificado. Redirigiendo de forma segura...</p>" +
	  	                "<form method=\"post\" action=\"%s\">" +
	  	                    "<input type=\"hidden\" name=\"sessionid\" value=\"%s\"/>" +
	  	                    "<input type=\"hidden\" name=\"entrypoint\" value=\"%s\"/>" +
	  	                    "<input type=\"hidden\" name=\"fullname\" value=\"%s\"/>" +
	  	                    "<input type=\"hidden\" name=\"validthru\" value=\"%s\"/>" +
	  	                    "<noscript>" +
	  	                        "<p>Su navegador debe habilitar JavaScript. Haga clic en Continuar si no es redirigido automáticamente.</p>" +
	  	                        "<input type=\"submit\" value=\"Continuar\" style=\"padding: 10px 20px; cursor: pointer;\"/>" +
	  	                    "</noscript>" +
	  	                "</form>" +
	  	            "</body>" +
	  	        "</html>",
	  	        url,
	  	        encodedSessionId,
	  	        encodedEntrypoint,
	  	        encodedFullname,
	  	        encodedValidthru
	  	    );
	  	    return html;
	  	}	  	    
		
}