package com.dacrt.SBIABackend.controler;

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

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

import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.dacrt.SBIABackend.dto.AppPruebasResponseDto;
import com.dacrt.SBIABackend.dto.AppTypeDto;
import com.dacrt.SBIABackend.dto.AppcoveragedrpContentDto;
import com.dacrt.SBIABackend.dto.AppcoveragedrpFilterDto;
import com.dacrt.SBIABackend.dto.AppcoveragedrpHeaderDto;
import com.dacrt.SBIABackend.dto.AppcoveragedrpValueDto;
import com.dacrt.SBIABackend.dto.ApplicationDto;
import com.dacrt.SBIABackend.dto.ApplicationDto2;
import com.dacrt.SBIABackend.dto.ApplicationResponseDto2;
import com.dacrt.SBIABackend.dto.ApppruebasHeaderDto;
import com.dacrt.SBIABackend.dto.AppstrategyHeaderDto;
import com.dacrt.SBIABackend.dto.AppstrategyResponseDto;
import com.dacrt.SBIABackend.dto.CampaignFormat2Dto;
import com.dacrt.SBIABackend.dto.ContentDto;
import com.dacrt.SBIABackend.dto.DrptesttypesDto;
import com.dacrt.SBIABackend.dto.FacilityDto2;
import com.dacrt.SBIABackend.dto.FiltersResponseDto;
import com.dacrt.SBIABackend.dto.RecordCatalogoResponseDto;
import com.dacrt.SBIABackend.dto.StatusDto;
import com.dacrt.SBIABackend.dto.TestStatusResquestDto;
import com.dacrt.SBIABackend.dto.TestTypeResquestDto;
import com.dacrt.SBIABackend.dto.TypesUnitDto;
import com.dacrt.SBIABackend.dto.ValueDto;
import com.dacrt.SBIABackend.dto.responseDto.AppcoveragedrpResponseDto;
import com.dacrt.SBIABackend.dto.responseDto.ApplicationResponseDto;
import com.dacrt.SBIABackend.repository.ApplicationsRepository;
import com.dacrt.SBIABackend.repository.FacilitiesRepository;
import com.dacrt.SBIABackend.repository.SuppliersRepository;
import com.dacrt.SBIABackend.security.dto.AuditRequestDto;
import com.dacrt.SBIABackend.security.dto.PrivilegesAllDto;
import com.dacrt.SBIABackend.security.dto.RespuestaDto;
import com.dacrt.SBIABackend.security.dto.RespuestaMsgDto;
import com.dacrt.SBIABackend.security.entity.Roles;
import com.dacrt.SBIABackend.security.entity.Users;
import com.dacrt.SBIABackend.security.repository.AuditRepository;
import com.dacrt.SBIABackend.security.repository.ParamsRepository;
import com.dacrt.SBIABackend.security.repository.RolesPrivilegesRepository;
import com.dacrt.SBIABackend.security.repository.UsersRepository;
import com.dacrt.SBIABackend.security.service.MenuService;
import com.dacrt.SBIABackend.security.service.ParamsService;
import com.dacrt.SBIABackend.security.service.SecurityService;
import com.dacrt.SBIABackend.security.service.UsersService;

@RestController
@CrossOrigin(origins = "*")
public class TeststatusController {
	@Autowired
	private ParamsRepository paramsRepository;

	@Autowired
	private UsersRepository usersRepository;

	@Autowired
	private AuditRepository auditRepository;

	@Autowired
	private RolesPrivilegesRepository rolesPrivilegesRepository;

	@Autowired
	UsersService usersService;

	@Autowired
	ParamsService paramsService;

	@Autowired
	SecurityService securityService;

	@Autowired
	MenuService menuService;

	@PersistenceContext
	private EntityManager entityManager;

	@Autowired
	SuppliersRepository suppliersRepository;

	@Autowired
	ApplicationsRepository applicationsRepository;

	@Autowired
	FacilitiesRepository facilitiesRepository;

	@PostMapping("/dashboard/teststatus")
	public ResponseEntity<?> applications(HttpServletRequest request, @RequestBody TestStatusResquestDto tiposfiltros)
			throws ParseException {
		RespuestaDto respuesta = new RespuestaDto("", false);
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		AppcoveragedrpValueDto appcoveragedrpValueDto = new AppcoveragedrpValueDto();
		AppcoveragedrpFilterDto appcoveragedrpFilterDto = new AppcoveragedrpFilterDto();
		AppcoveragedrpHeaderDto appcoveragedrpHeaderDto = new AppcoveragedrpHeaderDto();
		AppcoveragedrpContentDto appcoveragedrpContentDto = new AppcoveragedrpContentDto();
		AppcoveragedrpResponseDto appcoveragedrpResponseDto = new AppcoveragedrpResponseDto();

		// ParamsDto detalleParams;
		ApplicationDto detalleApplication;
		ApplicationDto2 detalleApplication2;
		StatusDto detalleStatus;
		PrivilegesAllDto detallePrivilege;
		FacilityDto2 detallefacility;
		Long cuantosregistro = (long) 0;
		CampaignFormat2Dto detalleCompaing2;

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

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

		int idrol;
		String drptestyesnoparSearch = "";
		String apptypeSearch = "";
		String contentIn = "";
		int searchStatus = 0;

		int Inunit;
		String apptypeIn = "";
		String testtypeIn = "";

		int RtoMinutes;
		String fechaComoCadena;
		int orderIn = 0;
		int offsetIn = 0;
		int numofrecordsIn = 0;
		Date fecha2 = new Date();
		int iduser;
		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();
				iduser = encontreSessionUsuario.get().getId();
				// 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);

				}

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

				}

				Inunit = tiposfiltros.getUnits();

				switch (Inunit) {
				case 0: // viene sin busqueda por el like
					String mensaje = "ok";
					break;

				case 1: // viene sin busqueda por el like
					String mensaje2 = "ok";
					break;
				default:
					String var2 = "";
					boolean bloked = false;
					RespuestaMsgDto respuestaDto = new RespuestaMsgDto(var2);
					respuestaDto = new RespuestaMsgDto(
							"Llamada al servicio malformado- valor no permitido para la Unidad");
					estatus = HttpStatus.BAD_REQUEST;
					return new ResponseEntity(respuestaDto, estatus);

				}

				apptypeIn = tiposfiltros.getApptype();
				testtypeIn = tiposfiltros.getTesttype();

			} 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 SentenciaBaseIn1 = "";
			String QueryTotal = "";
			Query query;
			Query query2;
			Query query3;
			Query query4;
			Query query5;
			Query query6;
			String tipoTest;
			String filtro="";
			String InUnidades = " INNER JOIN main.unitprocesses up ON ep.unitprocessid = up.id   ";
			String filtroUnit = " INNER JOIN main.userunits uu ON up.unitid = uu.unitid AND uu.userid = " + iduser;
			String filtroType = "";
			if (Inunit == 0) {
				filtro = InUnidades;
			} else {
				filtro = InUnidades + filtroUnit;
			}

			switch (testtypeIn) {
				case "":
					//filtroType = " AND aplicaciones.drptesttypepar IN (2) ";
					filtroType = " ";
					break;
	
				default: // viene con el parametro para buscar por el like
					filtroType = " AND aplicaciones.drptesttypepar in  (" + testtypeIn + ") ";
					break;
			}

			SentenciaBaseIn1 = " SELECT "
					+ "					     SUM(CASE WHEN (aplicaciones.drptestresultpar = 1  "+ filtroType +" ) THEN 1 ELSE 0 END) AS exitoso,   "
					+ "    CASE  "
					+ "					 		 WHEN ROUND(CAST(SUM(CASE WHEN (aplicaciones.drptestresultpar = 1 "+ filtroType +" ) THEN 1 ELSE 0 END) * 100 AS NUMERIC) / NULLIF(COUNT(*), 0), 2) is null THEN 0.00   "
					+ "					 		 ELSE ROUND(CAST(SUM(CASE WHEN (aplicaciones.drptestresultpar = 1 "+ filtroType +") THEN 1 ELSE 0 END) * 100 AS NUMERIC) / NULLIF(COUNT(*), 0), 2)   "
					+ "	   END	AS porc_exitoso, "
					+ "					     SUM(CASE WHEN (aplicaciones.drptestresultpar = 2 "+ filtroType +" ) THEN 1 ELSE 0 END) AS parcial,   "
					+ "	   CASE  "
					+ "					 		 WHEN ROUND(CAST(SUM(CASE WHEN (aplicaciones.drptestresultpar = 2 "+ filtroType +" ) THEN 1 ELSE 0 END) * 100 AS NUMERIC) / NULLIF(COUNT(*), 0), 2) is null THEN 0.00   "
					+ "					 		 ELSE ROUND(CAST(SUM(CASE WHEN (aplicaciones.drptestresultpar = 2 "+ filtroType +") THEN 1 ELSE 0 END) * 100 AS NUMERIC) / NULLIF(COUNT(*), 0), 2)   "
					+ "	   END	AS porc_parcial, "
					+ "					     SUM(CASE WHEN (aplicaciones.drptestresultpar = 3 "+ filtroType +") THEN 1 ELSE 0 END) AS fallido,   "
					+ "	   CASE  "
					+ "					 		 WHEN ROUND(CAST(SUM(CASE WHEN (aplicaciones.drptestresultpar = 3 "+ filtroType +") THEN 1 ELSE 0 END) * 100 AS NUMERIC) / NULLIF(COUNT(*), 0), 2) is null THEN 0.00   "
					+ "					 		 ELSE ROUND(CAST(SUM(CASE WHEN (aplicaciones.drptestresultpar = 3 "+ filtroType +") THEN 1 ELSE 0 END) * 100 AS NUMERIC) / NULLIF(COUNT(*), 0), 2)   "
					+ "	   END	AS porc_fallido, "
					+ "					     SUM(CASE WHEN (aplicaciones.drptestedpar = 2) THEN 1 ELSE 0 END) AS sinpruebas,   "
					+ "	   CASE  "
					+ "					 		 WHEN ROUND(CAST(SUM(CASE WHEN (aplicaciones.drptestedpar = 2) THEN 1 ELSE 0 END) * 100 AS NUMERIC) / NULLIF(COUNT(*), 0), 2) is null THEN 0.00   "
					+ "					 		 ELSE ROUND(CAST(SUM(CASE WHEN (aplicaciones.drptestedpar = 2) THEN 1 ELSE 0 END) * 100 AS NUMERIC) / NULLIF(COUNT(*), 0), 2)   "
					+ "	   END	AS porc_sinpruebase "
					+ "					 FROM (   "
					+ "					     SELECT  a.id,   "
					+ "        a.name, "
					+ "        a.drptesttypepar, "
					+ "        a.drptestedpar, "
					+ "					         a.apptypepar, "
					+ "							 a.drptestresultpar "
					+ "					     FROM   main.applications a   "
					+ "					     INNER JOIN   main.evalprocapps ea ON ea.applicationid = a.id   "
					+ "					     INNER JOIN   main.evalprocimpacts ei ON ea.evalprocessid = ei.evalprocessid   "
					+ "					     INNER JOIN   main.evalprocesses ep ON ea.evalprocessid = ep.id   "
					+ filtro
					+ "					     WHERE        a.status = 1 AND ep.impactst = 1 AND ep.appst = 1   "
					+ "					     GROUP BY     a.id, a.name   "
					+ "					     ORDER BY     a.id   "
					+ "					 ) AS aplicaciones ";

			
			
			
			switch (apptypeIn) {
			case "":
				QueryTotal = SentenciaBaseIn1 + " WHERE TRUE = TRUE ";
				break;

			default: // viene con el parametro para buscar por el like
				QueryTotal = SentenciaBaseIn1 + " WHERE CAST(aplicaciones.apptypepar AS INTEGER)=  " + apptypeIn;
			}

			switch (testtypeIn) {
			case "":
				QueryTotal = QueryTotal + " AND  aplicaciones.drptesttypepar in (1,2,3) or aplicaciones.drptestedpar=2  ";
				break;

			default: // viene con el parametro para buscar por el like
				QueryTotal = QueryTotal + " AND aplicaciones.drptesttypepar in  (" + testtypeIn + ")  or aplicaciones.drptestedpar=2 ";
			}

			query = entityManager.createNativeQuery(QueryTotal);
			List<Object[]> listacompleta = query.getResultList();

			List<ContentDto> listasContent = new ArrayList<>();
			AppPruebasResponseDto appPruebasResponseDto = new AppPruebasResponseDto();
			ApppruebasHeaderDto ApppruebasHeaderDto = new ApppruebasHeaderDto(
					"Aplicaciones con Pruebas DRP que poseen BIA");
			FiltersResponseDto filtersResponseDto = new FiltersResponseDto();
			List<FiltersResponseDto> filters = new ArrayList<>();

			Object[] filas = (Object[]) query.getSingleResult();
			ValueDto valueDto = new ValueDto();
			ValueDto valueDto2 = new ValueDto();
			ValueDto valueDto3 = new ValueDto();
			ValueDto valueDto4 = new ValueDto();
			ContentDto contentDto = new ContentDto();
			ContentDto contentDto2 = new ContentDto();
			ContentDto contentDto3 = new ContentDto();
			ContentDto contentDto4 = new ContentDto();

			int cuantosregistros = listacompleta.size();
			
			String SentenciaBaseIn4 ="select count(1) from     (select count(applicationid)  from main.evalprocapps ea "
					+ "    inner join main.evalprocesses ep ON ep.id = ea.evalprocessid and ep.impactst = 1  AND ep.appst = 1  "
					+ "    where ea.applicationid in  (select id from main.applications s where s.status =1 )  "
					+ "    group by applicationid) as a";
			query5 = entityManager.createNativeQuery(SentenciaBaseIn4);
			BigInteger countResult1 = (BigInteger) query5.getSingleResult();
			
			String SentenciaBaseIn5 ="select count(1) from     (select count(applicationid)  from main.evalprocapps ea "
					+ "    inner join main.evalprocesses ep ON ep.id = ea.evalprocessid and ep.impactst = 1  AND ep.appst = 1  "
					+ "    where ea.applicationid in  (select id from main.applications s where s.status =1 and s.drptestedpar=1 )  "
					+ "    group by applicationid) as a";
			
			query6 = entityManager.createNativeQuery(SentenciaBaseIn5);
			BigInteger countResult2 = (BigInteger) query6.getSingleResult();
			
			// cuantosregistros = 0;
			if (cuantosregistros > 0) {
				contentDto.setName("Fallidas");
				valueDto.setPercent(filas[5]==null?"0.00%":filas[5].toString()+"%");
				valueDto.setNumber(filas[4]==null?new BigDecimal(0):new BigDecimal((BigInteger) filas[4]));
				contentDto.setValue(valueDto);
				listasContent.add(contentDto);

				contentDto2.setName("Parciales");
				valueDto2.setPercent(filas[3]==null?"0.00%":filas[3].toString()+"%");
				valueDto2.setNumber(filas[2]==null?new BigDecimal(0):new BigDecimal((BigInteger) filas[2]));
				contentDto2.setValue(valueDto2);
				listasContent.add(contentDto2);

				contentDto3.setName("Exitosas");
				valueDto3.setPercent(filas[1]==null?"0.00%":filas[1].toString()+"%");
				valueDto3.setNumber(filas[0]==null?new BigDecimal(0):new BigDecimal((BigInteger) filas[0]));
				contentDto3.setValue(valueDto3);
				listasContent.add(contentDto3);

				contentDto4.setName("Sin Pruebas");
				valueDto4.setPercent(filas[7]==null?"0.00%":filas[7].toString()+"%");
				valueDto4.setNumber(filas[6]==null?new BigDecimal(0):new BigDecimal((BigInteger) filas[6]));
				contentDto4.setValue(valueDto4);
				listasContent.add(contentDto4);

				appPruebasResponseDto.setHeader(ApppruebasHeaderDto);
				appPruebasResponseDto.setTotalapev(countResult1);
				appPruebasResponseDto.setTotalapevpru(countResult2);
				appPruebasResponseDto.setContent(listasContent);

			} else {
				contentDto.setName("Fallidas");
				valueDto.setPercent("0.00%");
				valueDto.setNumber(new BigDecimal(0));
				contentDto.setValue(valueDto);
				listasContent.add(contentDto);

				contentDto2.setName("Parciales");
				valueDto2.setPercent("0.00%");
				valueDto2.setNumber(new BigDecimal(0));
				contentDto2.setValue(valueDto2);
				listasContent.add(contentDto2);

				contentDto3.setName("Exitosas");
				valueDto3.setPercent("0.00%");
				valueDto3.setNumber(new BigDecimal(0));
				contentDto3.setValue(valueDto3);
				listasContent.add(contentDto3);

				contentDto4.setName("Sin Pruebas");
				valueDto4.setPercent("0.00%");
				valueDto4.setNumber(new BigDecimal(0));
				contentDto4.setValue(valueDto4);
				listasContent.add(contentDto4);

				appPruebasResponseDto.setHeader(ApppruebasHeaderDto);
				appPruebasResponseDto.setTotalapev(BigInteger.ZERO);
				appPruebasResponseDto.setTotalapevpru(BigInteger.ZERO);
				appPruebasResponseDto.setContent(listasContent);
			}

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

			query3 = entityManager.createNativeQuery(QueryTypes);
			List<Object[]> resultadosTypes;
			List<AppTypeDto> apptypes = new ArrayList();
			AppTypeDto appTypeDto = new AppTypeDto();
			resultadosTypes = query3.getResultList();
			JSONObject jsonObject;
			String jsonStringTipo = "";
			if (resultadosTypes.size() > 0) {
				for (Object tipos : resultadosTypes) {
					jsonStringTipo = (String) tipos; // Recupera el JSON como String
					jsonObject = new JSONObject(jsonStringTipo); // Convierte String a JSONObject
					// Extrae los valores del JSONObject
					String dsc = jsonObject.getString("dsc");
					String value = jsonObject.getString("value");

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

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

			query4 = entityManager.createNativeQuery(QueryDRP);
			List<Object[]> resultadosDRP;
			DrptesttypesDto drptesttypesDto = new DrptesttypesDto();
			List<DrptesttypesDto> drptesttypes = new ArrayList();
			resultadosDRP = query4.getResultList();
			if (resultadosTypes.size() > 0) {
				for (Object tipos : resultadosDRP) {
					jsonStringTipo = (String) tipos; // Recupera el JSON como String
					jsonObject = new JSONObject(jsonStringTipo); // Convierte String a JSONObject
					// Extrae los valores del JSONObject
					String dsc = jsonObject.getString("dsc");
					String value = jsonObject.getString("value");

					drptesttypesDto.setId(Integer.parseInt(value));
					drptesttypesDto.setName(dsc);
					drptesttypes.add(drptesttypesDto);
					drptesttypesDto = new DrptesttypesDto();
				}
			}

			filtersResponseDto.setApptypes(apptypes);
			filtersResponseDto.setDrptesttypes(drptesttypes);
			appPruebasResponseDto.setFilters(filtersResponseDto);

			return ResponseEntity.ok(appPruebasResponseDto);

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

		return new ResponseEntity(respuesta, estatus);

	}
}
