package com.cpop.oam.business.service.impl;

import com.cpop.common.utils.StringUtils;
import com.cpop.common.utils.bean.BeanUtils;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.utils.MessageUtils;
import com.cpop.core.utils.SpringUtils;
import com.cpop.oam.business.bo.DeptBo;
import com.cpop.oam.business.bo.DeptListBo;
import com.cpop.oam.business.entity.Dept;
import com.cpop.oam.business.mapper.DeptMapper;
import com.cpop.oam.business.service.DeptService;
import com.cpop.oam.business.service.StaffMidDeptService;
import com.cpop.oam.business.vo.DeptVo;
import com.cpop.oam.framework.config.wxCp.WxCpConfiguration;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.RowUtil;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpDepart;
import org.springframework.stereotype.Service;

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

import static com.cpop.oam.business.entity.table.DeptTableDef.DEPT;
import static com.cpop.oam.business.entity.table.StaffMidDeptTableDef.STAFF_MID_DEPT;

/**
 * 部门表 服务层实现。
 *
 * @author DB
 * @since 2023-09-08
 */
@Service("oamDeptService")
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements DeptService {

    /**
     * @descriptions 查询部门树列表
     * @author DB
     * @date 2023/09/08 18:25
     * @param bo 查询参数
     * @return java.util.List<com.jambox.system.business.vo.DeptVo>
     */
    @Override
    public List<DeptVo> getDeptTreeList(DeptListBo bo) {
        return buildDeptTree(this.listAs(QueryWrapper.create()
                .and(DEPT.NAME.like(bo.getName()))
                .and(DEPT.STATUS.eq(bo.getStatus()))
                .orderBy(DEPT.ORDER_NO.desc()), DeptVo.class));
    }

    /**
     * @Description: 构建部门树
     * @param list 部门集合
     * @return List<SysDeptVo>
     * @Author DB
     * @Date: 2023/5/9 20:56
     */
    private List<DeptVo> buildDeptTree(List<DeptVo> list) {
        List<DeptVo> returnList = new ArrayList<DeptVo>();
        List<String> tempList = new ArrayList<String>();
        for (DeptVo dept : list) {
            tempList.add(dept.getId());
        }
        for (DeptVo dept : list) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId())) {
                recursionFn(list, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty()) {
            returnList = list;
        }
        return returnList;
    }

    /**
     * @Description: 递归列表
     * @param list 部门集合
     * @param t 参数
     * @Author DB
     * @Date: 2023/5/9 20:55
     */
    private void recursionFn(List<DeptVo> list, DeptVo t) {
        // 得到子节点列表
        List<DeptVo> childList = getChildList(list, t);
        t.setChildren(childList);
        for (DeptVo tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * @Description: 得到子节点列表
     * @param list 部门集合
     * @param t 参数
     * @return boolean
     * @Author DB
     * @Date: 2023/5/9 20:55
     */
    private boolean hasChild(List<DeptVo> list, DeptVo t) {
        return getChildList(list, t).size() > 0;
    }

    /**
     * @Description: 得到子节点列表
     * @param list 部门集合
     * @param t 参数
     * @return List<SysDeptVo>
     * @Author DB
     * @Date: 2023/5/9 20:55
     */
    private List<DeptVo> getChildList(List<DeptVo> list, DeptVo t) {
        List<DeptVo> tList = new ArrayList<DeptVo>();
        for (DeptVo deptVo : list) {
            if (StringUtils.isNotNull(deptVo.getParentId()) && StringUtils.equals(deptVo.getParentId(), t.getId())) {
                tList.add(deptVo);
            }
        }
        return tList;
    }

    /**
     * 新增部门
     *
     * @param bo 请求参数
     */
    @Override
    public void insertDept(DeptBo bo) {
        Dept entity = BeanUtils.mapToClass(bo, Dept.class);
        this.save(entity);
    }

    /**
     * @Description: 修改部门
     * @param bo 请求参数
     * @Author DB
     * @Date: 2023/5/9 20:47
     */
    @Override
    public void updateDept(DeptBo bo) {
        Dept entity = BeanUtils.mapToClass(bo, Dept.class);
        this.updateById(entity);
    }

    /**
     * @Description: 删除部门
     * @param id 主键
     * @Author DB
     * @Date: 2023/5/9 20:48
     */
    @Override
    public void removeDept(String id) {
        //首先，只允许删除停用的部门
        if (this.count(QueryWrapper.create().where(DEPT.STATUS.eq(1)).and(DEPT.ID.eq(id))) > 0) {
            //再查询所有部门
            List<Dept> list = this.list();
            //递归获取当前部门与子部门
            List<String> deptIds = filterSonDept(list, id);
            //删除部门，首先要查询员工
            if (SpringUtils.getBean(StaffMidDeptService.class).count(QueryWrapper.create().where(STAFF_MID_DEPT.DEPT_ID.in(deptIds))) > 0) {
                throw new ServiceException(MessageUtils.message("i18n_alert_peopleUnderTheDepartmentError"));
            } else {
                //当部门人员及其子部门人员为空时，才允许删除部门
                this.removeByIds(deptIds);
            }
        }else {
            throw new ServiceException(MessageUtils.message("i18n_alert_departmentNotDeactivatedError"));
        }
    }

    /**
     * @Description: 过滤子部门
     * @param list 部门集合
     * @param id 部门id
     * @return List<String>
     * @Author DB
     * @Date: 2023/5/9 20:58
     */
    private List<String> filterSonDept(List<Dept> list, String id) {
        List<String> deptIds = new ArrayList<>();
        deptIds.add(id);
        //获取其子部门
        List<Dept> filterList = list.stream()
                .filter(s -> StringUtils.equals(s.getParentId(), id))
                .collect(Collectors.toList());
        recursionRemoveIds(deptIds, filterList);
        return deptIds;
    }

    /**
     * @Description: 递归获取当前部门与下属子部门
     * @param deptIds 部门id
     * @param filterList 过滤集合
     * @Author DB
     * @Date: 2023/5/9 20:59
     */
    private void recursionRemoveIds(List<String> deptIds, List<Dept> filterList) {
        filterList.forEach(item -> {
            deptIds.add(item.getId());
            recursionRemoveIds(deptIds, filterList.stream()
                    .filter(s -> null != s.getParentId() && StringUtils.equals(s.getParentId(), item.getId()))
                    .collect(Collectors.toList()));
        });
    }

}
