package com.nisum.myteam.service.impl;

import java.util.*;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
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.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.nisum.myteam.exception.handler.MyTeamException;
import com.nisum.myteam.model.dao.Billing;
import com.nisum.myteam.model.dao.Employee;
import com.nisum.myteam.model.dao.Project;
import com.nisum.myteam.model.dao.Resource;
import com.nisum.myteam.repository.BillingRepo;
import com.nisum.myteam.repository.EmployeeRepo;
import com.nisum.myteam.repository.ProjectRepo;
import com.nisum.myteam.repository.ResourceRepo;
import com.nisum.myteam.service.IEmployeeRoleService;
import com.nisum.myteam.service.IResourceService;
import com.nisum.myteam.service.IRoleService;
import com.nisum.myteam.utils.MyTeamResultDTO;
import com.nisum.myteam.utils.MyTeamUtils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateUtils;
import org.bson.types.ObjectId;

@Service
@Slf4j
public class ResourceService implements IResourceService {

	@Autowired
	private BillingService billingService;

	@Autowired
	private EmployeeShiftService empShiftService;

	@Autowired
	private ResourceRepo resourceRepo;

	@Autowired
	private MongoTemplate mongoTemplate;

	@Autowired
	private IRoleService roleInfoService;

	@Autowired
	private IEmployeeRoleService roleMappingService;

	@Autowired
	private ProjectRepo projectRepo;

	@Autowired
	private BillingRepo billingRepo;

	@Autowired
	private ProjectService projectService;

	@Autowired
	private EmployeeRepo employeeRepo;

	public Resource save(Resource resource) {
		return resourceRepo.save(resource);
	}

	@Override
	public Resource addResource(Resource resourceReq, String loginEmpId) throws MyTeamException {

		// calling a method
		updateProjectEndDateForResource(resourceReq, loginEmpId);

		resourceReq.setAuditFields(loginEmpId, MyTeamUtils.CREATE);
		Resource resourcePersisted = resourceRepo.save(resourceReq);


		// Get Active billings for Nisum Bench Project.
		List<Billing> listBD = billingService.getActiveBillings(resourcePersisted.getEmployeeId(), "Nisum0000");

		Date startDate = resourcePersisted.getStartDate() != null ? resourcePersisted.getStartDate() : new Date();
		if (listBD != null && listBD.size() > 0) {
			Billing bDetails = listBD.get(0);
			if (startDate.compareTo(bDetails.getBillingStartDate()) > 0) {
				bDetails.setBillingEndDate(DateUtils.truncate(DateUtils.addDays(startDate, -1), Calendar.DATE));
			} else {
				bDetails.setBillingEndDate(startDate);
			}
			bDetails.setActive(false);
			billingService.updateBilling(bDetails, loginEmpId);
		}

		Billing billings = new Billing();
		billings.setEmployeeId(resourcePersisted.getEmployeeId());
		billings.setEmployeeName(resourcePersisted.getEmployeeName());
		billings.setProjectId(resourcePersisted.getProjectId());
		billings.setProjectName(resourcePersisted.getProjectName());
		billings.setBillableStatus(resourcePersisted.getBillableStatus());
		billings.setAccount(resourcePersisted.getAccount());
		billings.setActive(resourcePersisted.isActive());
		if (!resourceReq.getProjectId().equalsIgnoreCase("Nisum0000")) {
			billings.setBillingStartDate(DateUtils.truncate(resourcePersisted.getNewBillingStartDate(), Calendar.DATE));
		} else {
			billings.setBillingStartDate(DateUtils.truncate(resourcePersisted.getStartDate(), Calendar.DATE));
		}
		if (resourcePersisted.getEndDate() != null) {
			billings.setBillingEndDate(DateUtils.truncate(resourcePersisted.getEndDate(), Calendar.DATE));
		}

		billingService.addBilling(billings, loginEmpId);

		empShiftService.addEmployeeShift(resourceReq, loginEmpId);

		// calling method
		addOrUpdateTeamMateRole(resourceReq.getRole(), resourceReq.getProjectId(), resourceReq.getEmployeeId(), false,
				loginEmpId);

		return resourcePersisted;
	}

	@Override
	public String updateResource(Resource resourceReq, String loginEmpId) throws MyTeamException {
		// String result = null;
		MyTeamResultDTO myResultDto = new MyTeamResultDTO();
		myResultDto.setResultCode(MyTeamResultDTO.SUCCESS_CODE);

		myResultDto.setResultData("TeamMate updated successfuly");

		Resource existingResource = resourceRepo.findById(resourceReq.getId());
		log.info("From database: Resource Details::"+existingResource);


		Date resEndDate = resourceReq.getEndDate();
		log.info("ResEndDate::"+resEndDate);
		List<Billing> listBD = billingService.getActiveBillings(resourceReq.getEmployeeId(), resourceReq.getProjectId());

		// Handling past or present endDate (To "Inactive" the Resource)
		if (resEndDate.compareTo(new Date()) <= 0 && resEndDate.compareTo(existingResource.getEndDate()) != 0) {
			existingResource.setActive(false);
			existingResource.setEndDate(resEndDate);
			if (listBD != null && !listBD.isEmpty()) {
				Billing billingDetailsExisting = listBD.get(0);
				Date actualEndDate = resEndDate;
				billingDetailsExisting.setBillingEndDate(actualEndDate);
				billingDetailsExisting.setActive(false);
				billingService.updateBilling(billingDetailsExisting, loginEmpId);
			}

			Project project = projectRepo.findByProjectId(MyTeamUtils.BENCH_PROJECT_ID);

			Resource newBenchAllocation = new Resource();
			Billing billingDetails = new Billing();
			billingDetails.setBillableStatus(MyTeamUtils.BENCH_BILLABILITY_STATUS);
			billingDetails.setBillingStartDate(resEndDate);
			billingDetails.setAccount(MyTeamUtils.BENCH_ACCOUNT);
			billingDetails.setActive(true);
			billingDetails.setEmployeeId(existingResource.getEmployeeId());
			billingDetails.setEmployeeName(existingResource.getEmployeeName());
			// billingDetails.setCreateDate(new Date());// Commented as added
			// common audit fields
			billingDetails.setProjectId(MyTeamUtils.BENCH_PROJECT_ID);
			billingDetails.setProjectName(MyTeamUtils.FREE_POLL);
			if (project != null) {
				billingDetails.setBillingEndDate(project.getProjectEndDate());
				newBenchAllocation.setAccountId(project.getAccountId());
				newBenchAllocation.setDomainId(project.getDomainId());
				newBenchAllocation.setProjectName(project.getProjectName());
				newBenchAllocation.setEndDate(project.getProjectEndDate());
			}
			billingService.addBilling(billingDetails, loginEmpId);

			newBenchAllocation.setBillableStatus(MyTeamUtils.BENCH_BILLABILITY_STATUS);
			newBenchAllocation.setDesignation(existingResource.getDesignation());
			newBenchAllocation.setEmailId(existingResource.getEmailId());
			newBenchAllocation.setEmployeeId(existingResource.getEmployeeId());
			newBenchAllocation.setActive(true);
			newBenchAllocation.setEmployeeName(existingResource.getEmployeeName());
			newBenchAllocation.setProjectId(MyTeamUtils.BENCH_PROJECT_ID);
			newBenchAllocation.setShift(existingResource.getShift());
			newBenchAllocation.setRole(existingResource.getRole());

			Calendar cal = Calendar.getInstance();
			cal.setTime(resEndDate);
			cal.add(Calendar.DAY_OF_MONTH, 1);

			newBenchAllocation.setStartDate(DateUtils.truncate(cal.getTime(), Calendar.DATE));
			newBenchAllocation.setNewBillingStartDate(DateUtils.truncate(cal.getTime(), Calendar.DATE));
			newBenchAllocation.setAuditFields(loginEmpId, MyTeamUtils.CREATE);// Setting
																				// audit
																				// fields
			resourceRepo.save(newBenchAllocation);

			myResultDto.setResultCode(MyTeamResultDTO.SUCCESS_CODE);
			myResultDto.setResultData(
					"Resource Successfully moved from " + resourceReq.getProjectName() + " project to Bench.");
		} else {


			log.info("Before compare billable status::");
			log.info("Existing Resource:::"+existingResource);
			log.info("Resource Request Details::"+resourceReq);

			// Handling Resource Project Billability Status change
			if (resourceReq.getBillableStatus() != null && existingResource.getBillableStatus() != null
					&& !existingResource.getBillableStatus().equalsIgnoreCase(resourceReq.getBillableStatus())) {
				/*
				 * List<BillingDetails> bDetailsList =
				 * teamMatesBillingRepo.findByEmployeeId(projectTeamMate.
				 * getEmployeeId()).stream() .filter(e ->
				 * (!e.isActive())).sorted(Comparator.comparing(BillingDetails::
				 * getBillingEndDate).reversed()) .collect(Collectors.toList());
				 */
				String result = validateBillabilityStartDate(listBD, resourceReq);
				if (result != null) { // Invalid Billability Start date
					return result;
				}
				if (listBD != null && !listBD.isEmpty()) {
					Billing billingDetails = listBD.get(0);
					Calendar cal = Calendar.getInstance();
					cal.setTime(resourceReq.getNewBillingStartDate());
					cal.add(Calendar.DAY_OF_MONTH, -1);
					Date startDate = existingResource.getNewBillingStartDate() != null
							? existingResource.getNewBillingStartDate() : existingResource.getStartDate();
					if (startDate.getDate() == resourceReq.getNewBillingStartDate().getDate()) {
						billingDetails.setBillingEndDate(
								DateUtils.truncate(resourceReq.getNewBillingStartDate(), Calendar.DATE));
					} else {
						billingDetails.setBillingEndDate(DateUtils.truncate(cal.getTime(), Calendar.DATE));
					}
					billingDetails.setActive(false);
					billingService.updateBilling(billingDetails, loginEmpId);
				}
				Billing billings = new Billing();
				billings.setEmployeeId(resourceReq.getEmployeeId());
				billings.setEmployeeName(resourceReq.getEmployeeName());
				billings.setProjectId(resourceReq.getProjectId());
				billings.setAccount(existingResource.getAccount());
				billings.setProjectName(resourceReq.getProjectName());
				billings.setBillableStatus(resourceReq.getBillableStatus());
				billings.setActive(true);
				billings.setBillingStartDate(DateUtils.truncate(resourceReq.getNewBillingStartDate(), Calendar.DATE));
				billings.setBillingEndDate(DateUtils.truncate(resEndDate, Calendar.DATE));
				// billings.setCreateDate(new Date());// Commented as added
				// common audit fields
				billingService.addBilling(billings, loginEmpId);

				existingResource.setBillableStatus(resourceReq.getBillableStatus());
				existingResource
						.setNewBillingStartDate(DateUtils.truncate(resourceReq.getNewBillingStartDate(), Calendar.DATE));

			} else {// Handling Billability Start Date change
				List<Billing> bDetailsList = billingRepo.findByEmployeeId(resourceReq.getEmployeeId()).stream()
						.filter(e -> (!e.isActive()))
						.sorted(Comparator.comparing(Billing::getBillingEndDate).reversed())
						.collect(Collectors.toList());
				String result = validateBillabilityStartDate(bDetailsList, resourceReq);
				if (result != null) { // Invalid Billability Start date
					return result;
				}
				if (bDetailsList != null && !bDetailsList.isEmpty()) {
					Calendar cal = Calendar.getInstance();
					cal.setTime(resourceReq.getNewBillingStartDate());
					cal.add(Calendar.DAY_OF_MONTH, -1);
					Billing preBillingDetails = bDetailsList.get(0);
					if (preBillingDetails.getBillingStartDate().getDate() == resourceReq.getNewBillingStartDate()
							.getDate()) {
						preBillingDetails.setBillingEndDate(
								DateUtils.truncate(resourceReq.getNewBillingStartDate(), Calendar.DATE));
					} else {
						preBillingDetails.setBillingEndDate(DateUtils.truncate(cal.getTime(), Calendar.DATE));
					}
					billingService.updateBilling(preBillingDetails, loginEmpId);
				}
				if (listBD != null && !listBD.isEmpty()) {
					Billing billingDetails = listBD.get(0);
					billingDetails
							.setBillingStartDate(DateUtils.truncate(resourceReq.getNewBillingStartDate(), Calendar.DATE));
					billingDetails.setBillingEndDate(DateUtils.truncate(resEndDate, Calendar.DATE));
					billingService.addBilling(billingDetails, loginEmpId);
				}
				existingResource
						.setNewBillingStartDate(DateUtils.truncate(resourceReq.getNewBillingStartDate(), Calendar.DATE));
			}
			if (resEndDate.compareTo(existingResource.getEndDate()) != 0) {
				existingResource.setEndDate(resEndDate);
			}
		}

		if (MyTeamResultDTO.SUCCESS_CODE.equals(myResultDto.getResultCode())) {
			// Handling Role change
			if ((existingResource.getRole() != null && !existingResource.getRole().equalsIgnoreCase(resourceReq.getRole()))
					|| (resourceReq.getRole() != null)
							&& !resourceReq.getRole().equalsIgnoreCase(existingResource.getRole())) {
				existingResource.setRole(resourceReq.getRole());
				addOrUpdateTeamMateRole(resourceReq.getRole(), resourceReq.getProjectId(), resourceReq.getEmployeeId(), true,
						loginEmpId);
			}
			// Handling Shift change
			if ((existingResource.getShift() != null
					&& !existingResource.getShift().equalsIgnoreCase(resourceReq.getShift()))
					|| (resourceReq.getShift() != null)
							&& !resourceReq.getShift().equalsIgnoreCase(existingResource.getShift())) {

				empShiftService.updateEmployeeShift(existingResource, loginEmpId);

				existingResource.setShift(resourceReq.getShift());
				Employee employeeDB = employeeRepo.findByEmployeeId(resourceReq.getEmployeeId());
				employeeDB.setShift(resourceReq.getShift());
				employeeDB.setModifiedBy(loginEmpId);
				employeeDB.setLastModifiedOn(new Date());
				employeeRepo.save(employeeDB);
			}
			existingResource.setAuditFields(loginEmpId, MyTeamUtils.UPDATE);// Setting
																			// audit
																			// fields
			resourceRepo.save(existingResource);
		}
		return myResultDto.getResultData()[myResultDto.getDataArrayCounter()];
	}

	private String validateBillabilityStartDate(List<Billing> billingList, Resource resource) {
		String response = null;
		if (billingList != null && billingList.size() > 0) {
			Billing billing = billingList.get(0);
			if (resource.getNewBillingStartDate().compareTo(billing.getBillingStartDate()) < 0) {
				response = "Resource Billability Start Date (" + resource.getNewBillingStartDate() + " ) for "
						+ resource.getBillableStatus() + " status should be later than previous billability ("
						+ billing.getBillableStatus() + " status) Start Date ( " + billing.getBillingStartDate() + ").";
			}
		} else {
			response = validateAgainstDOJ(resource);
		}
		return response;
	}


	@Override
	public Resource deleteResource(String empId, String projectId, ObjectId id, String loginEmpId) {
		Resource existingResource = resourceRepo.findById(id);
		existingResource.setActive(false);
		existingResource.setEndDate(new Date());
		Billing billingDetails = new Billing();
		billingDetails.setBillableStatus("Non-Billable");
		billingDetails.setBillingStartDate(new Date());
		billingDetails.setAccount("Nisum");
		billingDetails.setActive(true);
		billingDetails.setEmployeeId(existingResource.getEmployeeId());
		billingDetails.setEmployeeName(existingResource.getEmployeeName());
		// billingDetails.setCreateDate(new Date());// Commented as added common
		// audit fields
		billingDetails.setProjectId("Nisum0000");
		billingDetails.setProjectName(MyTeamUtils.FREE_POLL);
		billingService.addBilling(billingDetails, loginEmpId);
		List<Billing> listBD = billingService.getActiveBillings(empId, projectId);
		if (listBD != null && !listBD.isEmpty()) {
			Billing billingDetailsExisting = listBD.get(0);
			Date d = new Date();
			d.setDate(d.getDate() - 1);
			billingDetailsExisting.setBillingEndDate(d);
			billingDetailsExisting.setActive(false);
			billingService.updateBilling(billingDetailsExisting, loginEmpId);
		}
		existingResource.setAuditFields(loginEmpId, MyTeamUtils.UPDATE);// Setting
																		// audit
																		// fields
		resourceRepo.save(existingResource);
		Resource resourceBench = new Resource();
		resourceBench.setAccount("Nisum");
		resourceBench.setBillableStatus("Non-Billable");
		resourceBench.setDesignation(existingResource.getDesignation());
		resourceBench.setEmailId(existingResource.getEmailId());
		resourceBench.setEmployeeId(existingResource.getEmployeeId());
		resourceBench.setActive(true);
		resourceBench.setEmployeeName(existingResource.getEmployeeName());
		resourceBench.setProjectId("Nisum0000");
		resourceBench.setStartDate(new Date());
		Project p = projectRepo.findByProjectId("Nisum0000");
		resourceBench.setProjectName(p.getProjectName());
		// newBenchAllocation.setManagerId(p.getManagerId());
		// newBenchAllocation.setManagerName(p.getManagerName());
		resourceBench.setAuditFields(loginEmpId, MyTeamUtils.CREATE);// Setting
																		// audit
																		// fields
		Resource resource=resourceRepo.save(resourceBench);
		empShiftService.updateEmployeeShift(existingResource, loginEmpId);

		return  resource;
	}

	// Update ProjectEndDate column data in ProjectTeamMate.
	private void updateProjectEndDateForResource(Resource resource, String loginEmpId) {
		List<Resource> projectTeamMateList = mongoTemplate
				.find(prepareQuery(resource.getEmployeeId(), MyTeamUtils.ENDDATE_COLUMN), Resource.class);
		log.info("the project teamates list is::" + projectTeamMateList);
		if (!CollectionUtils.isEmpty(projectTeamMateList)) {
			Resource teamMate = projectTeamMateList.get(0);
			if (resource.getNewBillingStartDate() != null) {
				Date d = resource.getNewBillingStartDate();
				Calendar cal = Calendar.getInstance();
				cal.setTime(d);
				cal.add(Calendar.DAY_OF_MONTH, -1);
				Date oneDayLess = cal.getTime();
				Date startDate = teamMate.getNewBillingStartDate() != null ? teamMate.getNewBillingStartDate()
						: teamMate.getStartDate();
				if (startDate.getDate() == resource.getNewBillingStartDate().getDate()) {
					teamMate.setEndDate(DateUtils.truncate(resource.getEndDate(), Calendar.DATE));
				} else {
					teamMate.setEndDate(DateUtils.truncate(oneDayLess, Calendar.DATE));
				}
			}

			teamMate.setActive(false);
			teamMate.setAuditFields(loginEmpId, MyTeamUtils.UPDATE);// Setting
																	// audit
																	// fields
			resourceRepo.save(teamMate);
		}

	}

	private Query prepareQuery(String employeeId, String dateColumn) {
		Query query = new Query();
		query.addCriteria(Criteria.where(MyTeamUtils.EMPLOYEE_ID).is(employeeId));
		query.limit(MyTeamUtils.ONE);
		query.with(new Sort(Sort.Direction.DESC, dateColumn));
		return query;
	}

	private void addOrUpdateTeamMateRole(String role, String projectId, String empId, boolean isUpdate,
			String loginEmpId) throws MyTeamException {
		Project project = projectRepo.findByProjectId(projectId);
		int operationType = 0; // 0 = No Operation, 1 = Added, 2 = Removed
		if (role != null && role.equals("Lead")) {
			if (project.getManagerIds() == null) {
				project.setManagerIds(Arrays.asList(empId));
				operationType = 1;
			} else if (project.getManagerIds() != null && !project.getManagerIds().contains(empId)) {
				project.getManagerIds().add(empId);
				operationType = 1;
			}
		} else if (isUpdate && project.getManagerIds() != null && project.getManagerIds().contains(empId)) {
			project.getManagerIds().remove(empId);
			operationType = 2;
		}
		if (operationType > 0) {
			project.setAuditFields(loginEmpId, MyTeamUtils.UPDATE);
			projectRepo.save(project);
			Query query = new Query(Criteria.where("employeeId").is(empId).and("role").is("Lead"));
			List<Resource> projectMates = mongoTemplate.find(query, Resource.class);
			String roleId = roleInfoService.getRole(MyTeamUtils.LEAD);
			if (operationType == 1) {
				roleMappingService.addEmployeeRole(empId, roleId);
			} else if (projectMates.size() == 0 || operationType == 2) {
				roleMappingService.deleteRole(empId, roleId);
			}
		}
	}

	public void addResources(Employee employee, String loginEmpId) {
		List<Resource> resourceList = resourceRepo.findByEmployeeId(employee.getEmployeeId());
		if (resourceList != null && !resourceList.isEmpty()) {
			for (Resource resource : resourceList) {
				resource.setRole(employee.getRole());
				resource.setAuditFields(loginEmpId, MyTeamUtils.UPDATE);
				resourceRepo.save(resource);
			}
		}

		// return null;
	}

	public void inactivateResource(Employee employeeReq, Employee employeeUpdated, String loginEmpId) {
		// inactive the employee from the assigned project
		if (employeeReq.getEmpStatus().equals(MyTeamUtils.IN_ACTIVE_SPACE) && employeeReq.getEndDate() != null
				&& employeeReq.getEndDate().compareTo(new Date()) <= 0) {

			List<Resource> resourcesList = resourceRepo.findByEmployeeIdAndActive(employeeReq.getEmployeeId(), true);
			if (resourcesList.size() == 1) {
				Resource resource = resourcesList.get(0);
				resource.setActive(false);
				resource.setEndDate(employeeReq.getEndDate());

				List<Billing> billingList = billingService.getActiveBillings(resource.getEmployeeId(),
						resource.getProjectId());
				if (billingList != null && !billingList.isEmpty()) {
					billingService.addBillingtoResource(billingList.get(0), employeeUpdated, loginEmpId);
				}
				resource.setAuditFields(loginEmpId, MyTeamUtils.UPDATE);
				resourceRepo.save(resource);
				empShiftService.updateEmployeeShift(resource, loginEmpId);
			}
		}
	}


	@Override
	public List<Resource> findByAccountAndActiveAndBillableStatus(String account, boolean status,
			String billableStatus) {
		return resourceRepo.findByAccountAndActiveAndBillableStatus(account, status, billableStatus);
	}

	@Override
	public List<Resource> getResourcesSortByStartDate(String employeeId) {
		Query query = prepareQuery(employeeId, MyTeamUtils.START_DATE);
		return mongoTemplate.find(query, Resource.class);
	}

	@Override
	public List<Resource> getResourcesForProject(String projectId, String statusFlag) {
		List<Resource> resourcesList = new ArrayList<>();
		List<Resource> resourceListPersisted = resourceRepo.findByProjectId(projectId);
		for (Resource resource : resourceListPersisted) {
			Date endDate = resource.getEndDate();
			if (endDate != null) {
				// Active
				if (statusFlag.equals(MyTeamUtils.ACTIVE) && endDate.compareTo(new Date()) >= 0)
					resourcesList.add(resource);
				else if (statusFlag.equals(MyTeamUtils.IN_ACTIVE) && endDate.compareTo(new Date()) < 0)
					resourcesList.add(resource);
				else if (statusFlag.equals(MyTeamUtils.BOTH))
					resourcesList.add(resource);
			}
		}
		return resourcesList;
	}

	@Override
	public List<Resource> getResourcesForEmployee(String empId) {
		return resourceRepo.findByEmployeeId(empId);
	}

	public List<Resource> getResourcesForProject(String projectId) {
		return resourceRepo.findByProjectId(projectId);
	}

	public List<Resource> getAllResources() {
		return resourceRepo.findAll();
	}

	@Override
	public List<Resource> getActiveResources(String empId) {
		List<Resource> resourcesList = new ArrayList<>();
		List<Resource> resourcesListPers = resourceRepo.findByEmployeeId(empId);
		for (Resource resource : resourcesListPers) {
			if (resource.isActive()) {
				resourcesList.addAll(resourceRepo.findByProjectId(resource.getProjectId()));
			}
		}
		return resourcesList;
	}

	@Override
	public List<Resource> getResourcesForActiveProjects() {
		List<Project> projects = projectService.getAllProjects();
		List<Resource> resourceList = new ArrayList<>();
		for (Project project : projects) {
			if (!"Completed".equalsIgnoreCase(project.getStatus())) {
				List<Resource> resourceListPersisted = getResourcesForProject(project.getProjectId());
				resourceList.addAll(resourceListPersisted);
			}

		}
		return resourceList;
	}

	@Override
	public List<Resource> getResourcesForShift(String shift) {
		List<Resource> resourcesListPers = null;
		List<Resource> resourcesList = new ArrayList<>();
		List<Project> projects = projectService.getAllProjects();
		for (Project project : projects) {
			if ("Active".equalsIgnoreCase(project.getStatus())) {
				resourcesListPers = getResourcesForProject(project.getProjectId());
				for (Resource resource : resourcesListPers) {
					if (resource.getShift() != null && resource.getShift().equalsIgnoreCase(shift)
							&& resource.isActive()) {
						resourcesList.add(resource);
					} else if (resource.getShift() == null && "Shift 1(9:00 AM - 6:00 PM)".equalsIgnoreCase(shift)
							&& resource.isActive())
						resourcesList.add(resource);
				}
			}
		}
		return resourcesList;
	}



    @Override
    public List<Resource> getResourcesUnderDeliveryLead(String deliveryLeadId) {
        List<String> projectIdsList = new ArrayList<>();
        List<Resource> resourcesList = new ArrayList<>();


        List<Project> projectsList = projectRepo.findByDeliveryLeadIds(deliveryLeadId);
        for (Project project : projectsList)
            projectIdsList.add(project.getProjectId());

        Query query = new Query(Criteria.where("projectId").in(projectIdsList));

        List<Resource> resourcesListPersisted = mongoTemplate.find(query, Resource.class);


        for (Resource resource : resourcesListPersisted) {
            if (!resource.getEmployeeId().equals(deliveryLeadId))
                resourcesList.add(resource);
        }
        return resourcesList;

    }




	@Override
	public HashMap<String,Object> verifyResourceAssignedToAnyProject(Resource resourceReq, String loginEmpId) throws MyTeamException {
		boolean flag = false;
		String projectName = null;
		String fromDate = null;
		String toDate = null;
		String result = null;
		HashMap<String, Object> responseMap = new HashMap<>();
		Resource resourcePersisted = null;

		List<Resource> resourceList = resourceRepo.findByEmployeeId(resourceReq.getEmployeeId()).stream()
				.filter(e -> !("Nisum0000".equalsIgnoreCase(e.getProjectId())))
				.sorted(Comparator.comparing(Resource::getEndDate).reversed())
				.collect(Collectors.toList());

		// Checking, if resource has existing project assignment.
		for (Resource resource : resourceList) {

			log.info("Resource::" + resource);
			if (resource.getEndDate() != null && (resource.getEndDate().compareTo(new Date()) > 0)) {
				flag = true;
				projectName = resource.getProjectName();
				fromDate = resource.getStartDate().toString();
				toDate = resource.getEndDate().toString();
				break;
			}
		}
		if (flag) {// If yes, error thrown to user.
			result = "Resource " + resourceReq.getEmployeeId() + " already Assigned to the " + projectName
					+ " Project" + " from " + fromDate + "to " + toDate;

		} else {// If no, validating new project assignment start date against previous project end date.
			result = validateNewProjectAssignmentStartDate(resourceList, resourceReq);
			if (result == null) {
				resourcePersisted = this.addResource(resourceReq, loginEmpId);
				result = "TeamMate added successfuly";

			}
		}
		responseMap.put("message", result);
		responseMap.put("resourceObj", resourcePersisted);
		return responseMap;

	}

	private String validateNewProjectAssignmentStartDate(List<Resource> resourceList, Resource resourceReq) {
		String response = null;
		if (resourceList != null && resourceList.size() > 0) {
			Resource resource = resourceList.get(0);
			if (resourceReq.getNewBillingStartDate().compareTo(resource.getEndDate()) <= 0) {
				response = "Resource Start Date (" + resourceReq.getNewBillingStartDate() +" ) in " + resourceReq.getProjectName()
				+ " project should be after " + resource.getProjectName() + " project End Date ( " + resource.getEndDate() + ").";
			}
		} else {
			response = validateAgainstDOJ(resourceReq);
		}
		return response;
	}

	private String validateAgainstDOJ(Resource resource) {
		String response = null;
		Date empDoj = employeeRepo.findByEmployeeId(resource.getEmployeeId()).getDateOfJoining();
		if (resource.getNewBillingStartDate().compareTo(empDoj) < 0) {
			response = "Resource Start Date (" + resource.getNewBillingStartDate() + " ) in "
					+ resource.getProjectName() + " project should not be before Date of Joining ( " + empDoj + ").";
		}
		return response;
	}

}
