package com.dacrt.SBIABackend.controler;

import java.net.URI;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Optional;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.dacrt.SBIABackend.security.dto.AuditRequestDto;
import com.dacrt.SBIABackend.dto.UnitsUsersDto;
import com.dacrt.SBIABackend.dto.CampaignFormat2Dto;
import com.dacrt.SBIABackend.dto.EntryPositionDto;
import com.dacrt.SBIABackend.dto.EntryPositionDto2;
import com.dacrt.SBIABackend.dto.PositionActualizarDto;
import com.dacrt.SBIABackend.dto.PositionDto;
import com.dacrt.SBIABackend.dto.RecordCatalogoResponseDto;
import com.dacrt.SBIABackend.dto.StatusDto;
import com.dacrt.SBIABackend.dto.StatusDto2;
import com.dacrt.SBIABackend.dto.responseDto.PositionResponseDto;
import com.dacrt.SBIABackend.entity.Positions;
import com.dacrt.SBIABackend.entity.Positionunits;
import com.dacrt.SBIABackend.security.dto.RespuestaDto;
import com.dacrt.SBIABackend.security.dto.RespuestaMsgDto;
import com.dacrt.SBIABackend.security.dto.RespuestaValueDto;
import com.dacrt.SBIABackend.security.dto.UsersListDto;
import com.dacrt.SBIABackend.security.dto.PrivilegesAllDto;
import com.dacrt.SBIABackend.security.entity.Params;
import com.dacrt.SBIABackend.security.entity.Roles;
import com.dacrt.SBIABackend.security.entity.Users;
import com.dacrt.SBIABackend.security.repository.ParamsRepository;
import com.dacrt.SBIABackend.security.repository.RolesPrivilegesRepository;
import com.dacrt.SBIABackend.security.repository.UsersRepository;
import com.dacrt.SBIABackend.security.service.UsersService;
import com.dacrt.SBIABackend.service.UnitsService;
import com.dacrt.SBIABackend.security.service.MenuService;
import com.dacrt.SBIABackend.security.service.ParamsService;
import com.dacrt.SBIABackend.security.service.SecurityService;
import com.dacrt.SBIABackend.utils.HttpReqRespUtils;
import com.dacrt.SBIABackend.security.repository.AuditRepository;
import com.dacrt.SBIABackend.repository.PositionsRepository;
import com.dacrt.SBIABackend.repository.PositionunitsRepository;
import com.dacrt.SBIABackend.repository.UnitsRepository;
import com.dacrt.SBIABackend.repository.UserunitsRepository;

@RestController
@CrossOrigin(origins = "*")

public class PositionsController {

	@Autowired
	private ParamsRepository paramsRepository;

	@Autowired
	private UsersRepository usersRepository;

	@Autowired
	private AuditRepository auditRepository;

	@Autowired
	private RolesPrivilegesRepository rolesPrivilegesRepository;

	@Autowired
	private PositionsRepository positionsRepository;

	@Autowired
	UsersService usersService;

	@Autowired
	SecurityService securityService;

	@Autowired
	ParamsService paramsService;

	@Autowired
	MenuService menuService;

	@Autowired
	UserunitsRepository userunitsRepository;

	@Autowired
	UnitsRepository unitsRepository;

	@Autowired
	PositionunitsRepository positionunitsRepository;

	@Autowired
	UnitsService unitsService;

	@Autowired
	private JdbcTemplate jdbcTemplate;

	@PersistenceContext
	private EntityManager entityManager;

	@Value("${spring.datasource.url}")
	private String conexion;

	@Value("${spring.datasource.username}")
	private String userbd;

	@Value("${spring.datasource.password}")
	private String passbd;

	@PostMapping("/positions")
	public ResponseEntity<?> positions(HttpServletRequest request, @RequestBody UsersListDto tiposfiltros)
			throws ParseException {
		RespuestaDto respuesta = new RespuestaDto("", false);
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		PositionResponseDto positionResponseDto = new PositionResponseDto();
		RecordCatalogoResponseDto facilityFormatResponseDto = new RecordCatalogoResponseDto();
		CampaignFormat2Dto detalleCompaing2;
		int formatList = 0;
		// ParamsDto detalleParams;
		UnitsUsersDto detalleUnits;
		StatusDto detalleStatus;
		UnitsUsersDto detalleUnitsShort;
		PositionDto detallePosition;
		PrivilegesAllDto detallePrivilege;

		List<PositionDto> listasPosition = new ArrayList<>();

		Long cuantosregistro = (long) 0;

		// List<PrivilegesDto> listasPrivelege = new ArrayList<>();

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

		int idrol;
		boolean searchShowall;
		String searchIn = "";
		int usuarioLogin;
		String contentIn = "";
		int searchStatus = 0;
		int searchVP, searchFacility, searchType, searchUnits;
		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);
			// String usuarioIN = encontreSessionUsuario.get().getUsr();
			// int position = usuarioIN.indexOf('(');
			if (encontreSessionUsuario.isPresent()) {
				Date FechaReg = encontreSessionUsuario.get().getValidthru();

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

				}

				
	             formatList = 1;
				
				try {
					//formatIn = evalProcessRequestDto.getFormat();
					formatList = tiposfiltros.getFormat();
					if (formatList==0) {
						formatList = 1;
					}

				} catch (Exception e) {
					formatList = 1;

				}
				// Funcion de validación de roles para poder ejecutar el endpoint

				Roles roles = encontreSessionUsuario.get().getRolid();
				idrol = roles.getId();
				int rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol, 410);
				if (formatList != 2) {

					if (rolisvalid == 0) {

						String var = "";
						boolean bloked = false;
						RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
						// respuestaDto.setBlocked(bloked);
						respuestaDto.setMsg("No tiene los Privilegios");
						return new ResponseEntity(respuestaDto, HttpStatus.FORBIDDEN);
					}
				}
				// seteo del request body, valores que vienen desde el front

				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);
				  }
				searchUnits = tiposfiltros.getFilters().getUnitid();
				searchStatus = tiposfiltros.getFilters().getStatus();
				searchVP = tiposfiltros.getFilters().getVicepresidencyid();
				searchFacility = tiposfiltros.getFilters().getFacilityid();
				searchType = tiposfiltros.getFilters().getUnittype();
				orderIn = tiposfiltros.getOrder();
				offsetIn = tiposfiltros.getOffset();
				numofrecordsIn = tiposfiltros.getNumofrecords();

				try {
					searchShowall = tiposfiltros.getFilters().isShowall();

				} catch (Exception e) {
					searchShowall = false;

				}

				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;
			String sqlAdd;
			String sqlWhereAdd;
			if (!searchShowall) {
				sqlAdd = " LEFT JOIN main.userunits uu ON pu.unitid = uu.unitid ";
				if (searchUnits!=0)
					sqlWhereAdd = " AND uu.userid = " + usuarioLogin + " " +
					              " WHERE 1=1 ";
				else
					sqlWhereAdd = " AND 1=1 " +
				              " WHERE 1=1 ";

			} else {
				sqlWhereAdd = " WHERE  1=1 ";
				sqlAdd = "";
			}

			SentenciaBase = "select c.id,c.name,c.status,CASE WHEN c.status = 1 THEN 'Activo' ELSE 'Inactivo' END AS estatus, STRING_AGG(DISTINCT CAST(pu.unitid AS TEXT), ';') idunidades,STRING_AGG(DISTINCT CAST(u.name AS TEXT), ';') unidades,c.dsc,STRING_AGG(DISTINCT CAST(pu.id AS TEXT), ';') unidadesid "
					+ "	FROM main.positions c LEFT JOIN main.positionunits pu ON c.id = pu.positionid "
					+ "	LEFT JOIN  main.units u ON u.id = pu.unitid ";

			SentenciaBase = SentenciaBase + sqlAdd + sqlWhereAdd;

			String QueryTotal = "";
			String name = "c.dsc";
			String name2 = "c.name";
			String status = "c.status";
			String lowername = "LOWER(c.dsc)";
			String LowerSearch = searchIn.toLowerCase();

			switch (searchStatus) {
			case 0: // Busca por cualquier estatus
				QueryTotal = SentenciaBase + " AND 1 = 1 ";
				break;
			case 1: // Busca por estatus activo

				QueryTotal = SentenciaBase + " AND " + status + " = " + searchStatus;
				break;
			case 2: // Busca por estatus Inactivo

				// QueryTotal = QueryTotal + " AND " + status + " = " + searchStatus;
				QueryTotal = SentenciaBase + " AND " + "c.status" + " = " + 0;
				break;

			default: // viene con el parametro para buscar por el like
				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);

			}

			switch (searchUnits) {
			case 0: // viene en 0 y hace las busqueda por todas las unidades
				QueryTotal = QueryTotal + " AND c.id IN (SELECT pu_filter.positionid "
						+ " FROM main.positionunits pu_filter WHERE pu_filter.positionid = c.id )";
				break;
			case -99: // viene en 0 y hace las busqueda por todas las unidades
				QueryTotal = QueryTotal;
				break;	

			default: // filtra por el id de unidad enviada desde el front
				//QueryTotal = QueryTotal + " AND pu.unitid = " + searchUnits;
				QueryTotal = QueryTotal + " AND c.id IN (SELECT pu_filter.positionid " +
					      " FROM main.positionunits pu_filter WHERE pu_filter.positionid = c.id AND pu_filter.unitid = " +searchUnits + " ) ";

			}

			switch (searchIn) {
			case "": // viene sin busqueda por el like
				// QueryTotal = SentenciaBase;
				// QueryTotal = SentenciaBase + " WHERE " + lowername + " LIKE " + "'%" + "" +
				// "%'";
				QueryTotal = QueryTotal;
				break;

			default: // viene con el parametro para buscar por el like
				QueryTotal = QueryTotal + " AND (" + " main.sinacentos(LOWER(c.name)) " + " LIKE " + "'%" + LowerSearch + "%'" + " OR main.sinacentos(LOWER(c.dsc)) LIKE " + "'%" + LowerSearch + "%'" + ")";

			}

			Query query;

			String Group = " GROUP BY c.id,c.name,c.status,c.dsc ";
			QueryTotal = QueryTotal + Group;
			if (formatList == 1) { /// solo cuento cuando el formato es 1

				query = entityManager.createNativeQuery(QueryTotal);
				cuantosregistro = (long) query.getResultList().size();
			}

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

			int absolutoOrden = Math.abs(orderIn);

			switch (absolutoOrden) {
			case 1: // ordena por dsc ascendente

				QueryTotal = QueryTotal + " ORDER BY " + " c.name " + ordena;
				break;
			case 2: // ordena por status ascendente

				QueryTotal = QueryTotal + " ORDER BY " + status + ordena;
				break;
			case 3: // ordena por dsc

				QueryTotal = QueryTotal + " ORDER BY " + " c.dsc " + ordena;
				break;
			case 99: // ordena por status ascendente

				QueryTotal = QueryTotal + " ORDER BY " + "c.id" + ordena;
				break;
			default:
				String var2 = "";
				boolean bloked = false;
				RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var2);
				respuestaDto = new RespuestaMsgDto("Llamada al servicio malformado");
				estatus = HttpStatus.BAD_REQUEST;
				return new ResponseEntity(respuestaDto, estatus);

			}

			if (formatList != 2) {

				query = entityManager.createNativeQuery(QueryTotal);
				
				
				query.setFirstResult(offsetIn);
				query.setMaxResults(numofrecordsIn);
				List<Object[]> listacompleta = query.getResultList();
				// List<UnitsUsersDto> listasUnits = new ArrayList<>();
				detalleUnits = new UnitsUsersDto();
				detallePosition = new PositionDto();
				int idactual = 0;
				for (Object[] reg : listacompleta) {

					detallePosition = new PositionDto();

					detalleStatus = new StatusDto();
					detalleUnits = new UnitsUsersDto();
					List<Integer> can = new ArrayList<>();
					List<UnitsUsersDto> listasUnits = new ArrayList<>();
					can = new ArrayList<>();
					detallePosition.setId((int) reg[0]);
					detallePosition.setName((String) reg[1]);

					detalleStatus.setId((int) reg[2]);
					detalleStatus.setName((String) reg[3]);

					String IdUniString = (String) reg[4]; // AQUI VIENEN LOS ID DE LAS UNIDADES
					String NameUniString = (String) reg[5]; // AQUI VIENEN LOS NOMBRES DE LAS UNIDADES
					String IdUnitPositionString = (String) reg[7]; // AQUI VIENEN LOS ID DE UNIDADES PROSITIONS


					if (IdUniString != null && !IdUniString.isEmpty()) {

						String[] UniIds = IdUniString.split(";");
						String[] UniNames = NameUniString.split(";");
						String[] UniPosiId = IdUnitPositionString.split(";");
						int i = 0;
						listasUnits = new ArrayList<>();
						for (String uniId : UniIds) {
							detalleUnits = new UnitsUsersDto();
							can.add(Integer.parseInt(uniId));
							String Nombreuni = UniNames[i];
							String Idunipos = UniPosiId[i];
							detalleUnits.setId(Integer.parseInt(uniId));
							detalleUnits.setName(Nombreuni);
							detalleUnits.setPositionunitid(Integer.parseInt(Idunipos));
							listasUnits.add(detalleUnits);
							i = i + 1;
						}
					} else {
						System.out.print(IdUniString);
						detalleUnits = new UnitsUsersDto();

						// detalleUnits.setId(0);
						// detalleUnits.setName(null);
						// listasUnits.add(detalleUnits);
					}

					detallePosition.setStatus(detalleStatus);

					detallePosition.setUnits(listasUnits);
					
					detallePosition.setDsc((String) reg[6]==null?"":(String) reg[6]);

					// idactual = (int) reg[0];
					listasPosition.add(detallePosition);
				}

				detallePrivilege = new PrivilegesAllDto();

				boolean tieneView = rolesPrivilegesRepository.existsByRolidAndPrivilegeid(idrol, 410);
				boolean tieneUpdate = rolesPrivilegesRepository.existsByRolidAndPrivilegeid(idrol, 411);
				boolean tieneAdd = rolesPrivilegesRepository.existsByRolidAndPrivilegeid(idrol, 412);
				boolean tieneDelete = rolesPrivilegesRepository.existsByRolidAndPrivilegeid(idrol, 413);
				// existsByRolidAndPrivilegeid

				detallePrivilege.setView(tieneView);
				detallePrivilege.setUpdate(tieneUpdate);
				detallePrivilege.setAdd(tieneAdd);
				detallePrivilege.setDelete(tieneDelete);

				positionResponseDto.setNumofrecords(cuantosregistro);
				// paramsResponseDto.setValidthru(ValidThrufechaSalida);
				positionResponseDto.setSessionvalidthru(fechaComoCadena);
				positionResponseDto.setRecords(listasPosition);
				positionResponseDto.setPrivileges(detallePrivilege);

				return ResponseEntity.ok(positionResponseDto);

			} else {

				query = entityManager.createNativeQuery(QueryTotal);
				// query.setFirstResult(offsetIn);
				// query.setMaxResults(numofrecordsIn);
				// List<UnitsDtoStatus> listacompleta = query.getResultList();
				List<Object[]> listacompleta = query.getResultList();
				cuantosregistro = (long) query.getResultList().size();
				// List<UnitsUsersDto> listasUnits = new ArrayList<>();
				detalleUnits = new UnitsUsersDto();
				detallePosition = new PositionDto();
				int idactual = 0;
				for (Object[] reg : listacompleta) {

					detallePosition = new PositionDto();
					List<UnitsUsersDto> listasUnits = new ArrayList<>();
					detalleStatus = new StatusDto();
					detalleUnits = new UnitsUsersDto();
					List<Integer> can = new ArrayList<>();
					can = new ArrayList<>();
					detallePosition.setId((int) reg[0]);
					detallePosition.setName((String) reg[1]);

					detalleStatus.setId((int) reg[2]);
					detalleStatus.setName((String) reg[3]);

					String IdUniString = (String) reg[4]; // AQUI VIENEN LOS ID DE LAS UNIDADES
					String NameUniString = (String) reg[5]; // AQUI VIENEN LOS NOMBRES DE LAS UNIDADES
					String IdUnitPositionString = (String) reg[7]; // AQUI VIENEN LOS ID DE UNIDADES PROSITIONS

					if (IdUniString != null && !IdUniString.isEmpty()) {

						String[] UniIds = IdUniString.split(";");
						String[] UniNames = NameUniString.split(";");
						String[] UniPosiId = IdUnitPositionString.split(";");
						int i = 0;
						listasUnits = new ArrayList<>();
						for (String uniId : UniIds) {
							detalleUnits = new UnitsUsersDto();
							can.add(Integer.parseInt(uniId));
							String Nombreuni = UniNames[i];
							String Idunipos = UniPosiId[i];
							detalleUnits.setId(Integer.parseInt(uniId));
							detalleUnits.setName(Nombreuni);
							detalleUnits.setPositionunitid(Integer.parseInt(Idunipos));
							listasUnits.add(detalleUnits);
							i = i + 1;
						}
					} else {
						System.out.print(IdUniString);
						detalleUnits = new UnitsUsersDto();

						// detalleUnits.setId(0);
						// detalleUnits.setName(null);
						// listasUnits.add(detalleUnits);
					}

					detallePosition.setStatus(detalleStatus);

					detallePosition.setUnits(listasUnits);

					detallePosition.setDsc((String) reg[6]==null?"":(String) reg[6]);
					// idactual = (int) reg[0];
					listasPosition.add(detallePosition);
				}

				positionResponseDto.setNumofrecords(cuantosregistro);
				positionResponseDto.setSessionvalidthru(fechaComoCadena);
				positionResponseDto.setRecords(listasPosition);

				return ResponseEntity.ok(positionResponseDto);

			

			}

		} 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("/positions/{positionsid}")
	public ResponseEntity<?> obtenerUnPosition(HttpServletRequest request,
			@PathVariable("positionsid") final Integer positionsid) throws ParseException {

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

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

		String contentIn = "";

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

		// Verifico la session
		if (sessionid == null) {
			respuesta.setMsg("Llamada al servicio malformado");
			estatus = HttpStatus.BAD_REQUEST;
			return new ResponseEntity(respuesta, estatus);
		} else {
			sessionid = sessionid.substring(7);
			// verifico si la sesión del usuario existe.
			Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(sessionid);
			if (encontreSessionUsuario.isPresent()) { // si la sesión del usuario existe
				Date FechaReg = encontreSessionUsuario.get().getValidthru();
				// Llamada a la funcion que validad el tiempo de Session, retorna la fecha
				// sumandole el tiempo de session activa, y vacio si no esta activa
				fechaComoCadena = securityService.consultarSessionActiva(FechaReg, fecha2,
						encontreSessionUsuario.get().getId());

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

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

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

			// Aqui empieza la carga de la data de respuesta

			EntryPositionDto entryPositionDto = new EntryPositionDto();
			EntryPositionDto2 entryPositionDto2 = new EntryPositionDto2();

			try {
				Query query;
				Query query2;
				Long cuantosregistro2 = 0L;
				List<Object[]> resultadosUnidades;
				StatusDto2 status = new StatusDto2();
				// Sentencia General
				String SentenciaBase = "SELECT p.id,p.name,p.dsc,p.status, "
						+ "                     CASE WHEN p.status = 1 THEN 'Activo' ELSE 'Inactivo' END AS descStatus "
						+ "              FROM main.positions p " + "              WHERE p.id = :positionsid ";
				query = entityManager.createNativeQuery(SentenciaBase);
				query.setParameter("positionsid", positionsid);
				cuantosregistro = (long) query.getResultList().size();
				List<Object[]> resultados = query.getResultList();
				UnitsUsersDto units = new UnitsUsersDto();
				List<UnitsUsersDto> listUnits = new ArrayList();

				String QueryUnidades = "SELECT u.id,u.name,p.id as idrela " 
				      + " FROM main.positionunits p,main.units u "
						+ " WHERE p.positionid = :positionsid "
						+ " AND u.id = p.unitid " + " order by 1 ";

				query2 = entityManager.createNativeQuery(QueryUnidades);
				query2.setParameter("positionsid", positionsid);
				cuantosregistro2 = (long) query2.getResultList().size();
				resultadosUnidades = query2.getResultList();

				for (Object[] fila2 : resultadosUnidades) {
					units.setId((int) fila2[0]);
					units.setName((String) fila2[1]);
					units.setPositionunitid((int) fila2[2]);
					listUnits.add(units);
					units = new UnitsUsersDto();
				}

				if (cuantosregistro > 0) {
					// 4. Recorrer la lista y procesar los resultados
					for (Object[] fila : resultados) {
						entryPositionDto2.setId((int) fila[0]);
						entryPositionDto2.setName((String) fila[1]);
						entryPositionDto2.setDsc((String) fila[2]==null?"":(String) fila[2]);

						status.setId((int) fila[3]);
						status.setName((String) fila[4]);
						entryPositionDto2.setStatus(status);
						entryPositionDto2.setUnits(listUnits);
						entryPositionDto.setEntry(entryPositionDto2);

						status = new StatusDto2();

					}

					entryPositionDto.setEntry(entryPositionDto2);

				} else {
					respuesta.setMsg("Registro no encontrado");
					return new ResponseEntity(respuesta, HttpStatus.NOT_FOUND);
				}
				return new ResponseEntity(entryPositionDto, HttpStatus.OK);

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

	@PostMapping("/positions/{positionid}")
	public ResponseEntity<?> actualizarPosition(HttpServletRequest request,
			@RequestBody PositionActualizarDto positionActualizarDto,
			@PathVariable("positionid") final Integer positionid) throws ParseException {

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

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

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

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

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

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

			Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(sessionid);
			if (encontreSessionUsuario.isPresent()) { // si la sesión del usuario existe
				Date FechaReg = encontreSessionUsuario.get().getValidthru();
				// Llamada a la funcion que validad el tiempo de Session, retorna la fecha
				// sumandole el tiempo de session activa, y vacio si no esta activa
				fechaComoCadena = securityService.consultarSessionActiva(FechaReg, fecha2,
						encontreSessionUsuario.get().getId());
				if (fechaComoCadena == "") {
					RespuestaMsgDto respuestaDto2;
					String var2 = "";
					boolean bloked2 = false;
					respuestaDto2 = new RespuestaMsgDto(var2);
					respuestaDto2.setMsg("Sesión expirada o inválida");
					return new ResponseEntity(respuestaDto2, HttpStatus.UNAUTHORIZED);
				}

				int rolisvalid = 0;
				if (positionid != 0) {// actualizar Cargo
					
					 String Salida = usersService.verificarCaracteresValidosConRegex(positionActualizarDto.getName());
					  
					  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);
					  }
					  
                      String SalidaDsc = usersService.verificarCaracteresValidosConRegex(positionActualizarDto.getDsc());
					  
					  if (SalidaDsc=="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);
					  }
					  

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

						// Verificar si el campo nombre no puede ser vacío
						if (positionActualizarDto.getName() == "") {
							String var = "";
							RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
							respuestaDto.setMsg("El campo nombre no puede ser vacío");
							return new ResponseEntity(respuestaDto, HttpStatus.BAD_REQUEST);
						}

						// Verifico si existe el id del cargo en la base de datos
						Optional<Positions> obtposition = positionsRepository.findById(positionid);
						Positions position = new Positions();
						Positions position2 = new Positions();
						// Verifico si encontre el cargo
						if (obtposition.isPresent()) {
							position = obtposition.get();
						} else {
							respuesta.setMsg("Registro no encontrado");
							return new ResponseEntity(respuesta, HttpStatus.NOT_FOUND);
						}
						
						// Verificar si el nombre del cargo existe en la base de datos
						if (positionsRepository.existsByName(positionActualizarDto.getName()) && positionsRepository
								.getByName(positionActualizarDto.getName()).get().getId() != positionid) {
							respuesta.setMsg("Registro Duplicado");
							return new ResponseEntity(respuesta, HttpStatus.CONFLICT);
						}

						// Construyo los datos de la entidad de procesos
						position.setStatus(positionActualizarDto.getStatus());
						position.setName(positionActualizarDto.getName());
						position.setDsc(positionActualizarDto.getDsc());
						position.setModifiedat(fecha2);

						position2 = positionsRepository.save(position);

						if (position2 != null) {

							if (positionActualizarDto.getUnits() != null) {
								positionunitsRepository.borrarPositionunits(positionid);
								UnitsUsersDto units = new UnitsUsersDto();
								Positionunits positionunits = new Positionunits();

								for (Integer uni : positionActualizarDto.getUnits()) {
									positionunits.setPositionid(position2.getId());
									positionunits.setUnitid(uni);

									positionunitsRepository.save(positionunits);
									positionunits = new Positionunits();
								}
							}
							module = "Cargos";
							Descmodule = "Se actualizó el cargo: " + position2.getName() + " con id: "+position2.getId();
							auditDto.setIpaddr(HttpReqRespUtils.getClientIpAddressIfServletRequestExist());
							String singo1 = "(";
							String singo2 = ")";
							String usryemail = encontreSessionUsuario.get().getUsr().concat(" ").concat(singo1)
									.concat(encontreSessionUsuario.get().getEmail().concat(singo2));
							auditDto.setUserref(usryemail);
							auditDto.setModule(module);
							auditDto.setDesc(Descmodule);
							auditDto.setCreatedat(fechaDate2);
							usersService.registrarAuditSesion(auditDto);

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

							return ResponseEntity.created(location).body(respuestaValueDto);
						}
					} catch (Exception e) {
						respuesta.setMsg("Error interno del servidor ");
						estatus = HttpStatus.INTERNAL_SERVER_ERROR;
					}finally {
						if (entityManager != null && entityManager.isOpen()) {
							entityManager.close();
						}
					}

				} else { // incluir cargo

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

						// Verificar si el campo nombre no puede ser vacío
						if (positionActualizarDto.getName() == "") {
							String var = "";
							RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
							respuestaDto.setMsg("El campo nombre no puede ser vacío");
							return new ResponseEntity(respuestaDto, HttpStatus.BAD_REQUEST);
						}

						// Verificar si el registro está duplicado el nombre en la base de datos
						if (positionsRepository.existsByName(positionActualizarDto.getName())) {
							String var = "";
							RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var);
							respuestaDto.setMsg("Registro Duplicado");
							return new ResponseEntity(respuestaDto, HttpStatus.CONFLICT);
						}

						// Construyo los datos de la entidad de procesos
						Positions position = new Positions();
						Positions position2 = new Positions();
						// Construyo los datos de la entidad de procesos
						position.setStatus(positionActualizarDto.getStatus());
						position.setName(positionActualizarDto.getName());
						position.setDsc(positionActualizarDto.getDsc());
						position.setModifiedat(fecha2);
						position.setCreatedat(fecha2);
						position2 = positionsRepository.save(position);

						try {
							if (position2 != null) {

								UnitsUsersDto units = new UnitsUsersDto();
								Positionunits positionunits = new Positionunits();

								for (Integer uni : positionActualizarDto.getUnits()) {
									positionunits.setPositionid(position2.getId());
									positionunits.setUnitid(uni);

									positionunitsRepository.save(positionunits);
									positionunits = new Positionunits();
								}

								module = "Cargos";
								Descmodule = "Se insertó el cargo: " + position2.getName() + " con id: "+position2.getId();
								auditDto.setIpaddr(HttpReqRespUtils.getClientIpAddressIfServletRequestExist());
								String singo1 = "(";
								String singo2 = ")";
								String usryemail = encontreSessionUsuario.get().getUsr().concat(" ").concat(singo1)
										.concat(encontreSessionUsuario.get().getEmail().concat(singo2));
								auditDto.setUserref(usryemail);
								auditDto.setModule(module);
								auditDto.setDesc(Descmodule);
								auditDto.setCreatedat(fechaDate2);
								usersService.registrarAuditSesion(auditDto);

								RespuestaValueDto respuestaValueDto = new RespuestaValueDto(position2.getId());
								URI location = URI.create("/positions/" + position2.getId()); // O la URL correcta
																								// para // tu
																								// recurso
								return ResponseEntity.created(location).body(respuestaValueDto);
							} else {
								respuesta.setMsg("No se pudo actualizar por alguna razón");
								estatus = HttpStatus.CONFLICT;
								return new ResponseEntity(respuesta, estatus);
							}
						} catch (Exception e) {
							respuesta.setMsg("Error interno.  Descripción del error" + e.getMessage());
							estatus = HttpStatus.INTERNAL_SERVER_ERROR;
							return new ResponseEntity(respuesta, estatus);
						}
						finally {
							if (entityManager != null && entityManager.isOpen()) {
								entityManager.close();
							}
						}

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

			return new ResponseEntity(respuesta, HttpStatus.OK);

		}
	}

	@DeleteMapping("/positions/{positionid}")
	public ResponseEntity<?> borrarPositions(HttpServletRequest request,
			@PathVariable("positionid") final Integer positionid) throws ParseException {

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

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

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

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

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

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

			Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(sessionid);
			if (encontreSessionUsuario.isPresent()) { // si la sesión del usuario existe
				Date FechaReg = encontreSessionUsuario.get().getValidthru();
				// Llamada a la funcion que validad el tiempo de Session, retorna la fecha
				// sumandole el tiempo de session activa, y vacio si no esta activa
				fechaComoCadena = securityService.consultarSessionActiva(FechaReg, fecha2,
						encontreSessionUsuario.get().getId());
				if (fechaComoCadena == "") {
					RespuestaMsgDto respuestaDto2;
					String var2 = "";
					boolean bloked2 = false;
					respuestaDto2 = new RespuestaMsgDto(var2);
					respuestaDto2.setMsg("Sesión expirada o inválida");
					return new ResponseEntity(respuestaDto2, HttpStatus.UNAUTHORIZED);
				}

				int rolisvalid = 0;

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

					// Verifico si existe el id de cargo en la base de datos probando
					Optional<Positions> obtpositions = positionsRepository.findById(positionid);
					Positions positions = new Positions();
					// Verifico si encontre el proceso
					if (obtpositions != null) {
						positions = obtpositions.get();
					} else {
						respuesta.setMsg("Registro no encontrado");
						return new ResponseEntity(respuesta, HttpStatus.NOT_FOUND);
					}
					/// validar extra ahora por el positionunits y verificar si algun empleado tiene positionunitid 
					
				//	if (positionsRepository.getCountEmpleados(positionid)>0) {
				//		respuesta.setMsg("No se pudo borrar debido a que está asociado a empleados");
				//		estatus = HttpStatus.CONFLICT;
				//		return new ResponseEntity(respuesta, estatus);
			//		}
					
					/*if (positionsRepository.getCountPrositionsUnits(positionid)>0) {
						respuesta.setMsg("No se pudo borrar debido a que está asociado a unidades");
						estatus = HttpStatus.CONFLICT;
						return new ResponseEntity(respuesta, estatus);
					}*/
					
					
					
					if (positionsRepository.getCountEvalunitpos(positionid)>0) {   // este no depende del positionunitsid
						respuesta.setMsg("No se pudo borrar debido a que está asociado a evaluación de unidades");
						estatus = HttpStatus.CONFLICT;
						return new ResponseEntity(respuesta, estatus);
					}
					
					try {
						// Se borra la relación de unidades y cargos
						if (positionunitsRepository.existsByPositionid(positionid)) {
							positionunitsRepository.borrarPositionunits(positionid);

							positionsRepository.borrarPositions(positionid);
							module = "Cargos";
							Descmodule = "Se borró el cargo: " + positions.getName() + " con id: "+positions.getId();
							auditDto.setIpaddr(HttpReqRespUtils.getClientIpAddressIfServletRequestExist());
							String singo1 = "(";
							String singo2 = ")";
							String usryemail = encontreSessionUsuario.get().getUsr().concat(" ").concat(singo1)
									.concat(encontreSessionUsuario.get().getEmail().concat(singo2));
							auditDto.setUserref(usryemail);
							auditDto.setModule(module);
							auditDto.setDesc(Descmodule);
							auditDto.setCreatedat(fechaDate2);
							usersService.registrarAuditSesion(auditDto);

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

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

			}

			return new ResponseEntity(respuesta, HttpStatus.OK);

		}

	}
}