package com.lz.modules.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.lz.common.utils.*;
import com.lz.modules.app.dao.DepartmentsDao;
import com.lz.modules.app.dto.*;
import com.lz.modules.app.dao.StaffDao;
import com.lz.modules.app.entity.*;
import com.lz.modules.app.service.*;
import com.lz.modules.equipment.entity.model.FindByNameModel;
import com.lz.modules.flow.model.DepartManagers;
import com.lz.modules.job.model.responseBo.DepartmentStaffBo;
import com.lz.modules.sys.entity.SysUserEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;


@Service("staffService")
@Slf4j
public class StaffServiceImpl extends ServiceImpl<StaffDao, StaffEntity> implements StaffService {

    protected final static org.slf4j.Logger logger = LoggerFactory.getLogger(StaffServiceImpl.class);

    @Resource
    StaffDao staffDao;
    @Resource
    StaffOccupationService staffOccupationService;
    @Resource
    StaffEducationService staffEducationService;
    @Resource
    StaffProjectExperienceService staffProjectExperienceService;
    @Resource
    StaffWorkTransferRecordService staffWorkTransferRecordService;
    @Resource
    DepartmentsService departmentsService;
    @Resource
    DepartmentsStaffRelateService departmentsStaffRelateService;
    @Autowired
    private DepartmentsDao departmentsDao;
    @Autowired
    private StaffService staffService;




    @Override
    public StaffEntity selectStaffById(Long id){
        return staffDao.selectStaffById(id);
    }



    @Override
    public Long insertStaff(StaffEntity staff){
        return staffDao.insertStaff(staff);
    }



    @Override
    public int updateStaffById(StaffEntity staff){
        return staffDao.updateStaffById(staff);
    }



    @Override
    public int updateCoverStaffById(StaffEntity staff){
        return staffDao.updateCoverStaffById(staff);
    }



    @Override
    public int deleteStaffById(Long id){
        return staffDao.deleteStaffById(id);
    }

    @Override
    public StaffEntity selectByPhone(String phone) {
        return staffDao.selectByPhone(phone);
    }

    @Override
    public StaffEntity selectStaffByEmployeeId(String employeeId){
        return staffDao.selectStaffByEmployeeId(employeeId);
    }

    @Override
    public List<StaffEntity> selectBySearchName(IPage page, FindByNameModel nameModel) {
        return staffDao.selectBySearchName(page, nameModel);
    }
    @Override
    public SysUserEntity getUser(String userName) {
        SysUserEntity user = null;
        StaffEntity staffEntity = staffDao.selectByPhone(userName);
        if(staffEntity != null){
            user = new SysUserEntity();
            user.setPassword(staffEntity.getPassword());
            user.setMobile(staffEntity.getMobile());
            user.setUserId(staffEntity.getId());
            user.setEmail(staffEntity.getEmail());
            user.setSalt(staffEntity.getSalt());
            user.setStatus(1);
            user.setType(1);
            user.setUsername(staffEntity.getMobile());
            user.setRealName(staffEntity.getName());
            user.setUserNo(staffEntity.getMobile());
            return user;
        }
        return null;
    }


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<StaffEntity> page = this.page(
                new Query<StaffEntity>().getPage(params),
                new QueryWrapper<StaffEntity>()
        );
        return new PageUtils(page);
    }

    @Override
    public boolean updateStaffsInfo(List<DepartmentStaffBo> staffs) {
        try {
            for (DepartmentStaffBo staffBo : staffs) {
                StaffEntity staffEntity = staffDao.getStaffInfoByOpenId(staffBo.getOpenId());
                StaffEntity staff = convertStaffEntity(staffBo);

                if (staffEntity != null) {
                    staff.setId(staffEntity.getId());

                    staffDao.updateStaff(staff);
                } else {
                    staffDao.addStaff(staff);

                }
                staffBo.setId(staff.getId());
            }
            return true;
        } catch (Exception e) {
            logger.info("updateDepartmentInfos error : " + e);
        }
        return false;
    }

    @Override
    public StaffEntity getStaffInfoByOpenId(String openId) {
        return staffDao.getStaffInfoByOpenId(openId);
    }

    @Override
    public StaffEntity getByName(String name) {
        return staffDao.getByName(name);
    }

    @Override
    public List<StaffDto> getStaffInfos(int currentPage, int limit, String departmentId, String name, Integer intoStaffStatus) {
        Integer staffStatus = 0;
        if (intoStaffStatus == 1) {
            staffStatus = intoStaffStatus;
        }
        List<StaffDto> staffInfos = staffDao.getStaffInfos(departmentId, name, staffStatus, limit, (currentPage - 1) * limit);

        return staffInfos;
    }

    @Override
    public int getStaffInfoCount(String departmentId, String name, Integer intoStaffStatus) {
        Integer staffStatus = 0;
        if (intoStaffStatus == 1) {
            staffStatus = intoStaffStatus;
        }
        return staffDao.getStaffInfoCount(departmentId, name, staffStatus);
    }

    @Override
    public StaffBaseInfoDto getBaseInfo(Long staffId) {
        return staffDao.getBaseInfo(staffId);
    }

    @Override
    public StaffStatisticalDto getStatisticalData(String departmentId, String beginDate, String endDate) {
        return staffDao.getStatisticalData(departmentId, beginDate, endDate);
    }

    @Override
    public List<GraphicsStatisticalDto> getGenderData(String departmentId, String beginDate, String endDate) {
        List<GraphicsStatisticalDto> graphicsStatisticals = staffDao.getGenderData(departmentId, beginDate, endDate);
        BigDecimal totalCount = BigDecimal.ZERO;
        for (GraphicsStatisticalDto graphicsStatisticalDto : graphicsStatisticals) {
            totalCount = totalCount.add(new BigDecimal(graphicsStatisticalDto.getNumber()));
        }
        for (GraphicsStatisticalDto graphicsStatisticalDto : graphicsStatisticals) {
            graphicsStatisticalDto.setRate(new BigDecimal(graphicsStatisticalDto.getNumber() * 100).divide(totalCount, 2, BigDecimal.ROUND_HALF_UP) + "%");
        }
        return graphicsStatisticals;
    }

    @Override
    public List<GraphicsStatisticalDto> getAgeData(String departmentId, String beginDate, String endDate) {
        List<GraphicsStatisticalDto> graphicsStatisticals = staffDao.getAgeData(departmentId, beginDate, endDate);
        BigDecimal totalCount = BigDecimal.ZERO;
        for (GraphicsStatisticalDto graphicsStatisticalDto : graphicsStatisticals) {
            totalCount = totalCount.add(new BigDecimal(graphicsStatisticalDto.getNumber()));
        }
        for (GraphicsStatisticalDto graphicsStatisticalDto : graphicsStatisticals) {
            graphicsStatisticalDto.setRate(new BigDecimal(graphicsStatisticalDto.getNumber() * 100).divide(totalCount, 2, BigDecimal.ROUND_HALF_UP) + "%");
        }
        return graphicsStatisticals;
    }

    @Override
    public List<GraphicsStatisticalDto> getJobSeniorityData(String departmentId, String beginDate, String endDate) {
        List<GraphicsStatisticalDto> graphicsStatisticals = staffDao.getJobSeniorityData(departmentId, beginDate, endDate);
        BigDecimal totalCount = BigDecimal.ZERO;
        for (GraphicsStatisticalDto graphicsStatisticalDto : graphicsStatisticals) {
            totalCount = totalCount.add(new BigDecimal(graphicsStatisticalDto.getNumber()));
        }
        for (GraphicsStatisticalDto graphicsStatisticalDto : graphicsStatisticals) {
            graphicsStatisticalDto.setRate(new BigDecimal(graphicsStatisticalDto.getNumber() * 100).divide(totalCount, 2, BigDecimal.ROUND_HALF_UP) + "%");
        }
        return graphicsStatisticals;
    }

    @Override
    public List<GraphicsStatisticalDto> getEducationData(String departmentId, String beginDate, String endDate) {
        List<GraphicsStatisticalDto> graphicsStatisticals = staffDao.getEducationData(departmentId, beginDate, endDate);
        BigDecimal totalCount = BigDecimal.ZERO;
        for (GraphicsStatisticalDto graphicsStatisticalDto : graphicsStatisticals) {
            totalCount = totalCount.add(new BigDecimal(graphicsStatisticalDto.getNumber()));
        }
        for (GraphicsStatisticalDto graphicsStatisticalDto : graphicsStatisticals) {
            graphicsStatisticalDto.setRate(new BigDecimal(graphicsStatisticalDto.getNumber() * 100).divide(totalCount, 2, BigDecimal.ROUND_HALF_UP) + "%");
        }
        return graphicsStatisticals;
    }

    @Override
    public void enterDatabase(List<Map<String, String>> sheet12List, List<Map<String, String>> sheet3List, List<Map<String, String>> sheet4List) {
        for (Map<String, String> map : sheet12List) {
            StaffEntity staffEntity = JSON.parseObject(JSON.toJSONString(map), StaffEntity.class);
            StaffOccupationEntity occupationEntity = JSON.parseObject(JSON.toJSONString(map), StaffOccupationEntity.class);
            StaffEducationEntity educationEntity = JSON.parseObject(JSON.toJSONString(map), StaffEducationEntity.class);
            StaffEntity Staff = this.getByName(staffEntity.getName());
            if (Staff == null) {
                this.save(staffEntity);
            } else {
                staffEntity.setId(Staff.getId());
                this.updateById(staffEntity);
            }

            createDepartmentInfo(staffEntity, map.get("primarySector"));
            createDepartmentInfo(staffEntity, map.get("secondarySector"));
            createDepartmentInfo(staffEntity, map.get("tertiarySector"));

            StaffOccupationEntity occupation = staffOccupationService.getOne(new QueryWrapper<StaffOccupationEntity>().eq("staff_id", staffEntity.getId()));
            if (occupation == null) {
                occupationEntity.setStaffId(staffEntity.getId());
                staffOccupationService.save(occupationEntity);
            } else {
                occupationEntity.setId(occupation.getId());
                staffOccupationService.updateById(occupationEntity);
            }

            StaffEducationEntity education = staffEducationService.getOne(new QueryWrapper<StaffEducationEntity>().eq("staff_id", staffEntity.getId()));
            if (education == null) {
                educationEntity.setStaffId(staffEntity.getId());
                staffEducationService.save(educationEntity);
            } else {
                educationEntity.setId(education.getId());
                staffEducationService.updateById(educationEntity);
            }
        }
        for (Map<String, String> map : sheet3List) {
            StaffEntity Staff = this.getByName(map.get("name"));
            if (Staff != null) {
                staffProjectExperienceService.update(new UpdateWrapper<StaffProjectExperienceEntity>().set("is_delete", 1).eq("staff_id", Staff.getId()));
            }
        }
        for (Map<String, String> map : sheet3List) {
            if (map.get("projectBeginTime").length() == 6) {
                map.put("projectBeginTime", map.get("projectBeginTime") + "01");
            }
            if (map.get("projectEndTime").length() == 6) {
                map.put("projectEndTime", map.get("projectEndTime") + "01");
            }
            StaffProjectExperienceEntity staffProjectExperienceEntity = JSON.parseObject(JSON.toJSONString(map), StaffProjectExperienceEntity.class);
            StaffEntity Staff = this.getByName(map.get("name"));
            if (Staff == null) {
                continue;
            } else {
                StaffProjectExperienceEntity projectExperienceEntity = staffProjectExperienceService.getOne(new QueryWrapper<StaffProjectExperienceEntity>().eq("staff_id", Staff.getId()).eq("project_name", staffProjectExperienceEntity.getProjectName()));
                if (projectExperienceEntity == null) {
                    staffProjectExperienceEntity.setStaffId(Staff.getId());
                    staffProjectExperienceService.save(staffProjectExperienceEntity);
                } else {
                    logger.info(DateUtils.format(staffProjectExperienceEntity.getProjectBeginTime(), DateUtils.DATE_TIME_PATTERN));
                    logger.info(DateUtils.format(staffProjectExperienceEntity.getProjectEndTime(), DateUtils.DATE_TIME_PATTERN));
                    staffProjectExperienceEntity.setId(projectExperienceEntity.getId());
                    staffProjectExperienceEntity.setIsDelete(0);
                    staffProjectExperienceService.updateById(staffProjectExperienceEntity);
                }
            }
        }
        for (Map<String, String> map : sheet4List) {
            StaffEntity Staff = this.getByName(map.get("name"));
            if (Staff != null) {
                staffWorkTransferRecordService.update(new UpdateWrapper<StaffWorkTransferRecordEntity>().set("is_delete", 1).eq("staff_id", Staff.getId()));
            }
        }
        for (Map<String, String> map : sheet4List) {
            if (map.get("transferTime").length() == 6) {
                map.put("transferTime", map.get("transferTime") + "01");
            }
            StaffWorkTransferRecordEntity staffWorkTransferRecordEntity = JSON.parseObject(JSON.toJSONString(map), StaffWorkTransferRecordEntity.class);
            StaffEntity Staff = this.getByName(map.get("name"));
            if (Staff == null) {
                continue;
            } else {
                StaffWorkTransferRecordEntity workTransferRecordEntity = staffWorkTransferRecordService.getOne(new QueryWrapper<StaffWorkTransferRecordEntity>().eq("staff_id", Staff.getId()).eq("transfer_time", staffWorkTransferRecordEntity.getTransferTime()));
                if (workTransferRecordEntity == null) {
                    staffWorkTransferRecordEntity.setStaffId(Staff.getId());
                    staffWorkTransferRecordService.save(staffWorkTransferRecordEntity);
                } else {
                    staffWorkTransferRecordEntity.setId(workTransferRecordEntity.getId());
                    staffWorkTransferRecordEntity.setIsDelete(0);
                    staffWorkTransferRecordService.updateById(staffWorkTransferRecordEntity);
                }
            }
        }
    }

    @Override
    public List<StaffEntity> selectByName(String name) {
        return staffDao.selectByName(name);
    }

    @Override
    public List<StaffEntity> selectByIds(List<Long> staffIds) {

        return staffDao.selectByIds(staffIds);
    }

    private void createDepartmentInfo(StaffEntity staffEntity, String departmentName) {
        DepartmentsEntity departmentsEntity = departmentsService.getOne(new QueryWrapper<DepartmentsEntity>().eq("department_name", departmentName));
        if (departmentsEntity != null) {
            DepartmentsStaffRelateEntity departmentsStaffRelateEntity = departmentsStaffRelateService.getOne(new QueryWrapper<DepartmentsStaffRelateEntity>().eq("department_id", departmentsEntity.getDepartmentId()).eq("staff_id", staffEntity.getId()));
            if (departmentsStaffRelateEntity == null) {
                departmentsStaffRelateEntity = new DepartmentsStaffRelateEntity();
                departmentsStaffRelateEntity.setStaffId(staffEntity.getId());
                departmentsStaffRelateEntity.setDepartmentId(departmentsEntity.getDepartmentId());
                departmentsStaffRelateService.save(departmentsStaffRelateEntity);
            }
        }
    }

    public StaffEntity convertStaffEntity(DepartmentStaffBo staffBo) {
        StaffEntity staffEntity = new StaffEntity();
        staffEntity.setName(staffBo.getName());//员工姓名
        staffEntity.setGender(staffBo.getGender());
        staffEntity.setMobile(staffBo.getMobile());
        staffEntity.setEmail(staffBo.getEmail());
        staffEntity.setOpenId(staffBo.getOpenId());
        staffEntity.setEmployeeId(staffBo.getEmployeeId());
        staffEntity.setUnionId(staffBo.getUnionId());
        staffEntity.setAvatar(staffBo.getAvatar());
        staffEntity.setJobNumber(staffBo.getEmployeeNo());
        return staffEntity;
    }


    @Override
    public List<String> selectAllDeparmentIdsByDepartmentParentId(String departmentId) {
        //默认所有
        if(StringUtil.isBlank(departmentId)){
            departmentId = "1";
        }
        List<String> parentsIds = Lists.newArrayList(departmentId);
        List<String> departmentsList = new ArrayList<>();
        departmentsList.addAll(parentsIds);
        List<String> childs = departmentsDao.selectDepartmentIdsByparentIds(parentsIds);
        if(CollectionUtils.isEmpty(childs)){
            return departmentsList;
        }
        departmentsList.addAll(childs);
        List<String> allChilds = getAllChilds(departmentsList, childs);
        allChilds.remove("1");
        return allChilds.stream().distinct().collect(Collectors.toList());
    }


    @Override
    public List<String> staffsByAllDeparmentIds(List<String> deparmentIds) {
        if(CollectionUtils.isEmpty(deparmentIds)){
            return Lists.newArrayList();
        }
        //获取所有人员
        List<String> list = departmentsStaffRelateService.selectStaffIdsByDepartments(deparmentIds);
        if(CollectionUtils.isEmpty(list)){
            return Lists.newArrayList();
        }
        //获取人员个数去重, 去除离职
        List<String> data = staffOccupationService.removeDimissionStaffByStaffIds(list);
        return new ArrayList<>(new HashSet(data));

    }

    @Override
    public List<StaffEntity> selectAll() {
        return staffDao.selectAll();
    }

    /**
     *
     * @param departmentsList 最终的存储集合
     * @param parentIds 本次查询的父id集合
     * @return
     */
    private List<String> getAllChilds(List<String> departmentsList,List<String> parentIds){
        List<String> childs = departmentsDao.selectDepartmentIdsByparentIds(parentIds);
        if(CollectionUtils.isEmpty(childs)){
            return departmentsList;
        }
        departmentsList.addAll(childs);
        return getAllChilds(departmentsList,childs);

    }

    @Override
    public List<StaffSimpleDto> selectStaffSimpleInfoByIds(List<Long> ids){
        return staffDao.selectStaffSimpleInfoByIds(ids);
    }

    @Override
    public List<StaffDto> getDepatAllStaffInfos(String departmentId){
        return staffDao.getDepatAllStaffInfos(departmentId);
    }

    @Override
    public List<StaffSimpleInfo> selectAllStaffSimpleInfos(DepartmentsEntity depart){
        return staffDao.selectAllStaffSimpleInfos(depart);
    }

    @Override
    public List<StaffSimpleInfo> selectStaffSimpleInfos(List<Long> sIds){
        return staffDao.selectStaffSimpleInfos(sIds);
    }

    @Override
     //查找第几及领导
    public DepartManagers findLeader(Long id, Integer type){
        DepartmentsStaffRelateEntity departmentsStaffRelateEntity = departmentsStaffRelateService.selectByStaffId(id);
        DepartManagers departManagers = new DepartManagers();
        if(departmentsStaffRelateEntity != null){
            if(departmentsStaffRelateEntity.getIsLeader().intValue() == 1
                    & departmentsStaffRelateEntity.getStaffId().longValue() == id.longValue()){
                //自己是部门领导
                type++;
            }
            String depId = departmentsStaffRelateEntity.getDepartmentId();
            departManagers.setDepartmentId(depId);
            while(type > 1){
                //查找父级部门
                DepartmentsEntity departmentsEntity =
                        departmentsService.selectParentDepartmentByDepartmentId(depId);
                if(departmentsEntity != null){
                    depId = departmentsEntity.getDepartmentId();
                }else{
                    log.info("没有找到父级部门，部门id{}", depId);
                    departManagers.setManagers(new ArrayList<>());
                    return departManagers;
                }
                type--;
            }
            List<StaffEntity> staffEntities =
                    departmentsStaffRelateService.selectLeadersByDepartmentId(depId);
            departManagers.setManagers(staffEntities);
            if(staffEntities.size() == 0){
                log.info("无法找到管理人员.部门id{}", depId);
            }

            return departManagers;


        }
        log.info("没有找到部门信息，员工id{}", id);
        departManagers.setManagers(new ArrayList<>());
        return departManagers;

    }

    @Override
    public List<StaffEntity> selectOnJobByIds(List<Long> mIds){
        return staffDao.selectOnJobByIds(mIds);
    }

    @Override
    public StaffSimpleInfo selectStaffSimpleInfo(Long staffId){
        return staffDao.selectStaffSimpleInfo(staffId);
    }

    @Override
    public List<StaffEntity> selectNamesByIds(List<Long> sIds){
        return staffDao.selectNamesByIds(sIds);
    }

    @Override
    public List<StaffEntity> selectStaffsByGroupId(Long copyId){
        return staffDao.selectStaffsByGroupId(copyId);
    }

    @Override
    public List<StaffEntity> findManger(Long recordId, int flowProcess){
        return staffDao.findManger(recordId, flowProcess);
    }


}
