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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.bankaudit.constants.BankAuditConstant;
import com.bankaudit.dao.MaintUsergroupRolesDao;
import com.bankaudit.dto.DataTableResponse;
import com.bankaudit.dto.MaintUsergroupRolesDto;
import com.bankaudit.model.MaintUsergroupRoles;
import com.bankaudit.model.MaintUsergroupRolesWrk;
import com.bankaudit.model.MaintRoleEntitlement;
import com.bankaudit.model.MaintRoleEntitlementHst;
import com.bankaudit.model.MaintRoleEntitlementWrk;
import com.bankaudit.model.MaintUsergroupRoles;
import com.bankaudit.model.MaintUsergroupRolesHst;
import com.bankaudit.model.MaintUsergroupRolesWrk;
import com.bankaudit.model.UserRoleMapping;
import com.bankaudit.model.UserRoleMappingWrk;

/**
 * The Class {@link MaintUsergroupRolesServiceImpl} Implements the business
 * logic method.
 *
 * @author amit.patel
 * @version 1.0
 */
@Service("maintUsergroupRoles")
@Transactional("transactionManager")
public class MaintUsergroupRolesServiceImpl implements MaintUsergroupRolesService {

	/**
	 * The maint usergroup roles dao is autowired and make methods available
	 * from dao layer .
	 */
	@Autowired
	MaintUsergroupRolesDao maintUsergroupRolesDao;
	
	/**
	 * The maint role entitlement service is autowired and make methods
	 * available from dao layer .
	 */
	@Autowired
	MaintRoleEntitlementService maintRoleEntitlementService;
	
	/**
	 * The business date service is autowired and make methods available from
	 * dao layer .
	 */
	@Autowired
	BusinessDateService businessDateService;
	
	/* (non-Javadoc)
	 * @see com.bankaudit.service.MaintUsergroupRolesService#createMaintUsergroupRoles(com.bankaudit.dto.MaintUsergroupRolesDto)
	 */
	@Override
	public void createMaintUsergroupRoles(MaintUsergroupRolesDto maintUsergroupRolesDto) {
		
		MaintUsergroupRolesWrk maintUsergroupRolesWrk=maintUsergroupRolesDto.getMaintUsergroupRolesWrk();
		
		if(maintUsergroupRolesWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_DF)
				|| maintUsergroupRolesWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_UNAUTH)
				){
			
			maintUsergroupRolesDao.save(maintUsergroupRolesWrk);
			MaintRoleEntitlementWrk roleEntitlementWrk=null;
			if(maintUsergroupRolesDto.getFunctionIds()!=null){
				for (String functionId : maintUsergroupRolesDto.getFunctionIds()) {
					roleEntitlementWrk=new MaintRoleEntitlementWrk();
					roleEntitlementWrk.setBusinessdateTimestamp(maintUsergroupRolesWrk.getBusinessdateTimestamp());
					roleEntitlementWrk.setSysdateTimestamp(maintUsergroupRolesWrk.getSysdateTimestamp());
					roleEntitlementWrk.setFunctionId(functionId);
					roleEntitlementWrk.setLegalEntityCode(maintUsergroupRolesWrk.getLegalEntityCode());
					roleEntitlementWrk.setMaker(maintUsergroupRolesWrk.getMaker());
					roleEntitlementWrk.setUgRoleCode(maintUsergroupRolesWrk.getUgRoleCode());
					roleEntitlementWrk.setMakerTimestamp(maintUsergroupRolesWrk.getMakerTimestamp());
					
					maintUsergroupRolesDao.save(roleEntitlementWrk);
				}
			}
			
		}else if (maintUsergroupRolesWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_AUTH)) {
			
			MaintUsergroupRoles maintUsergroupRoles=new MaintUsergroupRoles();
			
			BeanUtils.copyProperties(maintUsergroupRolesWrk, maintUsergroupRoles);
			maintUsergroupRolesDao.save(maintUsergroupRoles);
			MaintRoleEntitlement roleEntitlement=null;
			if(maintUsergroupRolesDto.getFunctionIds()!=null){
				for (String functionId : maintUsergroupRolesDto.getFunctionIds()) {
					roleEntitlement=new MaintRoleEntitlement();
					roleEntitlement.setBusinessdateTimestamp(maintUsergroupRoles.getBusinessdateTimestamp());
					roleEntitlement.setSysdateTimestamp(maintUsergroupRoles.getSysdateTimestamp());
					roleEntitlement.setFunctionId(functionId);
					roleEntitlement.setLegalEntityCode(maintUsergroupRoles.getLegalEntityCode());
					roleEntitlement.setMaker(maintUsergroupRoles.getMaker());
					roleEntitlement.setUgRoleCode(maintUsergroupRoles.getUgRoleCode());
					roleEntitlement.setMakerTimestamp(maintUsergroupRoles.getMakerTimestamp());
					maintUsergroupRolesDao.save(roleEntitlement);
				}
			}
		}
		
	}

	/* (non-Javadoc)
	 * @see com.bankaudit.service.MaintUsergroupRolesService#updateMaintUsergroupRoles(com.bankaudit.dto.MaintUsergroupRolesDto)
	 */
	@Override
	public void updateMaintUsergroupRoles(MaintUsergroupRolesDto maintUsergroupRolesDto) {
		
		
		MaintUsergroupRolesWrk maintUsergroupRolesWrk =maintUsergroupRolesDto.getMaintUsergroupRolesWrk();
		
		if(!maintUsergroupRolesWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_AUTH)){

			if(maintUsergroupRolesWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_UNAUTH)
					|| maintUsergroupRolesWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_MOD)
					|| maintUsergroupRolesWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_DF)){
				maintUsergroupRolesWrk.setMakerTimestamp(businessDateService.getBusinessDateTimestampByLegalEntityCode(maintUsergroupRolesWrk.getLegalEntityCode()));
			}
			

			if(!maintUsergroupRolesWrk.getStatus().equalsIgnoreCase(BankAuditConstant.STATUS_DF)){
				// get Db object and save into the history
				Map<String,Object> properties=new HashMap<String,Object>();
				properties.put("legalEntityCode",maintUsergroupRolesWrk.getLegalEntityCode());
				properties.put("ugRoleCode",maintUsergroupRolesWrk.getUgRoleCode());
				MaintUsergroupRolesWrk maintUsergroupRolesWrkDb=(MaintUsergroupRolesWrk)maintUsergroupRolesDao.getUniqueEntityByMatchingProperties(MaintUsergroupRolesWrk.class, properties);
				List<String> functionIdsWrkDb = maintRoleEntitlementService.getFunctionIds(maintUsergroupRolesWrk.getLegalEntityCode(), maintUsergroupRolesWrk.getUgRoleCode(), BankAuditConstant.STATUS_UNAUTH);
				
				if(maintUsergroupRolesWrkDb!=null){
					MaintUsergroupRolesHst maintUsergroupRolesHst=new MaintUsergroupRolesHst();
					BeanUtils.copyProperties(maintUsergroupRolesWrkDb, maintUsergroupRolesHst);
					maintUsergroupRolesDao.save(maintUsergroupRolesHst);
					MaintRoleEntitlementHst maintRoleEntitlementHst=null;
					if(functionIdsWrkDb!=null){
						for (String functionId : functionIdsWrkDb) {
							maintRoleEntitlementHst=new MaintRoleEntitlementHst();
							maintRoleEntitlementHst.setBusinessdateTimestamp(maintUsergroupRolesHst.getBusinessdateTimestamp());
							maintRoleEntitlementHst.setSysdateTimestamp(maintUsergroupRolesHst.getSysdateTimestamp());
							maintRoleEntitlementHst.setFunctionId(functionId);
							maintRoleEntitlementHst.setLegalEntityCode(maintUsergroupRolesHst.getLegalEntityCode());
							maintRoleEntitlementHst.setMaker(maintUsergroupRolesHst.getMaker());
							maintRoleEntitlementHst.setUgRoleCode(maintUsergroupRolesHst.getUgRoleCode());
							maintRoleEntitlementHst.setMakerTimestamp(maintUsergroupRolesHst.getMakerTimestamp());
							maintUsergroupRolesDao.save(maintRoleEntitlementHst);
						}
					}
					
				}
			}
			
			//delete the existing object rfrom work  
/*			maintUsergroupRolesDao.deleteMaintUsergroupRolesWrk(maintUsergroupRolesWrk.getLegalEntityCode(),maintUsergroupRolesWrk.getUgRoleCode());*/
			// delete the existing work maintEntityAuditSubgroupMapping 
			maintUsergroupRolesDao.saveOrUpdate(maintUsergroupRolesWrk);
			
			maintRoleEntitlementService.deleteMaintRoleEntitlementWrk(maintUsergroupRolesWrk.getLegalEntityCode(), maintUsergroupRolesWrk.getUgRoleCode());
			
			//code changes for update role maintainance
			maintUsergroupRolesDao.flushSession();
			
			 
			MaintRoleEntitlementWrk roleEntitlementWrk=null;
			if(maintUsergroupRolesDto.getFunctionIds()!=null){
				for (String functionId : maintUsergroupRolesDto.getFunctionIds()) {
					roleEntitlementWrk=new MaintRoleEntitlementWrk();
					roleEntitlementWrk.setBusinessdateTimestamp(maintUsergroupRolesWrk.getBusinessdateTimestamp());
					roleEntitlementWrk.setSysdateTimestamp(maintUsergroupRolesWrk.getSysdateTimestamp());
					roleEntitlementWrk.setFunctionId(functionId);
					roleEntitlementWrk.setLegalEntityCode(maintUsergroupRolesWrk.getLegalEntityCode());
					roleEntitlementWrk.setMaker(maintUsergroupRolesWrk.getMaker());
					roleEntitlementWrk.setUgRoleCode(maintUsergroupRolesWrk.getUgRoleCode());
					roleEntitlementWrk.setMakerTimestamp(maintUsergroupRolesWrk.getMakerTimestamp());
					maintUsergroupRolesDao.save(roleEntitlementWrk);
				}
			}
			
			
		}else{

			// get Db object and save into the history
			Map<String,Object> properties=new HashMap<String,Object>();
			properties.put("legalEntityCode",maintUsergroupRolesWrk.getLegalEntityCode());
			properties.put("ugRoleCode",maintUsergroupRolesWrk.getUgRoleCode());
			MaintUsergroupRoles maintUsergroupRolesDb=(MaintUsergroupRoles)maintUsergroupRolesDao.getUniqueEntityByMatchingProperties(MaintUsergroupRoles.class, properties);
			
			if(maintUsergroupRolesDb!=null){
				List<String> functionIdsDb = maintRoleEntitlementService.getFunctionIds(maintUsergroupRolesWrk.getLegalEntityCode(), maintUsergroupRolesWrk.getUgRoleCode(), BankAuditConstant.STATUS_AUTH);
				MaintUsergroupRolesHst maintUsergroupRolesHst=new MaintUsergroupRolesHst();
				BeanUtils.copyProperties(maintUsergroupRolesDb, maintUsergroupRolesHst);
				maintUsergroupRolesDao.save(maintUsergroupRolesHst);
				
				MaintRoleEntitlementHst maintRoleEntitlementHst=null;
				if(functionIdsDb!=null){
					for (String functionId : functionIdsDb) {
						maintRoleEntitlementHst=new MaintRoleEntitlementHst();
						maintRoleEntitlementHst.setBusinessdateTimestamp(maintUsergroupRolesHst.getBusinessdateTimestamp());
						maintRoleEntitlementHst.setSysdateTimestamp(maintUsergroupRolesHst.getSysdateTimestamp());
						maintRoleEntitlementHst.setFunctionId(functionId);
						maintRoleEntitlementHst.setLegalEntityCode(maintUsergroupRolesHst.getLegalEntityCode());
						maintRoleEntitlementHst.setMaker(maintUsergroupRolesHst.getMaker());
						maintRoleEntitlementHst.setUgRoleCode(maintUsergroupRolesHst.getUgRoleCode());
						maintRoleEntitlementHst.setMakerTimestamp(maintUsergroupRolesHst.getMakerTimestamp());
						maintUsergroupRolesDao.save(maintRoleEntitlementHst);
					}
				}
				
			}
			
			//delete the existing object from both the tables  
			maintUsergroupRolesDao.deleteMaintUsergroupRoles(maintUsergroupRolesWrk.getLegalEntityCode(),maintUsergroupRolesWrk.getUgRoleCode(),BankAuditConstant.STATUS_AUTH);
			maintUsergroupRolesDao.deleteMaintUsergroupRoles(maintUsergroupRolesWrk.getLegalEntityCode(),maintUsergroupRolesWrk.getUgRoleCode(),BankAuditConstant.STATUS_UNAUTH);
			
			// delete the existing  maintEntityAuditSubgroupMapping from both table 
			
			maintRoleEntitlementService.deleteRoleEntitlements(maintUsergroupRolesWrk.getLegalEntityCode(), maintUsergroupRolesWrk.getUgRoleCode());
			maintRoleEntitlementService.deleteMaintRoleEntitlementWrk(maintUsergroupRolesWrk.getLegalEntityCode(), maintUsergroupRolesWrk.getUgRoleCode());
			
			//code changes for update role maintainance
		maintUsergroupRolesDao.flushSession();
			
			MaintUsergroupRoles maintUsergroupRoles=new MaintUsergroupRoles();
			
			BeanUtils.copyProperties(maintUsergroupRolesWrk, maintUsergroupRoles);
			maintUsergroupRoles.setCheckerTimestamp(maintUsergroupRoles.getBusinessdateTimestamp());
			// save again 
			maintUsergroupRolesDao.saveOrUpdate(maintUsergroupRoles);
			 
			MaintRoleEntitlement roleEntitlement=null;
			if(maintUsergroupRolesDto.getFunctionIds()!=null){
				for (String functionId : maintUsergroupRolesDto.getFunctionIds()) {
					roleEntitlement=new MaintRoleEntitlement();
					roleEntitlement.setBusinessdateTimestamp(maintUsergroupRoles.getBusinessdateTimestamp());
					roleEntitlement.setSysdateTimestamp(maintUsergroupRoles.getSysdateTimestamp());
					roleEntitlement.setFunctionId(functionId);
					roleEntitlement.setLegalEntityCode(maintUsergroupRoles.getLegalEntityCode());
					roleEntitlement.setMaker(maintUsergroupRoles.getMaker());
					roleEntitlement.setUgRoleCode(maintUsergroupRoles.getUgRoleCode());
					roleEntitlement.setMakerTimestamp(maintUsergroupRoles.getMakerTimestamp());
					maintUsergroupRolesDao.save(roleEntitlement);
				}
			}
		}
	}
	
	/* (non-Javadoc)
	 * @see com.bankaudit.service.MaintUsergroupRolesService#getMaintUsergroupRole(java.lang.Integer, java.lang.String, java.lang.String)
	 */
	@Override
	public MaintUsergroupRoles getMaintUsergroupRole(Integer legalEntityCode, String ugRoleCode,String status) {
		Map<String , Object> properties=new HashMap<String, Object>();
		properties.put("legalEntityCode",legalEntityCode);
		properties.put("ugRoleCode", ugRoleCode);
		if(!BankAuditConstant.STATUS_AUTH.equalsIgnoreCase(status)){
			MaintUsergroupRoles maintUsergroupRoles=null;
			MaintUsergroupRolesWrk maintUsergroupRolesWrk= (MaintUsergroupRolesWrk)maintUsergroupRolesDao.getUniqueEntityByMatchingProperties(MaintUsergroupRolesWrk.class, properties);			
			if(maintUsergroupRolesWrk!=null){
				BeanUtils.copyProperties(maintUsergroupRolesWrk, maintUsergroupRoles);
			}
			return maintUsergroupRoles;
		}else {
			return (MaintUsergroupRoles)maintUsergroupRolesDao.getUniqueEntityByMatchingProperties(MaintUsergroupRoles.class, properties);			
		}
	}


	/* (non-Javadoc)
	 * @see com.bankaudit.service.MaintUsergroupRolesService#createUserRoleMapping(com.bankaudit.model.UserRoleMapping)
	 */
	@Override
	public void createUserRoleMapping(UserRoleMapping userRoleMapping) {
		maintUsergroupRolesDao.save(userRoleMapping);
	}


	/* (non-Javadoc)
	 * @see com.bankaudit.service.MaintUsergroupRolesService#getMaintUsergroupRolesByLegalEntityCodeAndUserId(java.lang.Integer, java.lang.String, java.lang.String)
	 */
	@Override
	public Set<MaintUsergroupRoles> getMaintUsergroupRolesByLegalEntityCodeAndUserId(Integer legalEntityCode,
			String userId,String status) {
		return maintUsergroupRolesDao.getMaintUsergroupRolesByLegalEntityCodeAndUserId(legalEntityCode,userId,status).
				stream().map(UserRoleMapping::getMaintUsergroupRoles).collect(Collectors.toSet());
	}

	/* (non-Javadoc)
	 * @see com.bankaudit.service.MaintUsergroupRolesService#getMaintUsergroupRoles(java.lang.Integer, java.lang.String, java.lang.String, java.lang.Integer, java.lang.String, java.lang.Integer, java.lang.Integer)
	 */
	@Override
	public DataTableResponse getMaintUsergroupRoles(Integer legalEntityCode, String userId ,String search, Integer orderColumn,
			String orderDirection, Integer page, Integer size) {
		
		return  maintUsergroupRolesDao.getMaintUsergroupRoles( legalEntityCode,userId,  search,  orderColumn,
				 orderDirection,  page,  size);
	}

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

	/* (non-Javadoc)
	 * @see com.bankaudit.service.MaintUsergroupRolesService#getUserRoleMappings(java.lang.Integer, java.lang.String, java.lang.String)
	 */
	@Override
	public List<UserRoleMapping> getUserRoleMappings(Integer legalEntityCode, String userId, String status) {
		

		Map<String , Object> properties=new HashMap<String, Object>();
		properties.put("legalEntityCode",legalEntityCode);
		properties.put("userId", userId);
		if(!BankAuditConstant.STATUS_AUTH.equalsIgnoreCase(status)){
			List<UserRoleMapping> userRoleMappings=null;
			List<UserRoleMappingWrk> userRoleMappingWrks= maintUsergroupRolesDao.getEntitiesByMatchingProperties(UserRoleMappingWrk.class, properties);			
			if(userRoleMappingWrks!=null && !userRoleMappingWrks.isEmpty()){
				userRoleMappings=new ArrayList<UserRoleMapping>();
				UserRoleMapping userRoleMapping=null;
				for (UserRoleMappingWrk userRoleMappingWrk : userRoleMappingWrks) {
					userRoleMapping=new UserRoleMapping(); 
					BeanUtils.copyProperties(userRoleMappingWrk, userRoleMapping);
					userRoleMappings.add(userRoleMapping);
				}
				
			}
			return userRoleMappings;
		}else {
			return maintUsergroupRolesDao.getEntitiesByMatchingProperties(UserRoleMapping.class, properties);			
		}
	}

	/* (non-Javadoc)
	 * @see com.bankaudit.service.MaintUsergroupRolesService#deleteUserRoleMapping(java.lang.Integer, java.lang.String, java.lang.String)
	 */
	@Override
	public void deleteUserRoleMapping(Integer legalEntityCode, String userId, String status) {

		maintUsergroupRolesDao.deleteUserRoleMapping( legalEntityCode,  userId,  status);
	}

	/* (non-Javadoc)
	 * @see com.bankaudit.service.MaintUsergroupRolesService#getMaintUsergroupRolesByLegalEntityCodeAndUserId(java.lang.Integer, java.lang.String)
	 */
	@Override
	public List getMaintUsergroupRolesByLegalEntityCodeAndUserId(Integer legalEntityCode,
			String status) {
		Map<String,Object> properties=new HashMap<String, Object>();
		properties.put("legalEntityCode", legalEntityCode);
		List lst = new ArrayList();
		
		if(!BankAuditConstant.STATUS_AUTH.equalsIgnoreCase(status)){
			List<MaintUsergroupRolesWrk> listWrk=  maintUsergroupRolesDao.getEntitiesByMatchingProperties(MaintUsergroupRolesWrk.class, properties);
			for(MaintUsergroupRolesWrk rolesWrk: listWrk) {
				if(!("SADM").equalsIgnoreCase(rolesWrk.getUgRoleCode())) lst.add(rolesWrk); //not to consider Super Admin Role for the Client, It is used only for internal BAAS purpose
			}
					
		}else {
			properties.put("entityStatus", BankAuditConstant.STATUS_ACTIVE);
			List<MaintUsergroupRoles> listMst= maintUsergroupRolesDao.getEntitiesByMatchingProperties(MaintUsergroupRoles.class, properties);
			for(MaintUsergroupRoles rolesMst: listMst) {
				if(!("SADM").equalsIgnoreCase(rolesMst.getUgRoleCode())) lst.add(rolesMst); //not to consider Super Admin Role for the Client, It is used only for internal BAAS purpose
			}
		}
		return lst;
	}
	
	@Override
	public List<Map<String,Integer>> getTotalUsersPerRole(Integer legalEntityCode) {
		return maintUsergroupRolesDao.getTotalUsersPerRole(legalEntityCode);
	}


}
