package com.dacrt.SBIABackend.security.service;

import java.io.File;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;

import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import java.util.Optional;

import javax.persistence.Column;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.transaction.Transactional;
import javax.validation.constraints.NotNull;

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.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.NonNull;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;

import com.dacrt.SBIABackend.dto.Mensaje;
import com.dacrt.SBIABackend.dto.SuppliersDtoStatus;
//import com.dacrt.SBIABackend.security.dto.DetalleUsuarioRequestDto;
import com.dacrt.SBIABackend.security.dto.MenuDto;
import com.dacrt.SBIABackend.security.dto.MenuDto3;
import com.dacrt.SBIABackend.security.dto.AccessDto;
import com.dacrt.SBIABackend.security.dto.AccessDto2;
import com.dacrt.SBIABackend.security.dto.MenuResponseDto;
import com.dacrt.SBIABackend.security.dto.ParamsDto;
import com.dacrt.SBIABackend.security.dto.PrivilegeUniqueResponseDto;
import com.dacrt.SBIABackend.security.dto.RespuestaDto;
import com.dacrt.SBIABackend.security.dto.RolesAssignedResponseDto;
import com.dacrt.SBIABackend.security.dto.ShortcutsDto;
import com.dacrt.SBIABackend.security.dto.UsersDto;
import com.dacrt.SBIABackend.security.dto.UsersResponseDto;
import com.dacrt.SBIABackend.security.entity.Users;
import com.dacrt.SBIABackend.security.entity.Menu;
import com.dacrt.SBIABackend.security.entity.Params;
import com.dacrt.SBIABackend.security.entity.Roles;
import com.dacrt.SBIABackend.security.entity.Access;
import com.dacrt.SBIABackend.security.entity.Audit;
import com.dacrt.SBIABackend.security.repository.UsersRepository;
import com.dacrt.SBIABackend.security.repository.AuditRepository;
import com.dacrt.SBIABackend.security.repository.MenuRepository;
import com.dacrt.SBIABackend.security.repository.ParamsRepository;
import com.dacrt.SBIABackend.security.repository.AccessRepository;

@Service
@Transactional
public class MenuService {
	private static final Integer Integer = null;

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

	private final Set<Integer> processedMenuIds = new HashSet<>();

	@Autowired
	MenuRepository menuRepository;

	@Autowired
	AuditRepository auditRepository;

	@Autowired
	UsersRepository usersRepository;

	@Autowired
	ParamsRepository paramsRepository;

	@Autowired
	AccessRepository accessRepository;

	@PersistenceContext
	private EntityManager entityManager;

	@Value("${var.ambiente}")
	private String urlAmbiente;

	@Value("${ambiente}")
	private String ambiente;

	@Value("${imagepath}")
	private String imagepath;

	@Value("${principal}")
	private String principal;

	@Value("${imagen}")
	private String imagen;

	@Value("${carpeta}")
	private String carpeta;

	@Value("${shorcuts}")
	private String shorcuts;
	// @Autowired
	// private RestTemplate restTemplate;

	// @Autowired
//	private VistaUsuariosAllRepository vistaUsuariosAllRepository;

	@Autowired
	PasswordEncoder passworEncoder;

	public List<Menu> getAllMenu() {
		return menuRepository.findAll();
	}

	public boolean existsByUsr(String usr) {
		return usersRepository.existsByUsr(usr);
	}

	public boolean existsByEmail(String email) {
		return usersRepository.existsByEmail(email);
	}

	public boolean consultarSesionEstatus(Integer id) {
		boolean resp = false;
		int resp1 = usersRepository.consultarSesionEstatus(id);
		// Optional<UsuarioSesion> usuarioTo =
		// usuarioSesionRepository.consultarSesionActiva(idUsuario);
		// if(!usuarioTo.isEmpty())resp=true;
		// if(usuarioTo!=null)resp=true;
		// if(usuarioTo.size()>0)resp=true;
		if (resp1 == 1) {
			resp = true;
		} else {
			resp = false;
		}
		return resp;

	}

	public List<MenuDto> buildMenuDto2(int father, String sessionid) {
		String SentenciaBase = "";
		Query query;
		RespuestaDto respuesta = new RespuestaDto("", false);
		MenuDto menuDto2 = new MenuDto();
		List<MenuDto> menus = new ArrayList();
		List<Object[]> resultados = new ArrayList();
		HttpStatus estatus = HttpStatus.FORBIDDEN;
		String svg = ".svg";
		/*
		 * String png = ".png"; String jpeg = ".jpeg"; String jpg = ".jpg";
		 */

		String idcampo = "img/menu/";
		String ConcatAmbiente = urlAmbiente.concat(idcampo);
		String ruta = ConcatAmbiente;

		String filePath;
		boolean existe = false;
		// int responseCode = 0;
		// int tiene;
		// Optional<Users> encontreSessionUsuario;

		/*
		 * int permiso; Roles roles; int idrol; int rolisvalid;
		 */
		try {
			// ES UN PADRE
			if (father == 0) {
				/*
				 * SentenciaBase=
				 * "SELECT     m.id,m.dsc,m.content,m.father, CASE WHEN m.privilegeid=0 THEN TRUE ELSE FALSE END AS acc "
				 * + "FROM       main.menu m " + "LEFT JOIN  main.rolesprivileges RP "+
				 * "ON         m.privilegeid=RP.privilegeid "+
				 * "LEFT JOIN  (SELECT rolid FROM main.users WHERE sessionid=:sessionid) U "+
				 * "ON         RP.id=U.rolid "+ "WHERE      m.id<>0 "+
				 * "AND        m.father IS NULL "+ "order by   m.father ";
				 */
				SentenciaBase = "SELECT      m.id,m.dsc,m.content,m.father, CASE WHEN m.privilegeid=0 THEN TRUE ELSE FALSE END AS acc "
						+ "FROM       main.menu m " + "LEFT JOIN       (SELECT     privilegeid "
						+ "                 FROM       main.rolesprivileges RP "
						+ "                 INNER JOIN main.users U " + "                 ON         RP.rolid=U.rolid "
						+ "                 WHERE sessionid=:sessionid ) RP "
						+ "ON         m.privilegeid=RP.privilegeid " + "WHERE      m.id<>0 "
						+ "AND        m.father IS NULL " + "order by   m.father,m.ord ";

				// SentenciaBase = "SELECT m FROM Menu m WHERE m.id<>0 AND m.father IS NULL
				// order by m.ord";
				// query = entityManager.createQuery(SentenciaBase, Menu.class);
				query = entityManager.createNativeQuery(SentenciaBase);
				query.setParameter("sessionid", sessionid);
			} else {
				// HIJOS
				SentenciaBase = "SELECT     m.id,m.dsc,m.content,m.father, CASE WHEN RP.privilegeid IS NULL THEN FALSE ELSE TRUE END AS acc "
						+ "FROM       main.menu m " + "LEFT JOIN       (SELECT     privilegeid "
						+ "                 FROM       main.rolesprivileges RP "
						+ "                 INNER JOIN main.users U " + "                 ON         RP.rolid=U.rolid "
						+ "                 WHERE sessionid=:sessionid ) RP "
						+ "ON         m.privilegeid=RP.privilegeid " + "WHERE      m.id<>0 "
						+ "AND        m.father=:father " + "order by   m.ord asc";
				// SentenciaBase = "SELECT m FROM Menu m WHERE m.id<>0 AND m.father.id=:father
				// order by m.ord";
				// query = entityManager.createQuery(SentenciaBase, Menu.class);
				query = entityManager.createNativeQuery(SentenciaBase);
				query.setParameter("sessionid", sessionid);
				query.setParameter("father", father); // Correcto
			}

			resultados = query.getResultList();
			// System.out.println(SentenciaBase);
			String ruta_completa;
			File archivo;
			int idMenu = 0;
			if (resultados.size() != 0) {
				for (Object[] fila : resultados) {
					menuDto2.setId((int) fila[0]);
					menuDto2.setDsc((String) fila[1]);
					menuDto2.setContent((String) fila[2]);
					ruta_completa = ruta.concat(String.valueOf((int) fila[0])).concat(svg);
					
					
					if (ambiente.equals("/")) {
						
						  filePath = imagepath  + "/" + imagen + carpeta + menuDto2.getId() + svg;
								
						}
						else {
							filePath = imagepath + "/" + principal + "/" + ambiente + imagen + carpeta + menuDto2.getId() + svg;
						}

					archivo = new File(filePath);

					if (archivo.exists()) {
						menuDto2.setImage(ruta_completa);
					} else {
						menuDto2.setImage(null);
					}

					/*
					 * try { URL url = new URL(filePath); HttpURLConnection huc =
					 * (HttpURLConnection) url.openConnection(); // InputStream isd =
					 * url.openStream(); responseCode = huc.getResponseCode(); if (responseCode ==
					 * 200) { menuDto2.setImage(filePath); } else { menuDto2.setImage(null); }
					 * 
					 * // System.out.println("Abierto"); } catch (Exception e) { //
					 * System.out.println("cerrado"); menuDto2.setImage(null); }
					 */

					// tiene = responseCode;

					/*
					 * encontreSessionUsuario = usersRepository.getBySessionid(sessionid); permiso =
					 * menu.getPrivilegeid(); roles = encontreSessionUsuario.get().getRolid(); idrol
					 * = roles.getId(); rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol,
					 * permiso); if (permiso == 0) { menuDto2.setEnabled(true);
					 * 
					 * } else {
					 * 
					 * if (rolisvalid == 0) { menuDto2.setEnabled(false);
					 * 
					 * } else { menuDto2.setEnabled(true);
					 * 
					 * } } rolisvalid = 0;
					 */
					menuDto2.setEnabled((boolean) fila[4]);

					// resultados2 = query2.getResultList();
					menuDto2.setSubmenu(buildMenuDto2(menuDto2.getId(), sessionid));
					menus.add(menuDto2);
					menuDto2 = new MenuDto();
				}
			}
		} catch (Exception e) {
			respuesta = new RespuestaDto("Error interno del servidor", false);
			estatus = HttpStatus.INTERNAL_SERVER_ERROR;
		} finally {
			if (entityManager != null && entityManager.isOpen()) {
				entityManager.close();
			}
		}
		return menus;
	}

	public List<MenuDto> buildMenuDto(List<Menu> menuEntities, String sessionid) {
		processedMenuIds.clear();
		// return
		// menuEntities.stream().map(this::mapMenuEntityToDto()).collect(Collectors.toList());
		return menuEntities.stream().map(menuEntity -> mapMenuEntityToDto(menuEntity, sessionid))
				.collect(Collectors.toList());
	}

	private MenuDto mapMenuEntityToDto(Menu menuEntity, String sessionid) {
		// private MenuDto mapMenuEntityToDto(Menu menuEntity) {
		// obtiene los Men� Procesados
		if (processedMenuIds.contains(menuEntity.getId())) {
			return new MenuDto();
		}

		// Sino est� procesado lo agrego
		processedMenuIds.add(menuEntity.getId());

		String svg = ".svg";
		String png = ".png";
		String jpeg = ".jpeg";
		String jpg = ".jpg";

		// Construyo el Men�
		MenuDto menuDto = new MenuDto();
		menuDto.setId(menuEntity.getId());
		menuDto.setDsc(menuEntity.getDsc());

		// String ruta=
		// "https://vpskromasys2.hostnetcom.com/~daconsult/dev/img/menu/1.txt";
		// String ruta = "C:\Users\JAVIER SERRANO\bia\BACKEND.txt";
		String idcampo = "img/menu/";
		String ConcatAmbiente = urlAmbiente.concat(idcampo);
		String ruta = ConcatAmbiente;

		// String ruta= "http://vpskromasys2.hostnetcom.com/~daconsult/dev/img/menu/";
		String filePath = ruta.concat(String.valueOf(menuEntity.getId())).concat(svg);
		boolean existe = false;
		int responseCode = 0;
		try {
			URL url = new URL(filePath);
			HttpURLConnection huc = (HttpURLConnection) url.openConnection();
			// InputStream isd = url.openStream();
			responseCode = huc.getResponseCode();
			if (responseCode == 200) {
				menuDto.setImage(filePath);
			} else {
				menuDto.setImage(null);
			}

			// System.out.println("Abierto");
		} catch (Exception e) {
			// System.out.println("cerrado");
			menuDto.setImage(null);
		}

		int tiene = responseCode;

		// int rolid =usersRepository.getRolbySessionid(sessionid);
		Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(sessionid);
		// Roles roles = rolid;
		// String query = "SELECT u.rolid FROM Users u WHERE u.rolid = " + rolid;
		// TypedQuery<Integer> params= entityManager.createQuery(query, Integer.class);

		// List<Integer> listacompleta = params.getResultList();
		// int rolidw = listacompleta.get(0);

		int permiso = menuEntity.getPrivilegeid();
		Roles roles = encontreSessionUsuario.get().getRolid();
		int idrol = roles.getId();
		int rolisvalid = auditRepository.getCantbyRolAndPrivi(idrol, permiso);

		if (permiso == 0) {
			menuDto.setEnabled(true);

		} else {

			if (rolisvalid == 0) {
				menuDto.setEnabled(false);

			} else {
				menuDto.setEnabled(true);

			}
		}
		rolisvalid = 0;

		menuDto.setContent(menuEntity.getContent());
		List<Menu> currentMenu = new ArrayList();
		// Verifico si el submenu no esta vacio
		if (!menuEntity.getSubmenus().isEmpty()) {
			List<MenuDto> submenus = menuEntity.getSubmenus().stream()
					// .map(this::mapMenuEntityToDto)
					.map(submenuEntity -> mapMenuEntityToDto(submenuEntity, sessionid)).collect(Collectors.toList());
			menuDto.setSubmenu(submenus);
		} else {
			// Si el menu es vac�o asigno vac�o
			List<MenuDto> submenus = new ArrayList();
			menuDto.setSubmenu(submenus);
		}

		return menuDto;
	}

	public MenuResponseDto getMenu(String sessionid) {
		// Construyo el men� de Respuesta
		MenuResponseDto menuDto = new MenuResponseDto();
		RespuestaDto respuesta = new RespuestaDto("", false);
		ShortcutsDto shorcutsdto = new ShortcutsDto();
		ShortcutsDto detalleShortcuts;
		List<ShortcutsDto> listashortcuts = new ArrayList<>();
		// Access accessDto = new Access();
		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);

		// Busco el usuario dependiendo de la sesi�n del usuario
		Optional<Users> encontreSessionUsuario = usersRepository.getBySessionid(sessionid);

		if (encontreSessionUsuario.isPresent()) {
			UsersResponseDto usuario = new UsersResponseDto();
			Optional<Menu> menushort;
			usuario.setName(encontreSessionUsuario.get().getName());
			int iduser = encontreSessionUsuario.get().getId();
			String idcampo = "img/logo.png";
			String ConcatAmbiente = urlAmbiente.concat(idcampo);
			String ruta = ConcatAmbiente;
			// String ruta=
			// "http://vpskromasys2.hostnetcom.com/~daconsult/dev/img/logo.png";
			String desPadre = "";
			String desContentPadre = "";
			// Seteo el menu
			menuDto.setUser(usuario);
			// menuDto.setValidthru(ValidThrufechaSalida);
			menuDto.setValidthru(fechaComoCadena);

			// Menu valormenu = new Menu();
			// List<Access> accessDto =
			// accessRepository.getAllAccessxUser(encontreSessionUsuario.get().getId());
			List<String> accessDtoString = accessRepository.getAllAccessxUserMax(encontreSessionUsuario.get().getId());
			// String SentenciaBase = "SELECT new
			// com.dacrt.SBIABackend.security.dto.ParamsDto (u.id,
			// u.paramname,u.group,u.name,u.type,u.value,u.info,u.modifiedat) FROM Params
			// u";
			// SELECT a.userid,a.content,max(a.id) as id from main.access a WHERE a.userid =
			// ?1 GROUP BY a.userid,a.content ORDER BY id desc
			// String SentenciaBase = "SELECT new
			// com.dacrt.SBIABackend.security.dto.AccessDto2 (a.content,a.userid,max(a.id)
			// as id) FROM Access a WHERE a.userid =" + encontreSessionUsuario.get().getId()
			// + " GROUP BY a.userid,a.content ORDER BY id desc ";
			// TypedQuery<AccessDto2> access= entityManager.createQuery(SentenciaBase,
			// AccessDto2.class);
			// params.setFirstResult(offsetIn);
			// params.setMaxResults(numofrecordsIn);
			// List<AccessDto2> listacompleta = access.getResultList();
			String label = "";

			for (String acceso : accessDtoString) {
				// for (AccessDto2 acceso : listacompleta) {
				// List<Menu> menushort= menuRepository.findByContent(acceso.getContent());
				menushort = menuRepository.findByContent(acceso);
				// menushort = menuRepository.findByContent(acceso.getContent());
				int tienepadre = menuRepository.findByContentCount(acceso);
				// int tienepadre = menuRepository.findByContentCount(acceso.getContent());
				if (tienepadre == 1) {

					int Valor = menushort.get().getFather().getId();
					if (menuRepository.findByFather(Valor).get() != null
							&& menuRepository.findByFather(Valor).get().getFather() != null
							&& menuRepository.findByFather(Valor).get().getFather().getId() > 0) {
						desPadre = menuRepository
								.findByDscPadre(menuRepository.findByFather(Valor).get().getFather().getId());
						desContentPadre = menuRepository.findByContentDesc(desPadre,
								menuRepository.findByFather(Valor).get().getFather().getId());
						label = menushort.get().getFather().getDsc() + " - " + menushort.get().getDsc();
					} else {
						desPadre = menuRepository.findByDscPadre(menushort.get().getFather().getId());
						desContentPadre = menuRepository.findByContentDesc(desPadre,
								menushort.get().getFather().getId());
						label = menushort.get().getDsc();
					}
					int valor2 = Valor;

					String papa = desPadre;
				} else {
					desPadre = "";
					String papa = desPadre;
					desContentPadre = menushort.get().getContent();
					label = menushort.get().getDsc();
				}

				detalleShortcuts = new ShortcutsDto();
				detalleShortcuts.setLabel(label);
				detalleShortcuts.setGroup(desPadre);
				detalleShortcuts.setOpt(menushort.get().getContent());
				label = "";
				String svg = ".svg";
				String idcampoShort = "img/shortcuts/";
				String ConcatAmbienteShort = urlAmbiente.concat(idcampoShort);
				String rutaShort = ConcatAmbienteShort;
				// String rutaShort=
				// "http://vpskromasys2.hostnetcom.com/~daconsult/dev/img/shortcuts/";
				String ruta_completa = rutaShort.concat(desContentPadre).concat(svg);
				// String filePathshort = rutaShort.concat(desContentPadre).concat(svg);
				String filePathshort;
				
				if (ambiente.equals("/")) {
				
				 filePathshort = imagepath + "/" + imagen + shorcuts + desContentPadre + svg;
				}
				else {
				 filePathshort = imagepath + "/" + principal + "/" + ambiente + imagen + shorcuts + desContentPadre
						+ svg;
				}
				
				System.out.println(filePathshort);
				boolean existe = false;
				int responseCode = 0;
				/*
				 * try { URL url = new URL(filePathshort); HttpURLConnection huc =
				 * (HttpURLConnection) url.openConnection(); // InputStream isd =
				 * url.openStream(); responseCode = huc.getResponseCode(); if (responseCode ==
				 * 200) { detalleShortcuts.setImage(filePathshort); } else {
				 * detalleShortcuts.setImage(null); } // System.out.println("Abierto"); } catch
				 * (Exception e) { // System.out.println("cerrado");
				 * detalleShortcuts.setImage(null); }
				 */

				File archivo = new File(filePathshort);

				if (archivo.exists()) {
					detalleShortcuts.setImage(ruta_completa);
				} else {
					detalleShortcuts.setImage(null);
				}

				// detalleShortcuts.setImage(ruta);
				listashortcuts.add(detalleShortcuts);
			}

			menuDto.setShortcuts(listashortcuts);
			// menuDto.setShortcuts(null);
			Optional<Params> mainMessage = paramsRepository.findByParamname("MAIN_MESSAGE");
			menuDto.setMainmessage(mainMessage.get().getValue());

			List<MenuDto> menusDto = new ArrayList();
			menusDto = buildMenuDto2(0, sessionid);
			// Los asigno al options
			menuDto.setOptions(menusDto);
			usersRepository.asociarcambioValidthru(encontreSessionUsuario.get().getId(), ValidThrufechaSalida);
		} else {
			menuDto = null;
		}

		return menuDto;
	}

	public void iscontentdiffnull(String content, int userid) {
		try {
			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);
			Access detalleAcces = new Access();

			if (content == "") {
				String mensaje = "No pasa nada";
			}

			else

			{

				boolean existeContent = accessRepository.existsByContentAndUserid(content, userid);

				if (existeContent) {

					accessRepository.deleteContentUser(userid, content);

					detalleAcces.setUserid(userid);
					detalleAcces.setContent(content);
					detalleAcces.setDate(fechaDate);

					accessRepository.save(detalleAcces);

				} else {

					detalleAcces.setUserid(userid);
					detalleAcces.setContent(content);
					detalleAcces.setDate(fechaDate);

					accessRepository.save(detalleAcces);
				}
			}

		} catch (Exception e) {
			return;
		}
	}

}