package com.nisum.mytime.service;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.nisum.mytime.exception.handler.MyTimeException;
import com.nisum.mytime.model.Account;
import com.nisum.mytime.model.AccountInfo;
import com.nisum.mytime.model.BillingDetails;
import com.nisum.mytime.model.Designation;
import com.nisum.mytime.model.Domains;
import com.nisum.mytime.model.EmpLoginData;
import com.nisum.mytime.model.EmpShiftDetails;
import com.nisum.mytime.model.EmployeeLocationDetails;
import com.nisum.mytime.model.EmployeeRoles;
import com.nisum.mytime.model.Location;
import com.nisum.mytime.model.MasterData;
import com.nisum.mytime.model.Project;
import com.nisum.mytime.model.ProjectTeamMate;
import com.nisum.mytime.model.Shift;
import com.nisum.mytime.model.Skill;
import com.nisum.mytime.repository.AccountInfoRepo;
import com.nisum.mytime.repository.AccountRepo;
import com.nisum.mytime.repository.DesignationRepo;
import com.nisum.mytime.repository.DomainRepo;
import com.nisum.mytime.repository.EmployeeLocationDetailsRepo;
import com.nisum.mytime.repository.EmployeeRolesRepo;
import com.nisum.mytime.repository.LocationRepo;
import com.nisum.mytime.repository.MasterDataRepo;
import com.nisum.mytime.repository.ProjectRepo;
import com.nisum.mytime.repository.ProjectTeamMatesRepo;
import com.nisum.mytime.repository.ShiftRepo;
import com.nisum.mytime.repository.TeamMatesBillingRepo;
import com.nisum.mytime.repository.TechnologyRepo;
import com.nisum.mytime.utils.DataValidations;
import com.nisum.mytime.utils.MyTimeUtils;
import com.nisum.mytime.utils.PdfReportGenerator;
import com.poiji.bind.Poiji;
import com.poiji.exception.PoijiExcelType;
import com.poiji.option.PoijiOptions;

import lombok.extern.slf4j.Slf4j;

@Service("userService")
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private EmployeeRolesRepo employeeRolesRepo;
    @Autowired
    private ProjectRepo projectRepo;

    @Autowired
    private ProjectTeamMatesRepo projectTeamMatesRepo;
    @Autowired
    private ProjectService projectService;

    @Autowired
    private ShiftRepo shiftRepo;

    @Autowired
    private DesignationRepo designationRepo;

    @Autowired
    private AccountRepo accountRepo;
    @Autowired
    private MasterDataRepo masterDataRepo;

    @Autowired
    private TechnologyRepo technologyRepo;

    @Autowired
    private LocationRepo locationRepo;

    @Autowired
    private EmployeeDataService employeeDataBaseService;

    @Autowired
    private PdfReportGenerator pdfReportGenerator;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private EmployeeLocationDetailsRepo employeeLocationDetailsRepo;
    
    @Autowired
    private DomainRepo domainRepo;
    
    @Autowired
    private AccountInfoRepo accountInfoRepo;
    
    @Autowired
    private TeamMatesBillingRepo teamMatesBillingRepo;
    
    @Autowired
    private RoleMappingService roleMappingService;


    @Override
    public Boolean fetchEmployeesData(String perticularDate,
            boolean resynchFlag) throws MyTimeException {
    	return true;  
    }

    @Override
    public List<EmpLoginData> employeeLoginsBasedOnDate(long id, String fromDate, String toDate) throws MyTimeException {
        return employeeDataBaseService.fetchEmployeeLoginsBasedOnDates(id, fromDate, toDate);
    }

    @Override
    public List generatePdfReport(long id, String fromDate, String toDate)
            throws MyTimeException {
        return pdfReportGenerator.generateEmployeeReport(id, fromDate, toDate);
    }
    
    @Override    
    public List generatePdfReport(long id, String fromDate, String toDate,String fromTime,String toTime)
            throws MyTimeException, ParseException {
        return pdfReportGenerator.generateEmployeeReport(id, fromDate, toDate,fromTime,toTime);
    }
    
    @Override
    public List<EmployeeRoles> getEmployeeRoles() throws MyTimeException {
        //return employeeRolesRepo.findAll();
    	return employeeRolesRepo.findByEmpStatus(MyTimeUtils.ACTIVE);
    }

    @Override
    public EmployeeRoles assigingEmployeeRole(EmployeeRoles employeeRoles, String loginEmpId)
            throws MyTimeException {
    	employeeRoles.setCreatedOn(new Date());
    	employeeRoles.setCreatedBy(loginEmpId);
        employeeRoles.setModifiedBy(loginEmpId);

        ProjectTeamMate newBenchAllocation = new ProjectTeamMate();
        newBenchAllocation.setAccount(MyTimeUtils.BENCH_ACCOUNT);
        newBenchAllocation.setBillableStatus(MyTimeUtils.BENCH_BILLABILITY_STATUS);
        newBenchAllocation.setDesignation(employeeRoles.getDesignation());
        newBenchAllocation.setEmailId(employeeRoles.getEmailId());
        newBenchAllocation.setEmployeeId(employeeRoles.getEmployeeId());
        newBenchAllocation.setMobileNumber(employeeRoles.getMobileNumber());
        
        newBenchAllocation.setEmployeeName(employeeRoles.getEmployeeName());
        newBenchAllocation.setProjectId(MyTimeUtils.BENCH_PROJECT_ID);
        newBenchAllocation.setStartDate(employeeRoles.getDateOfJoining() != null ? employeeRoles.getDateOfJoining() : new Date());
        Project p = projectRepo.findByProjectId(MyTimeUtils.BENCH_PROJECT_ID);
        newBenchAllocation.setProjectName(p.getProjectName());
        newBenchAllocation.setAccountId(p.getAccountId());
        newBenchAllocation.setDomainId(p.getDomainId());
        newBenchAllocation.setShift(employeeRoles.getShift());
        newBenchAllocation.setRole(employeeRoles.getRole());

        if ( null != employeeRoles.getEmpStatus() &&  employeeRoles.getEmpStatus().trim().equalsIgnoreCase(MyTimeUtils.IN_ACTIVE_SPACE)) {
            newBenchAllocation.setEndDate(employeeRoles.getEndDate());
            newBenchAllocation.setActive(false);
        } else {
            employeeRoles.setEmpStatus(MyTimeUtils.ACTIVE);
            newBenchAllocation.setEndDate(p.getProjectEndDate());
            newBenchAllocation.setActive(true);
        }
        
        try {
            projectService.addProjectTeamMate(newBenchAllocation, loginEmpId);
        } catch (MyTimeException e) {
            e.printStackTrace();
        }
        saveEmployeeLocationDetails(employeeRoles);
        return employeeRolesRepo.save(employeeRoles);
    }

    @Override
    public EmployeeRoles getEmployeesRole(String emailId) {
        return employeeRolesRepo.findByEmailId(emailId);

    }

    @Override
    public void deleteEmployee(String employeeId) {
        EmployeeRoles role = employeeRolesRepo.findByEmployeeId(employeeId);
        employeeRolesRepo.delete(role);
    }

    @Override
    public EmployeeRoles updateEmployeeRole(EmployeeRoles employeeRoles, String loginEmpId) {
        // update all emp details to inactive if employee is inactive
        Query query = new Query(Criteria.where("employeeId").is(employeeRoles.getEmployeeId()));
        Update update = new Update();
        update.set("employeeName", employeeRoles.getEmployeeName());
        update.set("emailId", employeeRoles.getEmailId());
        update.set("role", employeeRoles.getRole());
        update.set("gender", employeeRoles.getGender());
        update.set("functionalGroup", employeeRoles.getFunctionalGroup());
        update.set("empStatus", employeeRoles.getEmpStatus());
        update.set("employmentType", employeeRoles.getEmploymentType());
        update.set("empLocation", employeeRoles.getEmpLocation());
        update.set("domain", employeeRoles.getDomain());
        update.set("designation", employeeRoles.getDesignation());
        update.set("dateOfBirth", employeeRoles.getDateOfBirth());
        update.set("dateOfJoining", employeeRoles.getDateOfJoining());
        update.set("lastModifiedOn", new Date());
        update.set("hasPassort", employeeRoles.getHasPassort());
        update.set("hasB1", employeeRoles.getHasB1());
        update.set("passportExpiryDate", employeeRoles.getPassportExpiryDate());
        update.set("b1ExpiryDate", employeeRoles.getB1ExpiryDate());
        
        update.set("modifiedBy", loginEmpId);
        
        if(employeeRoles.getEmpStatus().equalsIgnoreCase(MyTimeUtils.IN_ACTIVE_SPACE)) {
            update.set("endDate", employeeRoles.getEndDate());
        }
        // update employee location
        if (employeeRoles.getEmpLocation() != null && !employeeRoles.getEmpLocation().equals("")) {
            EmployeeRoles existingEmployee = employeeRolesRepo.findByEmployeeId(employeeRoles.getEmployeeId());
            if (!existingEmployee.getEmpLocation().equals(employeeRoles.getEmpLocation())) {
                updateEmployeeLocationDetails(employeeRoles, false);
            }

        }

        // update employee details
        FindAndModifyOptions options = new FindAndModifyOptions();
        options.returnNew(true);
        options.upsert(true);
        EmployeeRoles emp = mongoTemplate.findAndModify(query, update, options, EmployeeRoles.class);
        try {
            // update employee location
            if (employeeRoles.getEmpLocation() != null && !employeeRoles.getEmpLocation().equals("")) {
                EmployeeRoles existingEmployee = employeeRolesRepo.findByEmployeeId(employeeRoles.getEmployeeId());
                if (!existingEmployee.getEmpLocation().equals(employeeRoles.getEmpLocation())) {
                    updateEmployeeLocationDetails(employeeRoles, false);
                }
            }

            // update employee details
            List<ProjectTeamMate> employeeProfiles = projectTeamMatesRepo
                    .findByEmployeeId(emp.getEmployeeId());
            if (employeeProfiles != null && !employeeProfiles.isEmpty()) {
                for (ProjectTeamMate profile : employeeProfiles) {
                    profile.setRole(emp.getRole());
                    projectTeamMatesRepo.save(profile);
                }
            }
            // inactive the employee from the assigned project 
			if (employeeRoles.getEmpStatus().equals(MyTimeUtils.IN_ACTIVE_SPACE) && employeeRoles.getEndDate() != null
					&& employeeRoles.getEndDate().compareTo(new Date()) <= 0) {

				List<ProjectTeamMate> projectTeamMate = projectTeamMatesRepo
						.findByEmployeeIdAndActive(employeeRoles.getEmployeeId(), true);
				if (projectTeamMate.size()==1) {
					ProjectTeamMate teamMate = projectTeamMate.get(0);
					teamMate.setActive(false);
					teamMate.setEndDate(employeeRoles.getEndDate());
					List<BillingDetails> listBD = getEmployeeActiveBillingDetails(teamMate.getEmployeeId(),
							teamMate.getProjectId());
					if (listBD != null && !listBD.isEmpty()) {
						BillingDetails billingDetailsExisting = listBD.get(0);
						billingDetailsExisting.setBillingEndDate(employeeRoles.getEndDate());
						billingDetailsExisting.setActive(false);
						billingDetailsExisting.setAuditFields(loginEmpId, MyTimeUtils.UPDATE);
						teamMatesBillingRepo.save(billingDetailsExisting);
					}
					teamMate.setAuditFields(loginEmpId, MyTimeUtils.UPDATE);
					projectTeamMatesRepo.save(teamMate);
					updateShiftDetails(teamMate, loginEmpId);
				}
			}
        } catch (Exception e) {
        }
        return emp;
    }

    @Override
    public EmployeeRoles getEmployeesRoleData(String employeeId) {
        return employeeRolesRepo.findByEmployeeId(employeeId);
    }

    @Override
    public List<Shift> getAllShifts() throws MyTimeException {
        return shiftRepo.findAll();
    }

    @Override
    public List<Designation> getAllDesignations() throws MyTimeException {
        return designationRepo.findAll();
    }

    @Override
    public List<Account> getAccounts() throws MyTimeException {
        return accountRepo.findAll();
    }

    @Override
    public List<Skill> getTechnologies() throws MyTimeException {
        return technologyRepo.findAll();
    }

    @Override
    public List<Location> getLocations() throws MyTimeException {
        return locationRepo.findAll();
    }

    @Override
    public EmployeeRoles updateProfile(EmployeeRoles employeeRoles)
            throws MyTimeException {
        boolean mobileNumberChanged = false;
        employeeRoles.setLastModifiedOn(new Date());
        EmployeeRoles existingEmployee = employeeRolesRepo
                .findByEmployeeId(employeeRoles.getEmployeeId());
        String newMobileNumber = employeeRoles.getMobileNumber();
        if (newMobileNumber != null && !newMobileNumber.equalsIgnoreCase("")) {
            if ((existingEmployee != null
                    && existingEmployee.getMobileNumber() != null
                    && !existingEmployee.getMobileNumber()
                            .equalsIgnoreCase(newMobileNumber))
                    || (existingEmployee.getMobileNumber() == null)) {
                mobileNumberChanged = true;
            }
        }
        existingEmployee.setMobileNumber(employeeRoles.getMobileNumber());
        existingEmployee.setAlternateMobileNumber(employeeRoles.getAlternateMobileNumber());
        existingEmployee.setPersonalEmailId(employeeRoles.getPersonalEmailId());
        existingEmployee.setBaseTechnology(employeeRoles.getBaseTechnology());
        existingEmployee.setTechnologyKnown(employeeRoles.getTechnologyKnown());
        EmployeeRoles employeeRolesDB = employeeRolesRepo.save(existingEmployee);
        if (mobileNumberChanged) {
            try {
                List<ProjectTeamMate> employeeProfiles = projectTeamMatesRepo
                        .findByEmployeeId(employeeRoles.getEmployeeId());
                if (employeeProfiles != null && !employeeProfiles.isEmpty()) {
                    for (ProjectTeamMate profile : employeeProfiles) {
                        profile.setMobileNumber(employeeRolesDB.getMobileNumber());
                        projectTeamMatesRepo.save(profile);
                    }
                }
            } catch (Exception e) {
            }
        }
        return employeeRolesDB;

    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nisum.mytime.service.UserService#getEmployeeRoleDataForSearchCriteria
     * (java.lang.String, java.lang.String)
     */
    @Override
    public EmployeeRoles getEmployeeRoleDataForSearchCriteria(String searchId,
            String searchAttribute) {
        if (MyTimeUtils.EMPLOYEE_NAME.equals(searchAttribute)) {
            return employeeRolesRepo.findByEmployeeName(searchId);
        } else if (MyTimeUtils.EMAIL_ID.equals(searchAttribute)) {
            return employeeRolesRepo.findByEmailId(searchId);
        }
        return null;

    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.nisum.mytime.service.UserService#getEmployeeDetailsForAutocomplete()
     */
    @Override
    public List<String> getEmployeeDetailsForAutocomplete() {
        List<EmployeeRoles> roles = employeeRolesRepo.findAll();
        List<String> details = new ArrayList<>();
        roles.stream()
                .sorted(java.util.Comparator
                        .comparing(EmployeeRoles::getEmployeeId))
                .collect(Collectors.toList()).forEach(role -> {
                    details.add(role.getEmployeeId());
                });
        roles.stream()
                .sorted(java.util.Comparator
                        .comparing(EmployeeRoles::getEmployeeName))
                .collect(Collectors.toList()).forEach(role -> {
                    details.add(role.getEmployeeName());
                });
        roles.stream()
                .sorted(java.util.Comparator
                        .comparing(EmployeeRoles::getEmailId))
                .collect(Collectors.toList()).forEach(role -> {
                    details.add(role.getEmailId());
                });
        return details;
    }

    @Override
    public List<MasterData> getMasterData() throws MyTimeException {
        return masterDataRepo.findAll();
    }

    @Override
    public void updateEmployeeLocationDetails(EmployeeRoles employeeRoles,
            boolean delete) {
        try {
            Query getQuery = new Query();
            getQuery.addCriteria(new Criteria().andOperator(
                    Criteria.where("active").is(true),
                    Criteria.where("employeeId")
                            .is(employeeRoles.getEmployeeId())));
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.DATE, -1);
            EmployeeLocationDetails existingLocation = mongoTemplate
                    .findOne(getQuery, EmployeeLocationDetails.class);
            if (existingLocation != null) {
                existingLocation.setActive(false);
                existingLocation.setEndDate(cal.getTime());
                existingLocation.setUpdatedDate(new Date());
                mongoTemplate.save(existingLocation);
            }
            if (!delete)
                saveEmployeeLocationDetails(employeeRoles);
        } catch (Exception ex) {
            System.out.println(ex);
        }
    }

    @Override
    public void saveEmployeeLocationDetails(EmployeeRoles employeeRoles) {
        EmployeeLocationDetails employeeLocationDetails = new EmployeeLocationDetails();
        employeeLocationDetails.setActive(employeeRoles.getEmpStatus().equalsIgnoreCase("Active"));
        employeeLocationDetails.setEmployeeId(employeeRoles.getEmployeeId());
        employeeLocationDetails.setEmployeeName(employeeRoles.getEmployeeName());
        employeeLocationDetails.setCreateDate(new Date());
        employeeLocationDetails.setEndDate(new Date());
        employeeLocationDetails.setUpdatedDate(new Date());
        employeeLocationDetails.setStartDate(new Date());
        employeeLocationDetails.setEmpLocation(employeeRoles.getEmpLocation());
        employeeLocationDetailsRepo.save(employeeLocationDetails);
    }

    @Override
    public List<EmployeeLocationDetails> getEmployeeLocationDetails(String empId) {
        return employeeLocationDetailsRepo.findByEmployeeId(empId);
    }

    @Override
    public List<EmployeeRoles> getEmployeesByFunctionalGrp(
            String functionalGrp) {
        return employeeRolesRepo.findByEmpStatusAndFunctionalGroup("Active", functionalGrp);

    }

    @Override
    public List<EmployeeRoles> getEmployeesByStatus(String status) {
        if (status.equals("both")) {
            return employeeRolesRepo.findAll(new Sort(Sort.Direction.ASC, "employeeName"));
        } else {
            return employeeRolesRepo.findByEmpStatusOrderByEmployeeNameAsc(status);
        }
    }

	@Override
	public List<HashMap<String, String>> getDeliveryLeads(String domainId) {
		List<HashMap<String, String>> EmployeeList = null;
		Domains domains= domainRepo.findByDomainId(domainId);
		EmployeeList=getEmployeeData(domains.getDeliveryManagers());
		return EmployeeList;
	}
	public List<HashMap<String, String>> getEmployeeData(List<String> ids) {
		List<HashMap<String, String>> EmployeeList = new ArrayList<>();

		Query query = new Query(Criteria.where("employeeId").in(ids));
		List<EmployeeRoles> employeeRoles = mongoTemplate.find(query, EmployeeRoles.class);
		for (EmployeeRoles employeesRole : employeeRoles) {
			HashMap<String, String> managerMap = new HashMap<>();
			managerMap.put("employeeId", employeesRole.getEmployeeId());
			managerMap.put("employeeName", employeesRole.getEmployeeName());
			EmployeeList.add(managerMap);
		}
		return EmployeeList;
	}
	@Override
    public List<AccountInfo> getAccountsInfo() throws MyTimeException {
        return accountInfoRepo.findAll();
    }

	@Override
	public List<Domains> getDomains(String accountId)throws MyTimeException {
		List<Domains> domains= domainRepo.findByAccountId(accountId);
		return domains;

	}
	  
	public List<BillingDetails> getEmployeeActiveBillingDetails(String empId, String projectId) {
		Query query4 = new Query();
		query4.addCriteria(Criteria.where("active").is(new Boolean(true)));
		query4.addCriteria(Criteria.where("employeeId").is(empId));
		query4.addCriteria(Criteria.where("projectId").is(projectId));
		List<BillingDetails> billings = mongoTemplate.find(query4, BillingDetails.class);
		List<BillingDetails> billingsSorted = billings;
		try {
			billingsSorted = (billings == null || billings.size() == 0) ? billings
					: billings.stream().sorted(Comparator.comparing(BillingDetails::getBillingStartDate).reversed())
							.collect(Collectors.toList());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return billingsSorted;
	}

	public void updateShiftDetails(ProjectTeamMate existingTeammate, String loginEmpId) {
		Query getQuery = new Query();
		getQuery.addCriteria(new Criteria().andOperator(Criteria.where("active").is(true),
				Criteria.where("employeeId").is(existingTeammate.getEmployeeId())));
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, -1);
		EmpShiftDetails existingShift = mongoTemplate.findOne(getQuery, EmpShiftDetails.class);
		if (existingShift != null) {
			existingShift.setActive(false);
			//existingShift.setUpdatedDate(new Date());// Commented as added common audit fields
			existingShift.setAuditFields(loginEmpId, MyTimeUtils.UPDATE);
			mongoTemplate.save(existingShift);
		}
	}
	
	@Override
	public boolean verifyRole(String empId,String roleName) {
		boolean flag = false;
		String role  = getEmployeesRoleData(empId).getRole();
		if( null != role &&  "" !=  role && !"Admin".equalsIgnoreCase(role)  ) {
			Set<String> roleSet = roleMappingService.empRolesMapInfoByEmpId(empId);
			if(null != roleSet && !roleSet.isEmpty() && MyTimeUtils.INT_ZERO < roleSet.size() ) {
				if( roleSet.contains(roleName) ) {
					flag = true;
				}
			}
			
		}
		return flag;
	}
	
	@Override
	public String importDataFromExcelFile(MultipartFile file, String logInEmpId) throws MyTimeException {
		String result = "";
	    try {
	        PoijiOptions options = PoijiOptions.PoijiOptionsBuilder.settings().preferNullOverDefault(true).datePattern("dd-MMM-yyyy").build();
	        List<EmployeeRoles> employees = Poiji.fromExcel(file.getInputStream(), PoijiExcelType.XLS, EmployeeRoles.class, options);
	        if (!employees.isEmpty()) {
	        	result = allColumnsExistCheckInExcel(employees.get(MyTimeUtils.INT_ZERO));
	        	if(!result.isEmpty()) {
	                log.info("Imported Excel file {} missing column {}", file.getOriginalFilename(), result);
	        		return result;
	        	}
	        	result = duplicateEmpIAndEmptyEmpIdsCheckInImportedExcel(employees);
	        	result += validateExcelRecords(employees);
	        	log.info("Partial Import :: Imported {} employee records from file: {}", employees.size(), file.getOriginalFilename());
	            for (EmployeeRoles employee : employees) {
	            	addEmployee(employee,logInEmpId);
	            }
	        } else {
	        	result = "Uploaded file: {"+ file.getOriginalFilename() +"}, is Empty";
                log.info( "Uploaded file: {}, is Empty", file.getOriginalFilename());
	        }
            if (result.isEmpty()) {
            	result = "Successfully Employees added";
                log.info("Full Import :: Imported {} employee records from file: {}", employees.size(), file.getOriginalFilename());
            }
	    } catch (Exception e) {
	        log.error("Exception occured while exporting the data from excel file due to: {}",e);
	        throw new MyTimeException("Exception occured while exporting the data from excel file due to :"+e.getMessage());
	    }
	    return result;
	}
	
	private void addEmployee(EmployeeRoles employee,String empId) {
        try {
        	if(employee.getRole().trim().isEmpty()) {
        		employee.setRole(MyTimeUtils.EMPLOYEE);
        	}
            if (employee.getEmploymentType().trim().isEmpty()) {
            	employee.setEmploymentType(MyTimeUtils.FULL_TIME);
            }
            String empStatus =  employee.getEmpStatus().trim();
            if( empStatus.isEmpty() ) {
            	if(null == employee.getEndDate()) {
            		employee.setEmpStatus(MyTimeUtils.ACTIVE);
            	}else {
                	employee.setEmpStatus(MyTimeUtils.IN_ACTIVE_SPACE);
                }
            }else if ( (empStatus.equalsIgnoreCase(MyTimeUtils.IN_ACTIVE) || empStatus.equalsIgnoreCase(MyTimeUtils.IN_ACTIVE_SPACE)  
            		|| empStatus.equalsIgnoreCase(MyTimeUtils.IN_HYPEN_ACTIVE_SPACE)) && null != employee.getEndDate()   ) {
            	employee.setEmpStatus(MyTimeUtils.IN_ACTIVE_SPACE);
            }
            if (!employee.getGender().trim().isEmpty()) {
            	if(employee.getGender().equalsIgnoreCase(MyTimeUtils.MALE)) {
            		employee.setGender(MyTimeUtils.MALE);
            	}else if(employee.getGender().equalsIgnoreCase(MyTimeUtils.FEMALE)){
            		employee.setGender(MyTimeUtils.FEMALE);
            	}
            }
            assigingEmployeeRole(employee,empId);
        } catch (MyTimeException e) {
            e.printStackTrace();
        }
	}
	
	private String validateExcelRecords(List<EmployeeRoles> employees) {
		List<String> inValidEmpRecList = new ArrayList<String>();
		String result = "";
		boolean mandatoryFlag = true;
		int rowNumber = 1;
		List<EmployeeRoles> invalidEmpRecs = new ArrayList<EmployeeRoles>();
		
		Set<String> empIdsSet = employees.stream().map(EmployeeRoles :: getEmployeeId).collect(Collectors.toSet());
		
		List<EmployeeRoles> existingEmployess = employeeRolesRepo.findByEmployeeIdIn(empIdsSet);
		if(existingEmployess.size() > MyTimeUtils.INT_ZERO) {
			result = "Below employee records already existed : \n" + existingEmployess.stream().map(EmployeeRoles :: getEmployeeId).collect(Collectors.toSet()).toString();
			employees.removeAll(existingEmployess);
		}
		for(EmployeeRoles emp : employees) {
			rowNumber += 1;
			mandatoryFlag = importExcelMandatoryColumnsValidation(emp);
			
			if (mandatoryFlag) {
				importExcelAdditionalColumnVAlidation(emp, inValidEmpRecList,invalidEmpRecs, rowNumber);
			} else {
				addInValidRecord(inValidEmpRecList, invalidEmpRecs, emp, rowNumber);
			}
		}
		if(invalidEmpRecs.size() > MyTimeUtils.INT_ZERO) {
			employees.removeAll(invalidEmpRecs);
			result +="Please check the following row number records : \n"+ inValidEmpRecList.toString();
		}
		return result;
	}
	
	private void addInValidRecord(List<String> inValidEmpRecList, List<EmployeeRoles> invalidEmpRecs, EmployeeRoles emp, int rowNumber) {
		inValidEmpRecList.add(Integer.toString(rowNumber));
		invalidEmpRecs.add(emp);
	}
	
	
	private String allColumnsExistCheckInExcel(EmployeeRoles emp) {
		String resultString = "In excel sheet following coloumns are missing::";
		StringBuffer result = new StringBuffer(resultString);
		Method[] empMethodList = emp.getClass().getMethods();
		for (Method empMethod : empMethodList) {
			String mName = empMethod.getName();
			if(mName.startsWith("get") && isMethodInvocationRequired(mName)) {
				try {
					Object returnData = empMethod.invoke(emp);
					if (returnData == null) {
						mName = mName.substring(3, mName.length());
						result.append(mName).append(MyTimeUtils.CAMA);
					}
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}
		resultString = result.substring(resultString.length()-1, result.length()-1);
		if (resultString.length() > 0) {
			resultString = result.substring(0, result.length()-1);
		}
		return resultString;
	}
	
	private boolean isMethodInvocationRequired(String mName) {
		boolean isRequired = true;
		if (mName.contains("getCreatedBy")) {
			isRequired = false;
		}
		if(mName.contains("getModifiedBy")) {
			isRequired = false;
		}
		if (mName.contains("getCreatedOn")) {
			isRequired = false;
		}
		if(mName.contains("getLastModifiedOn")) {
			isRequired = false;
		}
		if(mName.contains("getEndDate")) {
			isRequired = false;
		}
		if (mName.contains("getId")) {
			isRequired = false;
		}
		if (mName.contains("getClass")) {
			isRequired = false;
		}
		if (mName.contains("getPassportExpiryDate")) {
			isRequired = false;
		}
		if (mName.contains("getB1ExpiryDate")) {
			isRequired = false;
		}
		if (mName.contains("getDateOfBirth")) {
			isRequired = false;
		}
		return isRequired;
	}
	
	private boolean importExcelMandatoryColumnsValidation(EmployeeRoles emp) {
		boolean mandatoryFlag = true;
		
		if(! DataValidations.validateNumber(emp.getEmployeeId())) {
			mandatoryFlag = false;
		}else if(! DataValidations.validateName(emp.getEmployeeName())) {
			mandatoryFlag = false;
		}else if(! DataValidations.isValidGender(emp.getGender())) {
			mandatoryFlag = false;
		}else if(! DataValidations.isValidDate(emp.getDateOfJoining())) {
			mandatoryFlag = false;   				
		}else if(! DataValidations.isValidFunctionalGroup(emp.getFunctionalGroup(),masterDataRepo)) {
			mandatoryFlag = false;
		}else if(! DataValidations.isValidDesignation(emp.getDesignation(),masterDataRepo)) {
			mandatoryFlag = false;
		}else if(! DataValidations.isValidWorkLocation(emp.getEmpLocation(), locationRepo)) {
			mandatoryFlag = false;
		}else if(! DataValidations.isValidEmploymentType(emp.getEmploymentType(),masterDataRepo)) {
			mandatoryFlag = false;
		}else if(! DataValidations.isValidRole(emp.getRole(),masterDataRepo)) {
			mandatoryFlag =  false;
		}else if(! DataValidations.isYesOrNo(emp.getHasPassort())) {
			mandatoryFlag =  false;
		}else if(! DataValidations.isYesOrNo(emp.getHasB1())) {
			mandatoryFlag = false;
		}else if(!DataValidations.isValidEmail(emp.getEmailId())) {
			mandatoryFlag = false;
		}
		return mandatoryFlag;		
	}
	
	
	private void importExcelAdditionalColumnVAlidation(EmployeeRoles emp,List<String> inValidEmpRecList, List<EmployeeRoles> invalidEmpRecs, int rowNumber) {
		if (!DataValidations.isAgeGreaterThanTwenty(emp.getDateOfBirth(), emp.getDateOfJoining())) {
			addInValidRecord(inValidEmpRecList, invalidEmpRecs, emp, rowNumber);
			return;
		}
		if (MyTimeUtils.YES.equalsIgnoreCase(emp.getHasPassort().trim())|| MyTimeUtils.STRING_Y.equalsIgnoreCase(emp.getHasPassort().trim())) {
			if (!DataValidations.isFutureDate(emp.getPassportExpiryDate())) {
				addInValidRecord(inValidEmpRecList, invalidEmpRecs, emp, rowNumber);
				return;
			}
		}
		if ( emp.getHasPassort().trim().isEmpty() || MyTimeUtils.NO.equalsIgnoreCase(emp.getHasPassort().trim())|| MyTimeUtils.STRING_N.equalsIgnoreCase(emp.getHasPassort().trim())) {
			if(null != emp.getPassportExpiryDate() || null != emp.getHasB1().trim() || null != emp.getB1ExpiryDate()) {
				addInValidRecord(inValidEmpRecList, invalidEmpRecs, emp, rowNumber);
				return;
			}
		}
		if ((MyTimeUtils.YES.equals(emp.getHasB1()) || MyTimeUtils.STRING_Y.equals(emp.getHasB1()))&& !DataValidations.isFutureDate(emp.getB1ExpiryDate())) {
			addInValidRecord(inValidEmpRecList, invalidEmpRecs, emp, rowNumber);
			return;
		}
		if (!emp.getEmpStatus().trim().isEmpty()) {
			if( null != emp.getEndDate() &&  (
					emp.getEmpStatus().trim().equalsIgnoreCase(MyTimeUtils.IN_ACTIVE) || 
					emp.getEmpStatus().trim().equalsIgnoreCase(MyTimeUtils.IN_ACTIVE_SPACE) || 
					emp.getEmpStatus().trim().equalsIgnoreCase(MyTimeUtils.IN_HYPEN_ACTIVE_SPACE) )) {
				addInValidRecord(inValidEmpRecList, invalidEmpRecs, emp, rowNumber);
				return;
			}
			if (emp.getEmpStatus().trim().equalsIgnoreCase(MyTimeUtils.ACTIVE) && null != emp.getEndDate()) {
				addInValidRecord(inValidEmpRecList, invalidEmpRecs, emp, rowNumber);
				return;
			}
		}
	}
	
	private String duplicateEmpIAndEmptyEmpIdsCheckInImportedExcel(List<EmployeeRoles> employees) {
		int rowNum = MyTimeUtils.INT_TWO;
		StringBuffer emptyEmpIds = new StringBuffer();
		StringBuffer duplicteEmpIds = new StringBuffer();
		List<String> empIdsList = new ArrayList<String>();
		String result = "";
		for (EmployeeRoles emp : employees) {
			String empId = emp.getEmployeeId().trim();
			if(empId.isEmpty()) {
				employees.remove(emp);
				emptyEmpIds.append(rowNum).append(MyTimeUtils.CAMA);
			}else if( empIdsList.contains(empId)) {
				employees.remove(emp);
				duplicteEmpIds.append(empId).append(MyTimeUtils.CAMA);
			}else {
				empIdsList.add(empId);// For, Duplicate check.
			}
			++rowNum;
		}

		if (emptyEmpIds.length() > 0 ) {
			result = "Below employee records have empty employee id :"  + emptyEmpIds.toString();
		}
		if (duplicteEmpIds.length() > 0) {
			result += ":: \n Below employee records have duplicate employee Ids " + duplicteEmpIds.toString();
		}
		return result; 
	}
}
