/*
 * 
 */
package com.bankaudit.service;



import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import org.jboss.logging.Logger;
import org.springframework.beans.BeanUtils;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.RestTemplate;

import com.bankaudit.constants.BankAuditConstant;
import com.bankaudit.constants.Constants;
import com.bankaudit.constants.DomainUtil;
import com.bankaudit.dao.GeneralParameterDao;
import com.bankaudit.dao.MaintEntityDao;
import com.bankaudit.dao.UserDao;
import com.bankaudit.dao.UserDaoImpl;
import com.bankaudit.dto.DataTableResponse;
import com.bankaudit.dto.GetTokenDetailsDTO;
import com.bankaudit.dto.LoginRequest;
import com.bankaudit.dto.UpdateTokenDetailsRequest;
import com.bankaudit.dto.UserRegistrationDto;
import com.bankaudit.jwthelper.JwtTokenUtil;
import com.bankaudit.model.GeneralParameter;
import com.bankaudit.model.MaintAuditSubgroup;
import com.bankaudit.model.MaintAuditTypeDesc;
import com.bankaudit.model.MaintEntity;
import com.bankaudit.model.MaintEntityAuditSubgroupMapping;
import com.bankaudit.model.MaintEntityAuditSubgroupMappingHst;
import com.bankaudit.model.MaintEntityAuditSubgroupMappingWrk;
import com.bankaudit.model.MaintLegalEntity;
import com.bankaudit.model.MaintUsergroupRoles;
import com.bankaudit.model.TestSuperSdmin;
import com.bankaudit.model.User;
import com.bankaudit.model.UserHst;
import com.bankaudit.model.UserLog;
import com.bankaudit.model.UserRoleMapping;
import com.bankaudit.model.UserRoleMappingHst;
import com.bankaudit.model.UserRoleMappingWrk;
import com.bankaudit.model.UserSession;
import com.bankaudit.model.UserSessionId;
import com.bankaudit.model.UserWrk;
import com.bankaudit.repository.MaintLegalEntityRepository;
import com.bankaudit.repository.UserRepository;
import com.bankaudit.repository.UserRoleMappingRepository;
import com.bankaudit.repository.UserSessionRepository;
import com.bankaudit.util.ServiceStatus;

import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import io.jsonwebtoken.Claims;

/**
 * {@link UserServiceImpl} class implements the methods of {@link UserService}
 * interface.
 *
 * @author amit.patel
 * @version 1.0
 */
@Service("userService")
@Transactional("transactionManager")
public class UserServiceImpl implements UserService {
	
	/** The user dao is autowired and make methods available from dao layer . */
	@Autowired
	UserDao userDao;
	
	/**
	 * The business date service is autowired and make methods available from
	 * dao layer .
	 */
	@Autowired
	BusinessDateService businessDateService; 
	
	/**
	 * The maint usergroup roles service is autowired and make methods available
	 * from dao layer .
	 */
	@Autowired
	MaintUsergroupRolesService maintUsergroupRolesService;
	
	
	/**
	 * The maint entity audit subgroup mapping service is autowired and make
	 * methods available from dao layer .
	 */
	@Autowired
	MaintEntityAuditSubgroupMappingService maintEntityAuditSubgroupMappingService;

	@Autowired
	MaintEntityService maintEntityService;
	
	@Autowired
	MaintAuditTypeDescService maintAuditTypeDescService;
	
	@Autowired
	MaintAuditSubgroupService maintAuditSubgroupService;

	@Autowired
    private UserRepository userRepository;

	@Autowired
    private UserSessionRepository userSessionRepository;

	@Autowired
    MaintEntityDao maintEntityDao;

    @Autowired
    GeneralParameterDao generalParameterDao;

	@Autowired
    private UserRoleMappingRepository userRoleMappingRepository;

	 @Autowired
    private MaintLegalEntityRepository maintLegalEntityRepository;

	
    @Value("${pwd_min_length}")
    private Integer passwordMinLength;

    @Value("${ped_max_length}")
    private Integer passwordMaxLength;

    @Value("${recaptcha.secret-key}")
    private String recaptchaSecretKey;

	
	static final Logger logger = Logger.getLogger(UserServiceImpl.class);

	@Override
    public ResponseEntity<ServiceStatus> login(String domain, LoginRequest loginRequest) {

        Map<String, Object> result = new HashMap<>();
        ServiceStatus apiResponse = new ServiceStatus();

		String encodedPassword = loginRequest.getPassword(); 
        String rawPassword = new String(Base64.getDecoder().decode(encodedPassword), StandardCharsets.UTF_8);
		


        // if domain is null and it is not dev env return invalid domain
        if (domain == null) {
            apiResponse.setStatus(Constants.FAILURE);
            apiResponse.setMessage(Constants.UserControllerErrorCode.INVALID_DOMAIN);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(apiResponse);
        }

        // find the legal entity code for the given domain
        MaintLegalEntity maintLegalEntity = DomainUtil.getLegalEntityCodeByDomain(domain);

        if (maintLegalEntity == null) {
            apiResponse.setStatus(Constants.FAILURE);
            apiResponse.setMessage(Constants.UserControllerErrorCode.INVALID_DOMAIN);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(apiResponse);
        }

        // validate captcha
        boolean validCaptcha = false;
        if (maintLegalEntity.isEnableCaptcha()) {
            validCaptcha = validateCaptcha(loginRequest.getCaptcha());
        } else {
            validCaptcha = true;
        }

        if (!validCaptcha) {
            apiResponse.setStatus(Constants.FAILURE);
            apiResponse.setMessage(Constants.UserControllerErrorCode.INVALID_CAPTCHA);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(apiResponse);
        }

        // validate the user
        User user = validateCredentials(maintLegalEntity.getLegalEntityCode(), loginRequest.getUsername(),
                rawPassword);

        // if logout is false, when the user logged in and have not opted for prev
        // session logout

        if (user != null) {
            // user is not a new login user
            // check if the user is locked or not

            UserSession userSession = userSessionRepository.findByUserIdAndLegalEntityCode(user.getUserId(),
                    maintLegalEntity.getLegalEntityCode());
            // fetch the main entity for unit code and details

            MaintEntity maintEntity = maintEntityDao.getUnique(maintLegalEntity.getLegalEntityCode(), user.getUnitCode(), BankAuditConstant.STATUS_ACTIVE);

			GeneralParameter defaultPwd = generalParameterDao.findByLegalEntityCodeAndKey1AndKey2(maintLegalEntity.getLegalEntityCode(),BankAuditConstant.GP_DEFAULT_PASS, BankAuditConstant.GP_DEFAULT_PASS);

			// check if user is using a default password

			if (defaultPwd !=null && defaultPwd.getValue().equalsIgnoreCase(rawPassword)) {
				apiResponse.setStatus(Constants.SUCCESS);
                apiResponse.setMessage(Constants.UserControllerErrorCode.DEFAULT_PWD);
                return ResponseEntity.status(HttpStatus.OK).body(apiResponse);
			}

            // general params for the token expiry time
            GeneralParameter generalEntity = generalParameterDao.findByLegalEntityCodeAndKey1AndKey2(maintLegalEntity.getLegalEntityCode(),Constants.JWT_TOKEN, Constants.ACCESS_TOKEN_TIMEOUT);

            if (userSession != null && userSession.isLocked()) {
                apiResponse.setStatus(Constants.FAILURE);
                apiResponse.setMessage(Constants.UserControllerErrorCode.ACCOUNT_LOCKED);
                return ResponseEntity.status(HttpStatus.OK).body(apiResponse);
            } else if (userSession != null && userSession.isLogged()) {
                // see if there are any existing sessions active for the user
                apiResponse.setStatus(Constants.SUCCESS);
                apiResponse.setMessage(Constants.UserControllerErrorCode.EXISTING_SESSION);

                // generate the temporary token for the user
                String token = JwtTokenUtil.generateTemporaryToken(maintLegalEntity, user, maintEntity,
                        Integer.valueOf(generalEntity.getValue()));

                result.put("tokenExpirationTimeInMinutes", Integer.valueOf(generalEntity.getValue()));
                result.put("userId", user.getUserId());
                result.put("token", token);
                apiResponse.setResult(result);
                return ResponseEntity.status(HttpStatus.OK).body(apiResponse);
            } else {
                // create user session entry
            

                // generate the temporary token for the user
                String token = JwtTokenUtil.generateTemporaryToken(maintLegalEntity, user, maintEntity,
                        Integer.valueOf(generalEntity.getValue()));
				createUserSession(user.getUserId(), maintLegalEntity.getLegalEntityCode(),token);
                apiResponse.setStatus(Constants.SUCCESS);
                apiResponse.setMessage(Constants.UserControllerErrorCode.LOGIN_SUCCESS);
                result.put("tokenExpirationTimeInMinutes", Integer.valueOf(generalEntity.getValue()));
                result.put("userId", user.getUserId());
                result.put("token", token);
                apiResponse.setResult(result);
                return ResponseEntity.ok(apiResponse);
            }
        } else {
            if (updateUserSession(maintLegalEntity.getLegalEntityCode(), loginRequest.getUsername()).booleanValue()) {
                apiResponse.setStatus(Constants.FAILURE);
                apiResponse.setMessage(Constants.UserControllerErrorCode.ACCOUNT_LOCKED);
                return ResponseEntity.status(HttpStatus.OK).body(apiResponse);
            } else {
                apiResponse.setStatus(Constants.FAILURE);
                apiResponse.setMessage(Constants.UserControllerErrorCode.LOGIN_EXCEPTION);
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(apiResponse);
            }
        }

    }

    @Override
    public ResponseEntity<ServiceStatus> logout(String authTokenHeader) {
        ServiceStatus apiResponse = new ServiceStatus();

        String authToken = authTokenHeader.substring("Bearer ".length());
        Claims claims = JwtTokenUtil.decodeJwt(authToken);

        GetTokenDetailsDTO tokenDetails = JwtTokenUtil.getTokenDetails(claims);

        // get the logged in the user
        User user = getLoggedInUser(tokenDetails.getUserId(), tokenDetails.getLegalEntityCode());

        // if logout is true i.e user trying to login and opted for the prev session
        // close
        if (user != null) {
            updateUserLogoutSession(tokenDetails.getLegalEntityCode(), user.getUserId());
            apiResponse.setStatus(Constants.SUCCESS);
            apiResponse.setMessage(Constants.UserControllerErrorCode.LOGOUT_SUCCESS);
            return ResponseEntity.ok(apiResponse);
        } else {
            apiResponse.setStatus(Constants.FAILURE);
            apiResponse.setMessage(Constants.UserControllerErrorCode.LOGIN_EXCEPTION);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(apiResponse);
        }
    }

    @Override
    public ResponseEntity<ServiceStatus> updateTokenDetails(String authTokenHeader,
            UpdateTokenDetailsRequest updateTokenDetailsRequest) {

        ServiceStatus apiResponse = new ServiceStatus();
        // get User session details from jwt token
        String authToken = authTokenHeader.substring("Bearer ".length());
        Claims claims = JwtTokenUtil.decodeJwt(authToken);

        GetTokenDetailsDTO tokenDetails = JwtTokenUtil.getTokenDetails(claims);

        Map<String, Object> response = new HashMap<>();

        // get user existing roles
        List<UserRoleMapping> userRoles = userRoleMappingRepository
                .findByUserIdAndLegalEntityCodeAndStatusAndEntityStatus(tokenDetails.getUserId(),
                        tokenDetails.getLegalEntityCode(), BankAuditConstant.STATUS_AUTH,
                        BankAuditConstant.STATUS_ACTIVE);

        Optional<UserRoleMapping> userSelectedRole = userRoles.stream()
                .filter(e -> e.getUserRoleId().equalsIgnoreCase(updateTokenDetailsRequest.getRoleId())).findFirst();

        if (userSelectedRole.isPresent()) {

            // general params for the token expiry time
            GeneralParameter generalEntity = generalParameterDao.findByLegalEntityCodeAndKey1AndKey2(
                    tokenDetails.getLegalEntityCode(),
                    Constants.JWT_TOKEN, Constants.ACCESS_TOKEN_TIMEOUT);

            // get Maint Legal entity for jwt secret
            MaintLegalEntity maintLegalEntity = maintLegalEntityRepository
                    .findByLegalEntityCode(tokenDetails.getLegalEntityCode());

            String token = JwtTokenUtil.generatePermanentToken(maintLegalEntity, tokenDetails,
                    userSelectedRole.get().getUserRoleId(),
                    userSelectedRole.get().getMaintUsergroupRoles().getUgRoleName(),
                    Integer.valueOf(generalEntity.getValue()));

            claims = JwtTokenUtil.decodeJwt(token);
            // update the token in user session table
            userSessionRepository.updateToken(token, tokenDetails.getUserId(), tokenDetails.getLegalEntityCode());

            apiResponse.setStatus(Constants.SUCCESS);
            apiResponse.setMessage(Constants.UserControllerErrorCode.TOKEN_DETAILS_SUCCESS);
            response.put("tokenDetails", JwtTokenUtil.getTokenDetails(claims));
            response.put("token", token);
            apiResponse.setResult(response);
            return ResponseEntity.ok(apiResponse);
        } else {
            apiResponse.setStatus(Constants.FAILURE);
            apiResponse.setMessage(Constants.UserControllerErrorCode.INVALID_ROLE);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(apiResponse);
        }
    }


	
	/* (non-Javadoc)
	 * @see com.bankaudit.service.UserService#getUserByLegalEntityCodeAndUserId(java.lang.Integer, java.lang.String)
	 */
	@Override
	public User getUserByLegalEntityCodeAndUserId(Integer legalEntityCode, String userId) {

		Map<String,Object> properties=new HashMap<String,Object>();
		properties.put("legalEntityCode", legalEntityCode);
		properties.put("userId", userId);
		return (User)userDao.getUniqueEntityByMatchingProperties(User.class, properties);
		
	}

	/* (non-Javadoc)
	 * @see com.bankaudit.service.UserService#getTestSuperSdminByUsername(java.lang.String)
	 */
	@Override
	public TestSuperSdmin getTestSuperSdminByUsername(String username) {
		
		Map<String,Object> properties=new HashMap<String,Object>();
		properties.put("username", username);
		return (TestSuperSdmin)userDao.getUniqueEntityByMatchingProperties(TestSuperSdmin.class, properties);
		
	}

	/* (non-Javadoc)
	 * @see com.bankaudit.service.UserService#updateUserLoginTimestamp(java.lang.Integer, java.lang.String)
	 */
	@Override
	public void updateUserLoginTimestamp(Integer legalEntityCode, String userId) {
		
		userDao.updateUserLoginTimestamp( legalEntityCode,  userId);
		
	}

	/* (non-Javadoc)
	 * @see com.bankaudit.service.UserService#createUser(com.bankaudit.dto.UserRegistrationDto)
	 */
	@Override
	public void createUser(UserRegistrationDto userRegistrationDto) {

		UserWrk userWrk=userRegistrationDto.getUserWrk();
		if(userWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_DF)
				|| userWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_UNAUTH)
				){
			
			userDao.save(userWrk);
			
			// Commented for BaaSDOS, as this feature taken out from here to Mapping 
			/* if(userRegistrationDto.getMaintEntityAuditSubgroupMappings()!=null 
					 && !userRegistrationDto.getMaintEntityAuditSubgroupMappings().isEmpty()){
				 for (MaintEntityAuditSubgroupMappingWrk maintEntityAuditSubgroupMappingWrk  : userRegistrationDto.getMaintEntityAuditSubgroupMappings()) {
					 maintEntityAuditSubgroupMappingWrk.setId(userWrk.getUserId());	
					 maintEntityAuditSubgroupMappingWrk.setMaker(userWrk.getMaker());
					 maintEntityAuditSubgroupMappingWrk.setBusinessdateTimestamp(userWrk.getBusinessdateTimestamp());
					 maintEntityAuditSubgroupMappingWrk.setStatus(userWrk.getStatus());
					 maintEntityAuditSubgroupMappingWrk.setSysdateTimestamp(userWrk.getSysdateTimestamp());
					 userDao.save(maintEntityAuditSubgroupMappingWrk);
					}
			 }*/
			 if(userRegistrationDto.getUserRoleIds()!=null){
				 UserRoleMappingWrk userRoleMappingWrk=null;	
				 for (String userRoleId: userRegistrationDto.getUserRoleIds()) {
						 userRoleMappingWrk=new UserRoleMappingWrk();
						 userRoleMappingWrk.setBusinessdateTimestamp(userWrk.getBusinessdateTimestamp());
						 userRoleMappingWrk.setSysdateTimestamp(new Timestamp(System.currentTimeMillis()));
						 userRoleMappingWrk.setUserId(userWrk.getUserId());
						 userRoleMappingWrk.setStatus("A");
						 userRoleMappingWrk.setMakerTimestamp(new Timestamp(System.currentTimeMillis()));
						 userRoleMappingWrk.setMaker(userWrk.getMaker());
						 userRoleMappingWrk.setLegalEntityCode(userWrk.getLegalEntityCode());
						 userRoleMappingWrk.setEntityStatus("A");
						 userRoleMappingWrk.setUserRoleId(userRoleId);
						userDao.save(userRoleMappingWrk);	
					} 
			 }
			
			 
		}else if (userWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_AUTH)) {
			
			User user=new User();
			BeanUtils.copyProperties(userWrk, user);
			
			userDao.save(user);
			
			// Commented for BaaSDOS, as this feature taken out from here
			/* if(userRegistrationDto.getMaintEntityAuditSubgroupMappings()!=null 
					 && !userRegistrationDto.getMaintEntityAuditSubgroupMappings().isEmpty()){
				 MaintEntityAuditSubgroupMapping maintEntityAuditSubgroupMapping=null;
				 for (MaintEntityAuditSubgroupMappingWrk maintEntityAuditSubgroupMappingWrk  : userRegistrationDto.getMaintEntityAuditSubgroupMappings()) {
					 maintEntityAuditSubgroupMapping=new MaintEntityAuditSubgroupMapping();
					 BeanUtils.copyProperties(maintEntityAuditSubgroupMappingWrk, maintEntityAuditSubgroupMapping);
					 maintEntityAuditSubgroupMapping.setId(user.getUserId());	
					 maintEntityAuditSubgroupMapping.setMaker(user.getMaker());
					 maintEntityAuditSubgroupMapping.setBusinessdateTimestamp(user.getBusinessdateTimestamp());
					 maintEntityAuditSubgroupMapping.setStatus(user.getStatus());
					 maintEntityAuditSubgroupMapping.setSysdateTimestamp(user.getSysdateTimestamp());
					 userDao.save(maintEntityAuditSubgroupMapping);
					}
			 }*/
			 
			 if(userRegistrationDto.getUserRoleIds()!=null){
				 UserRoleMapping userRoleMapping=null;	
				 for (String userRoleId: userRegistrationDto.getUserRoleIds()) {
					 userRoleMapping=new UserRoleMapping();
					 userRoleMapping.setBusinessdateTimestamp(userWrk.getBusinessdateTimestamp());
					 userRoleMapping.setSysdateTimestamp(new Timestamp(System.currentTimeMillis()));
					 userRoleMapping.setUserId(userWrk.getUserId());
					 userRoleMapping.setStatus("A");
					 userRoleMapping.setMakerTimestamp(new Timestamp(System.currentTimeMillis()));
					 userRoleMapping.setMaker(userWrk.getMaker());
					 userRoleMapping.setLegalEntityCode(userWrk.getLegalEntityCode());
					 userRoleMapping.setEntityStatus("A");
					 userRoleMapping.setUserRoleId(userRoleId);
						userDao.save(userRoleMapping);	
					} 
			 }
			 
			 
			// for BaaSDOS, mapping each Inspection type to User
				/* if(userRegistrationDto.getMaintEntityAuditSubgroupMappings()!=null 
						 && !userRegistrationDto.getMaintEntityAuditSubgroupMappings().isEmpty()){
					 MaintEntityAuditSubgroupMapping maintEntityAuditSubgroupMapping=null;
					 for (MaintEntityAuditSubgroupMappingWrk maintEntityAuditSubgroupMappingWrk  : userRegistrationDto.getMaintEntityAuditSubgroupMappings()) {
						 maintEntityAuditSubgroupMapping=new MaintEntityAuditSubgroupMapping();
						 BeanUtils.copyProperties(maintEntityAuditSubgroupMappingWrk, maintEntityAuditSubgroupMapping);
						 maintEntityAuditSubgroupMapping.setId(user.getUserId());	
						 maintEntityAuditSubgroupMapping.setMaker(user.getMaker());
						 maintEntityAuditSubgroupMapping.setBusinessdateTimestamp(user.getBusinessdateTimestamp());
						 maintEntityAuditSubgroupMapping.setStatus(user.getStatus());
						 maintEntityAuditSubgroupMapping.setSysdateTimestamp(user.getSysdateTimestamp());
						 userDao.save(maintEntityAuditSubgroupMapping);
						}
				 }*/
			 
			// for BaaSDOS, mapping each Inspection type to User
			 logger.info("User to Audit mapping .. "+user.getLegalEntityCode() + user.getUserId());
			 List<MaintAuditTypeDesc> auditLst= maintAuditTypeDescService.getMaintAuditTypeDescByLegalEntityCode(user.getLegalEntityCode());
			 for(MaintAuditTypeDesc audit: auditLst) { // iterate all the list of Audit types
				 List<MaintEntityAuditSubgroupMapping> userAuditMapping=maintEntityAuditSubgroupMappingService.getMaintEntityAuditSubgroupMappingIdWithName(user.getLegalEntityCode(), "U", user.getUserId(), audit.getAuditTypeCode(), "A");  // U-> User, A-> Authorize
				 if(userAuditMapping.isEmpty()) { // If user to that Audit mapping not done, then Insert a new mapping
					 List<MaintAuditSubgroup> ags = maintAuditSubgroupService.getMaintAuditSubgroupes(user.getLegalEntityCode(),audit.getAuditTypeCode(),null,null);
					 if(!ags.isEmpty()) {
						 MaintEntityAuditSubgroupMapping maintEntityAuditSubgroupMapping=new MaintEntityAuditSubgroupMapping();
						 maintEntityAuditSubgroupMapping.setLegalEntityCode(user.getLegalEntityCode());
						 maintEntityAuditSubgroupMapping.setId(user.getUserId());	
						 maintEntityAuditSubgroupMapping.setAuditTypeCode(audit.getAuditTypeCode());
						 maintEntityAuditSubgroupMapping.setAuditGroupCode(ags.get(0).getAuditGroupCode());
						 maintEntityAuditSubgroupMapping.setAuditSubGroupCode(ags.get(0).getAuditSubGroupCode());
						 maintEntityAuditSubgroupMapping.setStatus(user.getStatus());
						 maintEntityAuditSubgroupMapping.setMaker(user.getMaker());
						 maintEntityAuditSubgroupMapping.setMakerTimestamp(user.getBusinessdateTimestamp());
						 maintEntityAuditSubgroupMapping.setBusinessdateTimestamp(user.getBusinessdateTimestamp());
						 maintEntityAuditSubgroupMapping.setSysdateTimestamp(user.getSysdateTimestamp());
						 userDao.save(maintEntityAuditSubgroupMapping);
					 }
				 }
			 }
			 // User to Audit mapping, End here
			 
		}
	}
	
	
	/* (non-Javadoc)
	 * @see com.bankaudit.service.UserService#getUser(java.lang.Integer, java.lang.String, java.lang.String, java.lang.Integer, java.lang.String, java.lang.Integer, java.lang.Integer)
	 */
	@Override
	public DataTableResponse getUser(Integer legalEntityCode, String userId ,String search, Integer orderColumn, String orderDirection,
			Integer page, Integer size) {
		List<String> unitLst=maintEntityService.getSubBranchesGyUserIdOrUnitId(legalEntityCode,"user",userId); // 
		return userDao.getUser( legalEntityCode, userId, search,  orderColumn,  orderDirection,
				page, size, unitLst); // UnitLst included to get the Users based on Jurisdiction
		
	}

	/* (non-Javadoc)
	 * @see com.bankaudit.service.UserService#getUser(java.lang.Integer, java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public List<User> getUser(Integer legalEntityCode, String unitCode,String userId,String status) {
		List<User> users=userDao.getUser( legalEntityCode,  unitCode ,userId,status);
	 
		if(users!=null && users.size()>0 && users.size()<=1){
			users.get(0).setMaintEntityAuditSubgroupMappings(maintEntityAuditSubgroupMappingService.getMaintEntityAuditSubgroupMapping(legalEntityCode, "U", userId,status));
		}
		return users ;
	}

	/* (non-Javadoc)
	 * @see com.bankaudit.service.UserService#getUser(java.lang.Integer, java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public List<User> validateUser(Integer legalEntityCode, String emailId,String userId,String status) {
		List<User> users=userDao.getUser( legalEntityCode,  emailId ,userId,status);
	 
		if(users!=null && users.size()>0 && users.size()<=1){
			users.get(0).setMaintEntityAuditSubgroupMappings(maintEntityAuditSubgroupMappingService.getMaintEntityAuditSubgroupMapping(legalEntityCode, "U", userId,status));
		}
		return users ;
	}
	
	/* (non-Javadoc)
	 * @see com.bankaudit.service.UserService#updateUser(com.bankaudit.dto.UserRegistrationDto)
	 */
	@Override
	public void updateUser(UserRegistrationDto userRegistrationDto) {

		UserWrk userWrk=userRegistrationDto.getUserWrk();
		
		if(!userWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_AUTH)){

			if(userWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_UNAUTH)
					|| userWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_MOD)
					|| userWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_DF)){
				System.out.println("Time .. "+businessDateService.getBusinessDateTimestampByLegalEntityCode(userWrk.getLegalEntityCode()));
				userWrk.setMakerTimestamp(businessDateService.getBusinessDateTimestampByLegalEntityCode(userWrk.getLegalEntityCode()));
			}
			if(!userWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_DF)){
				// get Db object and save into the history
				List<User> userDbs=getUser(userWrk.getLegalEntityCode(), null, userWrk.getUserId(),BankAuditConstant.STATUS_UNAUTH);
				User userDb = null;
				if(userDbs!=null && userDbs.size() > 0){
					userDb = userDbs.get(0);
				}
				List<UserRoleMapping> userRoleMappings=maintUsergroupRolesService.getUserRoleMappings(userWrk.getLegalEntityCode(),userWrk.getUserId(),BankAuditConstant.STATUS_UNAUTH);
				if(userDb!=null){
					UserHst userHst=new UserHst();
					BeanUtils.copyProperties(userDb, userHst);
					userDao.save(userHst);
					
					// Commented for BaaSDOS, as this feature taken out from here
					/*  if(userHst.getMaintEntityAuditSubgroupMappings()!=null 
							 && !userHst.getMaintEntityAuditSubgroupMappings().isEmpty()){
						 MaintEntityAuditSubgroupMappingHst maintEntityAuditSubgroupMappingHst=null;
						 for (Object maintEntityAuditSubgroupMapping  : userHst.getMaintEntityAuditSubgroupMappings()) {
							 maintEntityAuditSubgroupMappingHst=new MaintEntityAuditSubgroupMappingHst();
							 BeanUtils.copyProperties(maintEntityAuditSubgroupMapping, maintEntityAuditSubgroupMappingHst);
							 maintEntityAuditSubgroupMappingHst.setId(userHst.getUnitCode());
							 maintEntityAuditSubgroupMappingHst.setMaker(userHst.getMaker());
							 maintEntityAuditSubgroupMappingHst.setBusinessdateTimestamp(userHst.getBusinessdateTimestamp());
							 maintEntityAuditSubgroupMappingHst.setStatus(userHst.getStatus());
							 maintEntityAuditSubgroupMappingHst.setSysdateTimestamp(userHst.getSysdateTimestamp());
							 userDao.save(maintEntityAuditSubgroupMappingHst);
							}
					 } */
					 if(userRoleMappings!=null){
						 UserRoleMappingHst userRoleMappingHst=null;
						 for (UserRoleMapping userRoleMapping : userRoleMappings) {
							 userRoleMappingHst=new UserRoleMappingHst();
							 BeanUtils.copyProperties(userRoleMapping, userRoleMappingHst);
							 userDao.save(userRoleMappingHst);
						}
					 }
					 
				}
			}
			
			// delete the existing work maintEntityAuditSubgroupMapping 
			//maintEntityAuditSubgroupMappingService.deleteMaintEntityAuditSubgroupMappingWrk(userWrk.getLegalEntityCode(),"U", userWrk.getUserId()); // Commented for BaaSDOS, as this feature taken out from here
			maintUsergroupRolesService.deleteUserRoleMapping(userWrk.getLegalEntityCode(),userWrk.getUserId(),BankAuditConstant.STATUS_UNAUTH);
			
			/*//delete the existing entity  
			userDao.deleteUser(userWrk.getLegalEntityCode(),userWrk.getUserId(),BankAuditConstant.STATUS_UNAUTH);
			 */
			
			userDao.flushSession();
			// save again 
			userDao.saveOrUpdate(userWrk);
			 
			// Commented for BaaSDOS, as this feature taken out from here
			/* if(userRegistrationDto.getMaintEntityAuditSubgroupMappings()!=null 
					 && !userRegistrationDto.getMaintEntityAuditSubgroupMappings().isEmpty()){
				 for (MaintEntityAuditSubgroupMappingWrk maintEntityAuditSubgroupMappingWrk  : userRegistrationDto.getMaintEntityAuditSubgroupMappings()) {
					 maintEntityAuditSubgroupMappingWrk.setId(userWrk.getUserId());
					 maintEntityAuditSubgroupMappingWrk.setMaker(userWrk.getMaker());
					 maintEntityAuditSubgroupMappingWrk.setBusinessdateTimestamp(userWrk.getBusinessdateTimestamp());
					 maintEntityAuditSubgroupMappingWrk.setStatus(userWrk.getStatus());
					 maintEntityAuditSubgroupMappingWrk.setSysdateTimestamp(userWrk.getSysdateTimestamp());
					 userDao.save(maintEntityAuditSubgroupMappingWrk);
					}
			 } */
			 
			 if(userRegistrationDto.getUserRoleIds()!=null){
				 UserRoleMappingWrk userRoleMappingWrk=null;	
				 for (String userRoleId: userRegistrationDto.getUserRoleIds()) {
						 userRoleMappingWrk=new UserRoleMappingWrk();
						 userRoleMappingWrk.setBusinessdateTimestamp(userWrk.getBusinessdateTimestamp());
						 userRoleMappingWrk.setSysdateTimestamp(new Timestamp(System.currentTimeMillis()));
						 userRoleMappingWrk.setUserId(userWrk.getUserId());
						 userRoleMappingWrk.setStatus("A");
						 userRoleMappingWrk.setMakerTimestamp(new Timestamp(System.currentTimeMillis()));
						 userRoleMappingWrk.setMaker(userWrk.getMaker());
						 userRoleMappingWrk.setLegalEntityCode(userWrk.getLegalEntityCode());
						 userRoleMappingWrk.setEntityStatus("A");
						 userRoleMappingWrk.setUserRoleId(userRoleId);
						userDao.save(userRoleMappingWrk);	
					} 
			 }
			
		}else{

			// get Db object and save into the history
			
			List<User> userDbs=getUser(userWrk.getLegalEntityCode(), null, userWrk.getUserId(),BankAuditConstant.STATUS_AUTH);
			User userDb = null;
			if(userDbs!=null && userDbs.size() > 0){
				userDb = userDbs.get(0);
			}
			
			List<UserRoleMapping> userRoleMappings=maintUsergroupRolesService.getUserRoleMappings(userWrk.getLegalEntityCode(),userWrk.getUserId(),BankAuditConstant.STATUS_AUTH);
			if(userDb!=null){
				UserHst userHst=new UserHst();
				BeanUtils.copyProperties(userDb, userHst);
				userDao.save(userHst);
				
				// Commented for BaaSDOS, as this feature taken out from here 
				/* if(userHst.getMaintEntityAuditSubgroupMappings()!=null 
						 && !userHst.getMaintEntityAuditSubgroupMappings().isEmpty()){
					
					 MaintEntityAuditSubgroupMappingHst maintEntityAuditSubgroupMappingHst=null;
					 
					 for (Object maintEntityAuditSubgroupMapping  : userHst.getMaintEntityAuditSubgroupMappings()) {
						 maintEntityAuditSubgroupMappingHst=new MaintEntityAuditSubgroupMappingHst();
						 BeanUtils.copyProperties(maintEntityAuditSubgroupMapping, maintEntityAuditSubgroupMappingHst);
						 maintEntityAuditSubgroupMappingHst.setId(userHst.getUnitCode());
						 maintEntityAuditSubgroupMappingHst.setMaker(userHst.getMaker());
						 maintEntityAuditSubgroupMappingHst.setBusinessdateTimestamp(userHst.getBusinessdateTimestamp());
						 maintEntityAuditSubgroupMappingHst.setStatus(userHst.getStatus());
						 maintEntityAuditSubgroupMappingHst.setSysdateTimestamp(userHst.getSysdateTimestamp());
						 userDao.save(maintEntityAuditSubgroupMappingHst);
						}
				 }*/
				 
				 if(userRoleMappings!=null){
					 UserRoleMappingHst userRoleMappingHst=null;
					 for (UserRoleMapping userRoleMapping : userRoleMappings) {
						 userRoleMappingHst=new UserRoleMappingHst();
						 BeanUtils.copyProperties(userRoleMapping, userRoleMappingHst);
						 userDao.save(userRoleMappingHst);
					}
				 }
				 
			}
			
	
			// delete the existing  maintEntityAuditSubgroupMapping from both table 
			//maintEntityAuditSubgroupMappingService.deleteMaintEntityAuditSubgroupMappingWrk(userWrk.getLegalEntityCode(),"U", userWrk.getUserId()); // Commented for BaaSDOS, as this feature taken out from here
			//maintEntityAuditSubgroupMappingService.deleteMaintEntityAuditSubgroupMapping(userWrk.getLegalEntityCode(), "U", userWrk.getUserId()); // Commented for BaaSDOS, as this feature taken out from here
			
			maintUsergroupRolesService.deleteUserRoleMapping(userWrk.getLegalEntityCode(),userWrk.getUserId(),BankAuditConstant.STATUS_AUTH);
			maintUsergroupRolesService.deleteUserRoleMapping(userWrk.getLegalEntityCode(),userWrk.getUserId(),BankAuditConstant.STATUS_UNAUTH);
			
			//delete the existing user  from both the tables 
			/*userDao.deleteUser(userWrk.getLegalEntityCode(),userWrk.getUserId(),BankAuditConstant.STATUS_AUTH);*/
			userDao.deleteUser(userWrk.getLegalEntityCode(),userWrk.getUserId(),BankAuditConstant.STATUS_UNAUTH);
					
			userDao.flushSession();
			
			String currentPassword=userDao.getUserPassword(userWrk.getLegalEntityCode(),userWrk.getUserId());
			User user=new User();
			
			BeanUtils.copyProperties(userWrk, user);
			user.setCheckerTimestamp(user.getBusinessdateTimestamp());
			if(currentPassword!=null)user.setPassword(currentPassword);
			// save again 
			userDao.saveOrUpdate(user);
			 
			// Commented for BaaSDOS, as this feature taken out from here
			/*if(userRegistrationDto.getMaintEntityAuditSubgroupMappings()!=null 
					 && !userRegistrationDto.getMaintEntityAuditSubgroupMappings().isEmpty()){
				 MaintEntityAuditSubgroupMapping maintEntityAuditSubgroupMapping=null; 
				 for (MaintEntityAuditSubgroupMappingWrk maintEntityAuditSubgroupMappingWrk  : userRegistrationDto.getMaintEntityAuditSubgroupMappings()) {
					 maintEntityAuditSubgroupMapping=new MaintEntityAuditSubgroupMapping();
					 BeanUtils.copyProperties(maintEntityAuditSubgroupMappingWrk, maintEntityAuditSubgroupMapping);
					 maintEntityAuditSubgroupMapping.setBusinessdateTimestamp(user.getBusinessdateTimestamp());
					 maintEntityAuditSubgroupMapping.setSysdateTimestamp(user.getSysdateTimestamp());
					 maintEntityAuditSubgroupMapping.setId(userWrk.getUserId());
					 maintEntityAuditSubgroupMapping.setMaker(userWrk.getMaker());
					 maintEntityAuditSubgroupMapping.setStatus("A");
					 userDao.save(maintEntityAuditSubgroupMapping);
					}
				 
			 }*/
			 
			 if(userRegistrationDto.getUserRoleIds()!=null){
				 UserRoleMapping userRoleMapping=null;	
				 for (String userRoleId: userRegistrationDto.getUserRoleIds()) {
					 userRoleMapping=new UserRoleMapping();
					 userRoleMapping.setBusinessdateTimestamp(userWrk.getBusinessdateTimestamp());
					 userRoleMapping.setSysdateTimestamp(new Timestamp(System.currentTimeMillis()));
					 userRoleMapping.setUserId(userWrk.getUserId());
					 userRoleMapping.setStatus("A");
					 userRoleMapping.setMakerTimestamp(new Timestamp(System.currentTimeMillis()));
					 userRoleMapping.setMaker(userWrk.getMaker());
					 userRoleMapping.setLegalEntityCode(userWrk.getLegalEntityCode());
					 userRoleMapping.setEntityStatus("A");
					 userRoleMapping.setUserRoleId(userRoleId);
						userDao.save(userRoleMapping);	
				} 
			 }
			 
			// for BaaSDOS, mapping each Inspection type to User
			 logger.info("User to Audit mapping .. "+user.getLegalEntityCode() + user.getUserId());
			 List<MaintAuditTypeDesc> auditLst= maintAuditTypeDescService.getMaintAuditTypeDescByLegalEntityCode(user.getLegalEntityCode());
			 for(MaintAuditTypeDesc audit: auditLst) { // iterate all the list of Audit types
				 List<MaintEntityAuditSubgroupMapping> userAuditMapping=maintEntityAuditSubgroupMappingService.getMaintEntityAuditSubgroupMappingIdWithName(user.getLegalEntityCode(), "U", user.getUserId(), audit.getAuditTypeCode(), "A");  // U-> User, A-> Authorize
				 if(userAuditMapping.isEmpty()) { // If user to that Audit mapping not done, then Insert a new mapping
					 List<MaintAuditSubgroup> ags = maintAuditSubgroupService.getMaintAuditSubgroupes(user.getLegalEntityCode(),audit.getAuditTypeCode(),null,null);
					 if(!ags.isEmpty()) {
						 MaintEntityAuditSubgroupMapping maintEntityAuditSubgroupMapping=new MaintEntityAuditSubgroupMapping();
						 maintEntityAuditSubgroupMapping.setLegalEntityCode(user.getLegalEntityCode());
						 maintEntityAuditSubgroupMapping.setMappingType("U");	
						 maintEntityAuditSubgroupMapping.setId(user.getUserId());	
						 maintEntityAuditSubgroupMapping.setAuditTypeCode(audit.getAuditTypeCode());
						 maintEntityAuditSubgroupMapping.setAuditGroupCode(ags.get(0).getAuditGroupCode());
						 maintEntityAuditSubgroupMapping.setAuditSubGroupCode(ags.get(0).getAuditSubGroupCode());
						 maintEntityAuditSubgroupMapping.setStatus(user.getStatus());
						 maintEntityAuditSubgroupMapping.setMaker(user.getMaker());
						 maintEntityAuditSubgroupMapping.setMakerTimestamp(user.getBusinessdateTimestamp());
						 maintEntityAuditSubgroupMapping.setBusinessdateTimestamp(user.getBusinessdateTimestamp());
						 maintEntityAuditSubgroupMapping.setSysdateTimestamp(user.getSysdateTimestamp());
						 userDao.save(maintEntityAuditSubgroupMapping);
					 }
				 }
			 }
			 // User to Audit mapping, End here
	
			 
		}
	}

	/* (non-Javadoc)
	 * @see com.bankaudit.service.UserService#isUser(java.lang.Integer, java.lang.String)
	 */
	@Override
	public Boolean isUser(Integer legalEntityCode, String userId) {
		return userDao.isUser( legalEntityCode,  userId);
	}

	@Override
	public List<User> getUserByRoleId(Integer legalEntityCode, String userRoleId) {
		
		return userDao.getUserByRoleId( legalEntityCode,  userRoleId);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<String> getUploadTables(Integer legalEntityCode) {
		return userDao.getUploadTables( legalEntityCode);
	}
	
	/* (non-Javadoc)
	 * @see com.bankaudit.service.UserService#getUser(java.lang.Integer, java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public List<User> getAllActiveUsers(Integer legalEntityCode, String unitCode,String status) {
		List<User> users=userDao.getAllActiveUsers( legalEntityCode,  unitCode ,status);
	 	return users ;
	}
	
	@Override
	public Boolean validateUserWithIdandMobile(Integer legalEntityCode, String userId, String mobile1, String emailId, String status) {
		return userDao.validateUserWithIdandMobile( legalEntityCode, userId, mobile1, emailId, status);
	}
	
	@Override
	public String updateUserPassword(Integer legalEntityCode, String userId, String pwd) {
		return userDao.updateUserPassword( legalEntityCode, userId, pwd);
	}
	
	@Override
	public String getUnitIdforUser(Integer legalEntityCode, String userId) {
		return userDao.getUnitIdforUser( legalEntityCode, userId);
	}
	
	@Override
	public String getUnitLevelforUser(Integer legalEntityCode, String userId) {
		return userDao.getUnitLevelforUser( legalEntityCode, userId);
	}
	
	@Override
	public void updateBusinessDateBasedOnSysDate(Integer legalEntityCode) {
		businessDateService.updateBusinessDateBasedOnSysDate( legalEntityCode);
	}
	
	@Override
	public int getUnsuccessfullAttempts(Integer legalEntityCode, String userId) {
		return userDao.getUnsuccessfullAttempts( legalEntityCode, userId);
	}
	
	@Override
	public void updateUnsuccessfullAttempts(Integer legalEntityCode, String userId) {
		userDao.updateUnsuccessfullAttempts( legalEntityCode, userId);
	}
	
	@Override
	public String validateUserOrgetUserStatus(Integer legalEntityCode, String userId, String status) {
		return userDao.validateUserOrgetUserStatus( legalEntityCode, userId, status);
	}
	
	@Override
	public void deleteUserByID(Integer legalEntityCode, String userId, String makerId) {
		maintUsergroupRolesService.deleteUserRoleMapping(legalEntityCode, userId,BankAuditConstant.STATUS_REJ);
		userDao.deleteUser(legalEntityCode, userId, BankAuditConstant.STATUS_REJ);
	}
	
	@Override
	public List<User> getUsersByLevel(Integer legalEntityCode, String levelCode, String status) {
		List<User> users=userDao.getUsersByLevel( legalEntityCode,  levelCode ,status);
	 	return users ;
	}
	
	@Override
	public List<User> getUsersByLevelAndNotInGrpEntityMapping(Integer legalEntityCode, String levelCode, String status) {
		List<User> users=userDao.getUsersByLevelAndNotInGrpEntityMapping( legalEntityCode,  levelCode ,status);
	 	return users ;
	}
	
	@Override
	public List<User> getReportingUsers(Integer legalEntityCode,String unitCode,String userId,String typeOfUser){
		List<User> users=userDao.getReportingUsers( legalEntityCode,  unitCode , userId, typeOfUser);
	 	return users ;
	}
	
	@Override
	public List<User> getReportingUsersFromParent(Integer legalEntityCode,String unitCode,String userId,String typeOfUser){
		List<User> users=userDao.getReportingUsers( legalEntityCode,  unitCode , userId, typeOfUser);
	 	return users ;
	}
	
	@Override
	public List<User> getImmedieateReportingUsers(Integer legalEntityCode,String unitCode,String userId,String typeOfUser, Boolean onlyParent, Boolean inclusionHO){
		List<User> users=userDao.getImmedieateReportingUsers( legalEntityCode,  unitCode , userId, typeOfUser, onlyParent, inclusionHO);
	 	return users ;
	}
	
	@Override
	public List<User> getReportReviewer(Integer legalEntityCode,String unitCode, Boolean onlyParent, Boolean inclusionHO){
		List<User> users=userDao.getReportReviewer( legalEntityCode,  unitCode , onlyParent, inclusionHO);
	 	return users ;
	}
	
	/* Used to get the report reviewer drop down in Rating */
	@Override
	public List<User> getReportReviewerRO(Integer legalEntityCode,String unitCode, Boolean onlyParent, Boolean inclusionHO){
		List<User> users=userDao.getReportReviewerRO( legalEntityCode,  unitCode , onlyParent, inclusionHO);
	 	return users ;
	}
	
	@Override
	public List<User> getReviewerHO(Integer legalEntityCode,String unitCode){
		return userDao.getReviewerHO( legalEntityCode,  unitCode);
	}
	
	@Override
	public List<User> getReportReviewerApprover(Integer legalEntityCode,String unitCode, Boolean onlyRO, Boolean onlyHO){
		List<User> users=userDao.getReportReviewerApprover( legalEntityCode,  unitCode , onlyRO, onlyHO);
	 	return users ;
	}
	
	@Override
	public List<User> getAuditorsByAuditId(Integer legalEntityCode,String auditId){
		return userDao.getAuditorsByAuditId( legalEntityCode,  auditId);
	}
	
	@Override
	public List<User> getReportReviewerROAndAuditors(Integer legalEntityCode, String unitCode, String auditId, Boolean onlyParent, Boolean inclusionHO, String userType){
		List<User> usersRO=userDao.getReportReviewerRO( legalEntityCode,  unitCode , false, false);
		List<User> usersAuditor= userDao.getAuditorsByAuditIdAndOptionalUerType(legalEntityCode, auditId, "L"); // only Lead auditor or PIO
		usersRO.addAll(usersAuditor);
		return usersRO;
	}
	
	@Override
	public Boolean isUserBelongsToSameUnitHierarchy(Integer legalEntityCode, String unitCode, String userId, String userUnitCode) {
		List<String> unitsList=maintEntityService.getSubBranchesGyUserIdOrUnitId(legalEntityCode,"user",userId);
		boolean isUserBelongs = false;
		if(!unitsList.isEmpty())	isUserBelongs =unitsList.stream().anyMatch(s -> unitCode.equals(s));
		return isUserBelongs;
	}
	
	@Override
	public List<User> getFYEOUser(Integer legalEntityCode,String unitCode, Boolean onlyParent, Boolean inclusionHO){
		List<User> users=userDao.getFYEOUser( legalEntityCode,  unitCode , onlyParent, inclusionHO);
	 	return users ;
	}
	
	@Override
	public Boolean isUserHavingParticularRole(Integer legalEntityCode, String userId, String role) {
		boolean validUsr = true;
		if(role!=null)validUsr=userDao.isUserHavingParticularRole(legalEntityCode, userId, role);
		logger.info("isUserHavingParticularRole srvcImpl role is :: "+role +" validUser :: "+validUsr );
		return validUsr;
	}
	
	@Override
	public Boolean isUserHavingEntitlement(Integer legalEntityCode, String userId, String role, String functionId, String action) {
		boolean validUsr = true;
		if(role!=null)validUsr=userDao.isUserHavingEntitlement(legalEntityCode, userId, role, functionId, action);
		logger.info("isUserHavingParticularRole srvcImpl role is :: "+role +" validUser :: "+validUsr );
		return validUsr;
	}
	
	@Override
	public String checkUserSession(Integer legalEntityCode, String userId){
		return userDao.checkUserSession(legalEntityCode, userId);
	}
	
	@Override
	public String isFirstLogin(Integer legalEntityCode, String userId){
		User user = userDao.isFirstLogin(legalEntityCode, userId);
		if(user == null){
			return BankAuditConstant.NO;
		} 		
		Date currentLoginDate = user.getCurrentLogin();
		return currentLoginDate == null ? BankAuditConstant.YES : BankAuditConstant.NO;
	}
	
	// Method to insert User log on each login, added on 01Apr2025
	@Override
	public void insertUserLogin(Integer legalEntityCode, String userId, String unitCode) {
		logger.info("Inside insertUserLogin .. "+ legalEntityCode+" :: "+userId+" :: "+unitCode);
		UserLog userlog=null;
		try {
			if(userId !=null) {		
				userlog=new UserLog();
				userlog.setLegalEntityCode(legalEntityCode);
				userlog.setUserId(userId);
				userlog.setUnitCode(unitCode);
				userlog.setCurrentLogin(new Timestamp(System.currentTimeMillis()));
				userlog.setBusinessdateTimestamp(new Timestamp(System.currentTimeMillis()));
				userlog.setSysdateTimestamp(new Timestamp(System.currentTimeMillis()));
				userDao.save(userlog);	
			}
		}catch(Exception e) {
			e.printStackTrace(System.out);
		}
		
	}

	  public boolean validateCaptcha(String captcha) {

        final RestTemplate restTemplate = new RestTemplate();
        final String RECAPTCHA_VERIFY_URL = "https://www.google.com/recaptcha/api/siteverify";

        MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
        requestBody.add("secret", recaptchaSecretKey);
        requestBody.add("response", captcha);

        ResponseEntity<Map> responseEntity = restTemplate.postForEntity(RECAPTCHA_VERIFY_URL, requestBody, Map.class);

        if (responseEntity.getStatusCode() == HttpStatus.OK) {
            Map responseBody = responseEntity.getBody();
            Boolean success = (Boolean) responseBody.get(Constants.SUCCESS);
            return success != null && success;
        } else {
            return false;
        }
    }

	public User validateCredentials(Integer legalEntityCode, String username, String password) {
        return userRepository.findByLegalEntityCodeAndLoginIdAndPasswordAndStatusAndEntityStatus(
                legalEntityCode,
                username, password);
    }

	 public User createUserSession(String userId, Integer legalEntityCode,String token) {
        User user = userRepository.findByUserIdAndLegalEntityCodeAndStatusAndEntityStatus(userId, legalEntityCode, "A",
                "A");
        initialUserSessionCreate(legalEntityCode, user.getUserId(), true,token);
        return user;
    }

	  public Boolean updateUserSession(Integer legalEntityCode, String userId) {
        Boolean isLocked = false;
        List<String> user = userRepository.findByUserId(legalEntityCode, userId);
        if (!user.isEmpty()) {
            UserSessionId id = new UserSessionId(legalEntityCode, user.get(0));
            UserSession userSession = userSessionRepository.findById(id).orElse(null);
            if (userSession != null) {
                Integer dbCount = userSession.getNumberOfAttemptsToLogin();
                Integer loginAttempt = ++dbCount;
                GeneralParameter generalEntity = generalParameterDao
                        .findByLegalEntityCodeAndKey1AndKey2(legalEntityCode, "UNSUCCESSFUL_ATTEMPT", "LOCK");
                Integer originalAttempt = Integer.parseInt(generalEntity.getValue());
                if (loginAttempt <= originalAttempt) {
                    if (loginAttempt == originalAttempt) {
                        userSession.setLocked(true);
                    }
                    userSession.setNumberOfAttemptsToLogin(loginAttempt++);
                    userSession.setLastSignIn(new Timestamp(new Date().getTime()));
                    userSessionRepository.save(userSession);
                } else {
                    if (isUserLocked(user.get(0), legalEntityCode, true).booleanValue()) {
                        isLocked = true;
                    }
                }
            } else {
                UserSession initialSession = new UserSession();
                initialSession.setLegalEntityCode(legalEntityCode);
                initialSession.setUserId(user.get(0));
                initialSession.setLogged(false);
                initialSession.setLocked(false);
                initialSession.setNumberOfAttemptsToLogin(1);
                userSessionRepository.save(initialSession);
            }
        }
        return isLocked;
    }

	 private void initialUserSessionCreate(Integer legalEntityCode, String userId, boolean isLoggedValue,String token) {
        UserSession userSession = new UserSession();
        userSession.setLegalEntityCode(legalEntityCode);
        userSession.setUserId(userId);
        userSession.setIpAddress(null);
        userSession.setLogged(isLoggedValue);
        userSession.setLocked(false);
        userSession.setNumberOfAttemptsToLogin(0);
        userSession.setLastSignIn(new Timestamp(new Date().getTime()));
        userSession.setPingTime(null);
		userSession.setToken(token);
        userSessionRepository.save(userSession);
    }

	  public Boolean isUserLocked(String userId, Integer legalEntityCode, boolean isLocked) {
        UserSession userSession = userSessionRepository.findByUserIdAndLegalEntityCodeAndIsLocked(userId,
                legalEntityCode, isLocked);
        if (userSession != null) {
            return true;
        } else {
            return false;
        }
    }

	  public User getLoggedInUser(String userId, Integer legalEntityCode) {
        return userRepository.findByUserIdAndLegalEntityCodeAndStatusAndEntityStatus(userId, legalEntityCode, "A",
                "A");
    }

	
    public void updateUserLogoutSession(Integer legalEntityCode, String userId) {
        userSessionRepository.updateUserLogoutSession(false, userId, legalEntityCode);
    }


    @Override
    public ResponseEntity<ServiceStatus> getUserRolesAndDetails(String authTokenHeader) {
        Map<String, Object> result = new HashMap<>();
        ServiceStatus apiResponse = new ServiceStatus();
        apiResponse.setStatus("success");
        apiResponse.setMessage("Valid user session.");

        // get User session details from jwt token
        String authToken = authTokenHeader.substring("Bearer ".length());
        Claims claims = JwtTokenUtil.decodeJwt(authToken);

        // fetch all the details from the jwt token
        GetTokenDetailsDTO tokenDetails = JwtTokenUtil.getTokenDetails(claims);
        result.put("tokenDetails", tokenDetails);

        // get user details
        User user = userRepository.findByUserIdAndLegalEntityCodeAndStatusAndEntityStatus(tokenDetails.getUserId(),
                tokenDetails.getLegalEntityCode(),
                BankAuditConstant.STATUS_AUTH, BankAuditConstant.STATUS_ACTIVE);
        if (BankAuditConstant.STATUS_ACTIVE.equalsIgnoreCase(user.getEntityStatus())) {// condition added to restrict
                                                                                       // the InActive and Closed Users

            // get user role mapping details
            List<UserRoleMapping> userRoles = userRoleMappingRepository
                    .findByUserIdAndLegalEntityCodeAndStatusAndEntityStatus(tokenDetails.getUserId(),
                            tokenDetails.getLegalEntityCode(), BankAuditConstant.STATUS_AUTH,
                            BankAuditConstant.STATUS_ACTIVE);
			Set<MaintUsergroupRoles> roles = userRoles.stream().map(UserRoleMapping::getMaintUsergroupRoles).collect(Collectors.toSet());

 			List<MaintUsergroupRoles> sortedRoles = new ArrayList<>(roles);
			Collections.sort(sortedRoles, new RolesComparator());
            result.put("roles", sortedRoles);

            List<String> authorities = new ArrayList<>();

            userRoles.forEach((userRole) -> {
                authorities.add(userRole.getMaintUsergroupRoles().getUgRoleCode() + "-"
                        + userRole.getMaintUsergroupRoles().getUgRoleName());
            });

            result.put("authorities", authorities);
            apiResponse.setResult(result);
        } else {
            String userStatus = user.getEntityStatus();
            String userStatusDesc=("I".equalsIgnoreCase(userStatus)? "Inactive" : ("L".equalsIgnoreCase(userStatus)? "Locked": "C".equalsIgnoreCase(userStatus)? "Closed":"not active") );
            apiResponse.setStatus(Constants.FAILURE);
            apiResponse.setMessage("The Account is " + userStatusDesc + ", contact Admin.");
        }

        return ResponseEntity.ok(apiResponse);
    }

	class RolesComparator implements Comparator<MaintUsergroupRoles> { 
  
		// override the compare() method 
		public int compare(MaintUsergroupRoles s1, MaintUsergroupRoles s2) 
		{ 
			return s1.getUgRoleName().compareTo(s2.getUgRoleName()); 
		} 
	} 




}