package com.mortals.xhx.module.staff.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.model.PageInfo;
import com.mortals.framework.service.impl.AbstractCRUDCacheServiceImpl;
import com.mortals.framework.util.SecurityUtil;
import com.mortals.xhx.base.system.idgenerator.service.IdgeneratorService;
import com.mortals.xhx.base.system.idgenerator.service.impl.IdgeneratorServiceImpl;
import com.mortals.xhx.base.system.role.model.RoleUserQuery;
import com.mortals.xhx.base.system.role.service.RoleUserService;
import com.mortals.xhx.base.system.user.model.UserEntity;
import com.mortals.xhx.base.system.user.service.UserService;
import com.mortals.xhx.common.code.*;
import com.mortals.xhx.module.attendance.model.*;
import com.mortals.xhx.module.attendance.service.AttendanceGroupStaffService;
import com.mortals.xhx.module.attendance.service.AttendanceStatService;
import com.mortals.xhx.module.attendance.service.AttendanceVacationBalanceService;
import com.mortals.xhx.module.dept.model.DeptEntity;
import com.mortals.xhx.module.dept.model.DeptQuery;
import com.mortals.xhx.module.dept.service.DeptService;
import com.mortals.xhx.module.hik.person.model.req.person.PersonReq;
import com.mortals.xhx.module.hik.person.model.rsp.person.PersonDataInfo;
import com.mortals.xhx.module.hik.person.model.rsp.person.PersonInfo;
import com.mortals.xhx.module.hik.person.service.IHikPersonService;
import com.mortals.xhx.module.staff.dao.StaffDao;
import com.mortals.xhx.module.staff.dao.ibatis.StaffDaoImpl;
import com.mortals.xhx.module.staff.dao.ibatis.StaffLeaveDaoImpl;
import com.mortals.xhx.module.staff.model.StaffEntity;
import com.mortals.xhx.module.staff.model.StaffLeaveEntity;
import com.mortals.xhx.module.staff.model.StaffLeaveQuery;
import com.mortals.xhx.module.staff.model.StaffQuery;
import com.mortals.xhx.module.staff.model.vo.StaffInfoVo;
import com.mortals.xhx.module.staff.service.StaffLeaveService;
import com.mortals.xhx.module.staff.service.StaffService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.mortals.xhx.base.system.idgenerator.service.impl.IdgeneratorServiceImpl.IdGeneratorKey.USER_KEY;

/**
 * StaffService
 * 员工基本信息 service实现
 *
 * @author zxfei
 * @date 2023-04-07
 */
@Service("staffService")
@Slf4j
public class StaffServiceImpl extends AbstractCRUDCacheServiceImpl<StaffDao, StaffEntity, Long> implements StaffService {

    @Autowired
    private UserService userService;
    @Autowired
    private DeptService deptService;

    @Autowired
    private RoleUserService roleUserService;

    @Autowired
    private IHikPersonService hikPersonService;

    @Autowired
    private AttendanceStatService attendanceStatService;

    @Autowired
    private AttendanceVacationBalanceService balanceService;
    @Autowired
    private IdgeneratorService idgeneratorService;
    @Autowired
    private StaffLeaveService staffLeaveService;
    @Autowired
    private AttendanceGroupStaffService attendanceGroupStaffService;

    @Override
    protected String getExtKey(StaffEntity data) {
        //工号作为redis 扩展key
        return StrUtil.padPre(data.getWorkNum(), 8, "0");
        //  return "1000"+data.getWorkNum();
    }

    @Override
    protected void saveBefore(StaffEntity entity, Context context) throws AppException {
        int count = this.count(new StaffQuery().workNum(entity.getWorkNum()), context);
        if (count > 0) {
            throw new AppException("工号重复！工号:" + entity.getWorkNum());
        }
    }

    @Override
    public StaffInfoVo queryAll(Context context) {
        StaffInfoVo staffInfoVo = new StaffInfoVo();
        //在职
        StaffQuery staffQuery = new StaffQuery();
        staffQuery.setStatusList(Arrays.asList(StaffSatusEnum.正式.getValue(), StaffSatusEnum.试用.getValue()));
        List<StaffEntity> staffEntities = this.find(staffQuery);
        staffInfoVo.setInWorkStaff(staffEntities.size());
        //全职
        Map<Integer, Long> collect = staffEntities.stream().collect(Collectors.groupingBy(x -> x.getStaffType(), Collectors.counting()));
        staffInfoVo.setFullStaff(collect.getOrDefault(StaffTypeEnum.全职.getValue(), 0L).intValue());
        //实习
        staffInfoVo.setPricateStaff(collect.getOrDefault(StaffTypeEnum.实习.getValue(), 0L).intValue());
        //兼职
        staffInfoVo.setConcurrentlyStaff(collect.getOrDefault(StaffTypeEnum.兼职.getValue(), 0L).intValue());
        //试用
        staffInfoVo.setOnTrialStaff(this.find(new StaffQuery().status(StaffSatusEnum.试用.getValue())).size());
        //正式
        staffInfoVo.setFormalStaff(this.find(new StaffQuery().status(StaffSatusEnum.正式.getValue())).size());
        //待离职
        staffInfoVo.setResignationStaff(this.find(new StaffQuery().status(StaffSatusEnum.离职.getValue())).size());
        return staffInfoVo;
    }


    @Override
    public int queryAllPerson() {
        StaffQuery staffQuery = new StaffQuery();
        staffQuery.setStatusList(Arrays.asList(StaffSatusEnum.正式.getValue(), StaffSatusEnum.试用.getValue()));
        List<StaffEntity> staffEntities = this.find(staffQuery);
        return staffEntities.size();
    }

    @Override
    public Rest<Void> syncPersons(Context context) {
        log.info("同步人员！");

        PersonReq personReq = new PersonReq();
        personReq.setPageNo(1);
        personReq.setPageSize(1000);
        Rest<PersonDataInfo> personRest = hikPersonService.getPersonList(personReq);
        if (personRest.getCode() == YesNoEnum.YES.getValue()) {

            //做差集 更新本地用户为离职员工
            StaffQuery staffQuery = new StaffQuery();
            staffQuery.setSource(1);
            staffQuery.setStatusNotList(Arrays.asList(StaffSatusEnum.离职.getValue()));
            Map<String, StaffEntity> staffCollect = this.find(staffQuery).stream().collect(Collectors.toMap(x -> x.getWorkNum(), y -> y, (o, n) -> n));


            List<PersonInfo> personInfoList = personRest.getData().getList();
            for (PersonInfo personInfo : personInfoList) {
                if (ObjectUtils.isEmpty(personInfo.getJobNo())) {
                    log.info("jobNo is null ==>{}", JSON.toJSONString(personInfo));
                    continue;
                }
                if (staffCollect.containsKey(personInfo.getJobNo())) {
                    staffCollect.remove(personInfo.getJobNo());

                }

                StaffEntity staffEntity = this.getExtCache(StrUtil.padPre(personInfo.getJobNo(), 8, "0"));
                DeptEntity deptEntity = deptService.selectOne(new DeptQuery().deptCode(personInfo.getOrgIndexCode()));
                //判断本地数据是否为空
                if (ObjectUtils.isEmpty(staffEntity)) {
                    //新增员工信息
                    staffEntity = new StaffEntity();
                    staffEntity.initAttrValue();
                    if (!ObjectUtils.isEmpty(deptEntity)) {
                        staffEntity.setDeptId(deptEntity.getId());
                    }
                    staffEntity.setName(personInfo.getPersonName());
                    staffEntity.setRemarkId(personInfo.getPersonId());
                    staffEntity.setPicUri(personInfo.getPersonPhoto().getPicUri());
                    staffEntity.setServerIndexCode(personInfo.getPersonPhoto().getServerIndexCode());
                    staffEntity.setDeptName(personInfo.getOrgName());
                    staffEntity.setGender(personInfo.getGender());
                    staffEntity.setWorkNum(personInfo.getJobNo());
                    staffEntity.setPhoneNumber(personInfo.getPhoneNo());
                    staffEntity.setCreateUserId(1L);
                    staffEntity.setCreateTime(new Date());
                    this.save(staffEntity);

                } else {
                    //更新
                    if (!ObjectUtils.isEmpty(deptEntity)) {
                        staffEntity.setDeptId(deptEntity.getId());
                    }
                    staffEntity.setName(personInfo.getPersonName());
                    staffEntity.setRemarkId(personInfo.getPersonId());
                    staffEntity.setPicUri(personInfo.getPersonPhoto().getPicUri());
                    staffEntity.setServerIndexCode(personInfo.getPersonPhoto().getServerIndexCode());
                    staffEntity.setDeptName(personInfo.getOrgName());
                    staffEntity.setGender(personInfo.getGender());
                    staffEntity.setWorkNum(personInfo.getJobNo());
                    staffEntity.setPhoneNumber(personInfo.getPhoneNo());
                    staffEntity.setUpdateUserId(1L);
                    staffEntity.setUpdateTime(new Date());
                    this.update(staffEntity);
                }

            }
            if (staffCollect.size() > 0) {
                //需要将此人员变更为离职
                staffCollect.entrySet().stream().forEach(item -> {

                    String key = item.getKey();
                    if (!ObjectUtils.isEmpty(key)) {
                        StaffEntity staff = item.getValue();
                        staff.setStatus(StaffSatusEnum.离职.getValue());
                        staff.setUpdateTime(new Date());
                        staff.setUpdateUserId(1L);
                        this.update(staff);

                        //新增离职人员
                        StaffLeaveEntity staffLeaveEntity = new StaffLeaveEntity();
                        staffLeaveEntity.initAttrValue();
                        staffLeaveEntity.setStaffId(staff.getId());
                        staffLeaveEntity.setStaffName(staff.getName());
                        staffLeaveEntity.setGender(staff.getGender());
                        staffLeaveEntity.setBirthday(staff.getBirthday());
                        staffLeaveEntity.setPhotoPath(staff.getPhotoPath());
                        staffLeaveEntity.setPhoneNumber(staff.getPhoneNumber());
                        staffLeaveEntity.setIdCard(staff.getIdCard());
                        staffLeaveEntity.setWorkNum(staff.getWorkNum());
                        staffLeaveEntity.setPoliticalstatus(staff.getPoliticalstatus());
                        staffLeaveEntity.setDeptId(staff.getDeptId());
                        staffLeaveEntity.setDeptName(staff.getDeptName());
                        staffLeaveEntity.setJobId(staff.getPositionId());
                        staffLeaveEntity.setJobName(staff.getPositionName());
                        staffLeaveEntity.setStaffType(staff.getStaffType());
                        staffLeaveEntity.setStatus(StaffSatusEnum.离职.getValue());
                        staffLeaveEntity.setLeaveDate(new Date());
                        staffLeaveEntity.setLeaveReason("");
                        staffLeaveEntity.setAuditStatus(AuditStatusEnum.通过.getValue());
                        staffLeaveEntity.setCreateUserId(1L);
                        staffLeaveEntity.setCreateTime(new Date());

                        StaffLeaveQuery staffLeaveQuery = new StaffLeaveQuery();
                        staffLeaveQuery.setWorkNum(staff.getWorkNum());

                        int count = staffLeaveService.count(staffLeaveQuery, null);
                        if (count == 0) {
                            staffLeaveService.save(staffLeaveEntity);
                        }

                        //考勤人员中有离职的 删除
                        Long[] groudStaffIds = attendanceGroupStaffService.find(new AttendanceGroupStaffQuery().staffId(staff.getId())).stream().toArray(Long[]::new);
                        if (!ObjectUtils.isEmpty(groudStaffIds)) {
                            attendanceGroupStaffService.remove(groudStaffIds, null);
                        }
                    }
                });
            }
        }

        return Rest.ok();
    }


    @Override
    protected void saveAfter(StaffEntity entity, Context context) throws AppException {
        super.saveAfter(entity, context);
        //初始化
        int count = balanceService.count(new AttendanceVacationBalanceQuery().staffId(entity.getId()), context);
        if (count == 0) {
            AttendanceVacationBalanceEntity balanceEntity = new AttendanceVacationBalanceEntity();
            balanceEntity.initAttrValue();
            balanceEntity.setStaffId(entity.getId());
            balanceEntity.setStaffName(entity.getName());
            balanceEntity.setDeptId(entity.getDeptId());
            balanceEntity.setDeptName(entity.getDeptName());
            balanceEntity.setCreateUserId(1L);
            balanceEntity.setCreateTime(new Date());
            balanceService.save(balanceEntity);
        }
        AttendanceStatQuery attendanceStatQuery = new AttendanceStatQuery();
        attendanceStatQuery.setYear(DateUtil.year(new Date()));
        attendanceStatQuery.setMonth(DateUtil.month(new Date()) + 1);
        attendanceStatQuery.setDay(DateUtil.dayOfMonth(new Date()));
        attendanceStatQuery.setStaffId(entity.getId());
        int count1 = attendanceStatService.count(attendanceStatQuery, context);
        if (count1 == 0) {
            AttendanceStatEntity attendanceStatEntity = new AttendanceStatEntity();
            attendanceStatEntity.initAttrValue();
            attendanceStatEntity.setStaffId(entity.getId());
            attendanceStatEntity.setStaffName(entity.getName());
            attendanceStatEntity.setDeptId(entity.getDeptId());
            attendanceStatEntity.setDeptName(entity.getDeptName());
            attendanceStatEntity.setPhoneNumer(entity.getPhoneNumber());
            attendanceStatEntity.setYear(DateUtil.year(new Date()));
            attendanceStatEntity.setMonth(DateUtil.month(new Date()) + 1);
            attendanceStatEntity.setDay(DateUtil.dayOfMonth(new Date()));
            attendanceStatEntity.setCreateUserId(1L);
            attendanceStatEntity.setCreateTime(new Date());
            attendanceStatService.save(attendanceStatEntity);
        }
        try {
            UserEntity userEntity = new UserEntity();
            if (ObjectUtils.isEmpty(entity.getLoginName())) {
                //姓名加工号作为登录名
                entity.setLoginName(entity.getName() + entity.getWorkNum());
            }
            if (ObjectUtils.isEmpty(entity.getLoginPwd())) {
                //设置初始密码
                entity.setLoginPwd("123456");
            }

            //生成用户id,不与门户服务用户相同
//            Long userId = idgeneratorService.getLongId(USER_KEY);
//            entity.setId(userId);
            userEntity.setLoginName(StrUtil.cleanBlank(entity.getLoginName()));
            userEntity.setRealName(entity.getName());
            userEntity.setUserType(UserType.WORK_PERSON.getValue());
            userEntity.setSiteIds("1");
            userEntity.setAreaCodes("511500000000");
            userEntity.setMobile(entity.getPhoneNumber());
            userEntity.setStatus(UserStatus.NORMAL.getValue());
            userEntity.setCreateUserId(this.getContextUserId(context));
            userEntity.setCreateTime(new Date());
            userEntity.setCustomerId(entity.getId());

            userEntity.setLoginPwd(SecurityUtil.md5DoubleEncoding(entity.getLoginPwd()));
            int insert = userService.getUserDao().insert(userEntity);
            if (insert > 0) {
                RoleUserQuery roleUserQuery = new RoleUserQuery();
                roleUserQuery.setUserId(userEntity.getId());
                roleUserQuery.setRoleIdList(Arrays.asList(4L));
                roleUserService.assignRoleToUser(roleUserQuery);
            }

        } catch (Exception e) {
            log.error("保存系统用户异常!", e);
        }

    }


    @Override
    protected void removeAfter(Long[] ids, Context context, int result) throws AppException {
        deptService.updateDeptNum(context);
    }

    public static void main(String[] args) {
        System.out.println("1" + StrUtil.padPre("125", 7, "0"));

    }

    @Override
    protected StaffEntity findBefore(StaffEntity params, PageInfo pageInfo, Context context) throws AppException {
        if (params.getDeptId() != null) {
            List<DeptEntity> deptList = deptService.getAllChildrenDept(params.getDeptId());
            if (CollectionUtils.isNotEmpty(deptList)) {
                List<Long> deptIdList = new ArrayList<>();
                deptIdList.add(params.getDeptId());
                deptList.forEach(item -> {
                    deptIdList.add(item.getId());
                });
                params.setDeptId(null);
                params.setDeptIdList(deptIdList);
            }
        }
        return params;
    }
}