package com.nisum.mytime.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
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 com.nisum.mytime.exception.handler.MyTimeException;
import com.nisum.mytime.model.Account;
import com.nisum.mytime.model.Designation;
import com.nisum.mytime.model.EmpLoginData;
import com.nisum.mytime.model.EmployeeRoles;
import com.nisum.mytime.model.Location;
import com.nisum.mytime.model.MasterData;
import com.nisum.mytime.model.ProjectTeamMate;
import com.nisum.mytime.model.Shift;
import com.nisum.mytime.model.Skill;
import com.nisum.mytime.repository.AccountRepo;
import com.nisum.mytime.repository.DesignationRepo;
import com.nisum.mytime.repository.EmployeeRolesRepo;
import com.nisum.mytime.repository.LocationRepo;
import com.nisum.mytime.repository.MasterDataRepo;
import com.nisum.mytime.repository.ProjectTeamMatesRepo;
import com.nisum.mytime.repository.ShiftRepo;
import com.nisum.mytime.repository.TechnologyRepo;
import com.nisum.mytime.utils.MyTimeUtils;
import com.nisum.mytime.utils.PdfReportGenerator;

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

    @Autowired
    private EmployeeRolesRepo employeeRolesRepo;

    @Autowired
    private ProjectTeamMatesRepo projectTeamMatesRepo;

    @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;

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

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

    @Override
    public String generatePdfReport(long id, String fromDate, String toDate)
            throws MyTimeException {
        return pdfReportGenerator.generateEmployeeReport(id, fromDate, toDate);
    }

    @Override
    public List<EmployeeRoles> getEmployeeRoles() throws MyTimeException {
        return employeeRolesRepo.findAll();
    }

    @Override
    public EmployeeRoles assigingEmployeeRole(EmployeeRoles employeeRoles)
            throws MyTimeException {
        employeeRoles.setCreatedOn(new Date());
        employeeRoles.setEmpStatus("Active");
        employeeRoles.setEmploymentType("Full Time");
        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) {
        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("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());
        FindAndModifyOptions options = new FindAndModifyOptions();
        options.returnNew(true);
        options.upsert(true);
        EmployeeRoles emp = mongoTemplate.findAndModify(query, update, options,
                EmployeeRoles.class);
        try {
            List<ProjectTeamMate> employeeProfiles = projectTeamMatesRepo
                    .findByEmployeeId(emp.getEmployeeId());
            if (employeeProfiles != null && !employeeProfiles.isEmpty()) {
                for (ProjectTeamMate profile : employeeProfiles) {
                    profile.setRole(emp.getRole());
                    ;
                    projectTeamMatesRepo.save(profile);
                }
            }
        } 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 mobileNumberChnaged = false;
        boolean designationChnaged = false;
        employeeRoles.setLastModifiedOn(new Date());
        EmployeeRoles existingEmployee = employeeRolesRepo
                .findByEmployeeId(employeeRoles.getEmployeeId());
        String newMobileNumber = employeeRoles.getMobileNumber();
        String designation = employeeRoles.getDesignation();
        if (newMobileNumber != null && !newMobileNumber.equalsIgnoreCase("")) {
            if ((existingEmployee != null
                    && existingEmployee.getMobileNumber() != null
                    && !existingEmployee.getMobileNumber()
                            .equalsIgnoreCase(newMobileNumber))
                    || (existingEmployee.getMobileNumber() == null)) {
                mobileNumberChnaged = true;
            }
        }
        if (designation != null && !designation.equalsIgnoreCase("")) {
            if ((existingEmployee != null
                    && existingEmployee.getDesignation() != null
                    && !existingEmployee.getDesignation()
                            .equalsIgnoreCase(newMobileNumber))
                    || (existingEmployee.getDesignation() == null)) {
                designationChnaged = true;
            }
        }
        existingEmployee.setDesignation(employeeRoles.getDesignation());
        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 (mobileNumberChnaged || designationChnaged) {
            try {
                List<ProjectTeamMate> employeeProfiles = projectTeamMatesRepo
                        .findByEmployeeId(employeeRoles.getEmployeeId());
                if (employeeProfiles != null && !employeeProfiles.isEmpty()) {
                    for (ProjectTeamMate profile : employeeProfiles) {
                        profile.setDesignation(
                                employeeRolesDB.getDesignation());
                        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 {
        // TODO Auto-generated method stub
        return masterDataRepo.findAll();
    }
}
