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

import com.mortals.framework.common.Rest;
import com.mortals.xhx.common.code.EnableEnum;
import com.mortals.xhx.common.code.EnabledEnum;
import com.mortals.xhx.common.code.StaffSatusEnum;
import com.mortals.xhx.module.staff.model.StaffEntity;
import com.mortals.xhx.module.staff.model.StaffQuery;
import com.mortals.xhx.module.staff.service.StaffService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.xhx.module.dept.dao.DeptDao;
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.dept.model.DeptTreeSelect;
import org.springframework.util.ObjectUtils;

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

/**
 * DeptService
 * 部门信息 service实现
 *
 * @author zxfei
 * @date 2023-03-06
 */
@Service("deptService")
@Slf4j
public class DeptServiceImpl extends AbstractCRUDServiceImpl<DeptDao, DeptEntity, Long> implements DeptService {

    @Autowired
    private StaffService staffService;

    @Override
    protected void saveBefore(DeptEntity entity, Context context) throws AppException {
        if (ObjectUtils.isEmpty(entity.getParentId())) {
            //如果父节点为空，默认挂载到根目录
            entity.setParentId(0L);
        }

        DeptEntity parentDeptEntity = this.get(entity.getParentId());
        if (!ObjectUtils.isEmpty(parentDeptEntity) && EnabledEnum.停用.getValue() == parentDeptEntity.getDeptStatus()) {
            throw new AppException("部门信息停用，不允许新增");
        }

        if (!ObjectUtils.isEmpty(parentDeptEntity)) {
            entity.setAncestors(parentDeptEntity.getAncestors() + "," + entity.getParentId());
        }

        super.saveBefore(entity, context);
    }

    @Override
    protected void updateBefore(DeptEntity entity, Context context) throws AppException {
        DeptEntity newParentEntity = this.get(entity.getParentId());
        DeptEntity oldEntity = this.get(entity.getId());
        if (!ObjectUtils.isEmpty(newParentEntity) && !ObjectUtils.isEmpty(oldEntity)) {
            String newAncestors = newParentEntity.getAncestors() + "," + entity.getId();
            String oldAncestors = oldEntity.getAncestors();
            entity.setAncestors(newAncestors);
            updateDeptChildren(entity.getId(), newAncestors, oldAncestors, context);
        }
        super.updateBefore(entity, context);
    }


    @Override
    protected void updateAfter(DeptEntity entity, Context context) throws AppException {
        if (EnabledEnum.启用.getValue() == entity.getDeptStatus()) {
            updateParentDeptStatus(entity, context);
        }
        super.updateAfter(entity, context);
    }

    /**
     * 修改该部门信息的父级部门信息状态
     *
     * @param dept 当前部门信息
     */
    private void updateParentDeptStatus(DeptEntity dept, Context context) {
        DeptEntity deptEntity = this.get(dept.getParentId());
        if (!ObjectUtils.isEmpty(deptEntity)) {
            deptEntity.setDeptStatus(EnabledEnum.启用.getValue());
            deptEntity.setUpdateTime(new Date());
            deptEntity.setUpdateUser(context == null ? "admin" : context.getUser().getLoginName());
            DeptEntity condition = new DeptEntity();
            condition.setId(deptEntity.getId());
            this.updateBatch(deptEntity, condition, context);
        }
    }

    /**
     * 修改子元素关系
     *
     * @param deptId       被修改的部门信息ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors, Context context) {

        List<DeptEntity> children = getDao().selectChildrenDeptById(deptId.toString());
        for (DeptEntity child : children) {
            child.setAncestors(child.getAncestors().replace(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            this.updateAfter(children, context);
        }
    }


    @Override
    protected void removeBefore(Long[] ids, Context context) throws AppException {
        //有子节点 禁止删除
        if (hasChildByDeptId(ids[0])) {
            throw new AppException("存在下级部门信息,不允许删除");
        }
        super.removeBefore(ids, context);
    }

    @Override
    public boolean hasChildByDeptId(Long deptId) {
        List<DeptEntity> list = this.find(new DeptQuery().parentId(deptId));

        return list.size() > 0 ? true : false;
    }

    @Override
    public List<DeptEntity> selectDeptList(DeptEntity dept) {
        return this.find(new DeptQuery());
    }

    @Override
    public List<DeptTreeSelect> buildDeptTreeSelect(List<DeptEntity> list) {

        for (Iterator<DeptEntity> iterator = list.iterator(); iterator.hasNext(); ) {
            DeptEntity deptEntity = iterator.next();
            StaffQuery staffQuery = new StaffQuery();
            staffQuery.setDeptId(deptEntity.getId());
            staffQuery.setStatusNotList(Arrays.asList(StaffSatusEnum.离职.getValue()));
            List<StaffEntity> staffEntities = staffService.find(staffQuery);
            List<Map<String, Object>> personList = new ArrayList<>();
            staffEntities.forEach(item -> {
                Map<String, Object> map = new HashMap<>();
                map.put("staffId", item.getId());
                map.put("staffName", item.getName());
                map.put("deptId", item.getDeptId());
                personList.add(map);
            });
            deptEntity.setPersonList(personList);
        }
        //获取父节点
        List<DeptEntity> returnList = list.stream().filter(t -> t.getParentId() == 0).map(
                m -> {
                    m.setChildren(getChildren(m, list));

                    StaffQuery query = new StaffQuery();
                    query.setStatusNotList(Arrays.asList(StaffSatusEnum.离职.getValue()));
                    query.setDeptIdList(getChildrenId(m, list));
                    int count = staffService.count(query,null);
                    m.setPersonNum(count);
                    return m;
                }
        ).collect(Collectors.toList());
        return returnList.stream().map(DeptTreeSelect::new).collect(Collectors.toList());
    }
    /**
     * 递归查询子节点
     * @param root  根节点
     * @param all   所有节点
     * @return 根节点信息
     */
    private List<DeptEntity> getChildren(DeptEntity root, List<DeptEntity> all) {
        List<DeptEntity> children = all.stream().filter(t -> {
            return Objects.equals(t.getParentId(), root.getId());
        }).map(
                m -> {
                    m.setChildren(getChildren(m, all));
                    StaffQuery query = new StaffQuery();
                    query.setDeptIdList(getChildrenId(m, all));
                    query.setStatusNotList(Arrays.asList(StaffSatusEnum.离职.getValue()));
                    int count = staffService.count(query,null);
                    m.setPersonNum(count);
                    return m;
                }
        ).collect(Collectors.toList());
        return children;
    }

    private List<Long> getChildrenId(DeptEntity root, List<DeptEntity> all){
        List<Long> idList = new ArrayList<>();
        idList.add(root.getId());
        all.forEach(item ->{
            if(Objects.equals(item.getParentId(), root.getId())){
                idList.addAll(getChildrenId(item,all));
            }
        });
        return idList;
    }

    @Override
    public List<DeptTreeSelect> getListByParentId(Long parentId, Context context) {
        if (ObjectUtils.isEmpty(parentId)) {
            parentId = 0L;
        }
        //只做一层
        List<DeptTreeSelect> collect = this.find(new DeptQuery().parentId(parentId), context).stream().map(item -> new DeptTreeSelect(item)
        ).collect(Collectors.toList());
        if ("0".equals(parentId)) {
            return collect;
        }

        return collect;
    }

    @Override
    public Rest<Void> updateDeptNum(Context context) {
        log.info("更新部门用户数量");
        StaffQuery query = new StaffQuery();
        query.setStatusNotList(Arrays.asList(StaffSatusEnum.离职.getValue()));
        Map<Long, Long> collect = staffService.find(query).stream().collect(Collectors.groupingBy(x -> x.getDeptId(), Collectors.counting()));
        DeptEntity deptEntity1 = new DeptEntity();
        deptEntity1.setPersonNum(0);
        this.getDao().update(deptEntity1, new HashMap<>());

        collect.entrySet().stream().forEach(item -> {
            Long deptId = item.getKey();
            Long count = item.getValue();
            log.info("deptId:{},num:{}", deptId, count);
            DeptEntity deptEntity = this.get(deptId);
            if (!ObjectUtils.isEmpty(deptEntity)) {
                deptEntity.setPersonNum(count.intValue());
                this.update(deptEntity);
            }
        });

        for (Map.Entry<Long, Long> item : collect.entrySet()) {
            Long deptId = item.getKey();
            if (deptId == null) continue;
            DeptEntity deptEntity = this.get(deptId);
            if (!ObjectUtils.isEmpty(deptEntity)) {
                //查询当前父节点的所有子部门
                DeptQuery deptQuery = new DeptQuery();
                deptQuery.setParentId(deptEntity.getParentId());

                int sum = this.find(new DeptQuery().parentId(deptEntity.getParentId())).stream().map(i -> i.getPersonNum()).reduce(0, Integer::sum);
                DeptEntity parentDept = this.get(deptEntity.getParentId());

                if (!ObjectUtils.isEmpty(parentDept)) {
                    log.info("parentDept:{},sum:{}", parentDept.getDeptName(), sum);
                    parentDept.setPersonNum(sum);
                    this.update(parentDept);
                }
            }else {
                log.info("deptEntity is null.deptId:{}",item.getKey());
            }
        }

        return Rest.ok();
    }

    @Override
    public List<DeptEntity> getAllChildrenDept(Long deptId) throws AppException {
        return dao.getAllChildrenDept(deptId);
    }

    @Override
    public List<DeptEntity> getAllSala() throws AppException {
        return dao.getList(new DeptQuery().parentId(71l));
    }

    @Override
    public List<DeptEntity> getDeptBySalaId(Long salaId) throws AppException {
        DeptQuery query = new DeptQuery();
        if(salaId == null){
            List<DeptEntity> allSala = dao.getList(new DeptQuery().parentId(71l));
            List<Long> salaList = new ArrayList<>();
            for(DeptEntity item:allSala){
                salaList.add(item.getId());
            }
            query.setParentIdList(salaList);
        }else {
            query.setParentId(salaId);
        }
        return dao.getList(query);
    }

}
