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

import com.alibaba.fastjson.JSON;
import com.dingtalk.api.response.OapiV2DepartmentListsubResponse;
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.common.code.YesNoEnum;
import com.mortals.xhx.module.dingding.personal.service.IDingPersonService;
import com.mortals.xhx.module.hik.person.model.req.org.OrgListReq;
import com.mortals.xhx.module.hik.person.model.rsp.org.OrgDataInfo;
import com.mortals.xhx.module.hik.person.model.rsp.org.OrgInfo;
import com.mortals.xhx.module.hik.person.service.IHikPersonService;
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;
import java.util.stream.Stream;

/**
 * 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;

    @Autowired
    private IHikPersonService hikPersonService;

    @Autowired
    private IDingPersonService dingPersonService;

    @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 || salaId == -1l) {
            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);
    }

    @Override
    public Rest<String> syncDept(Context context) {
        //部门同步
        OrgListReq orgListReq = new OrgListReq();
        orgListReq.setPageNo(1);
        orgListReq.setPageSize(1000);
        Rest<OrgDataInfo> orgRest = hikPersonService.getOrgList(orgListReq);
        if (orgRest.getCode() == YesNoEnum.YES.getValue()) {
            List<OrgInfo> orgInfoList = orgRest.getData().getList();
            log.info("orgInfoList:{}", JSON.toJSONString(orgInfoList));
            for (OrgInfo orgInfo : orgInfoList) {
                //查询数据库信息
                DeptEntity deptEntity = this.selectOne(new DeptQuery().deptCode(orgInfo.getOrgIndexCode()));
                DeptEntity deptEntityParent = this.selectOne(new DeptQuery().deptCode(orgInfo.getParentOrgIndexCode()));
                //新增
                if (ObjectUtils.isEmpty(deptEntity)) {
                    deptEntity = new DeptEntity();
                    deptEntity.initAttrValue();
                    if (!ObjectUtils.isEmpty(deptEntityParent)) {
                        deptEntity.setParentId(deptEntityParent.getId());
                    }
                    deptEntity.setDeptName(orgInfo.getOrgName());
                    deptEntity.setDeptCode(orgInfo.getOrgIndexCode());
                    deptEntity.setAncestors(orgInfo.getOrgPath());
                    deptEntity.setRemark(orgInfo.getParentOrgIndexCode());
                    deptEntity.setCreateTime(new Date());
                    deptEntity.setCreateUserId(1L);
                    this.save(deptEntity);
                } else {
                    //更新
                    deptEntity.setDeptName(orgInfo.getOrgName());
                    deptEntity.setDeptCode(orgInfo.getOrgIndexCode());
                    deptEntity.setAncestors(orgInfo.getOrgPath());
                    deptEntity.setUpdateTime(new Date());
                    deptEntity.setUpdateUserId(1L);
                    this.update(deptEntity);
                }
            }

            //差额删除部门
            List<DeptEntity> localDeptList = this.find(new DeptQuery());
            // Map<String, DeptEntity> localDeptMap = localDeptList.stream().collect(Collectors.toMap(x -> x.getDeptCode(), y -> y, (o, n) -> n));
            //差额对
            Map<String, OrgInfo> remoteDeptMap = orgInfoList.stream().collect(Collectors.toMap(x -> x.getOrgIndexCode(), y -> y, (o, n) -> n));

            List<DeptEntity> deleteLocalDeptList = localDeptList.stream().map(item -> {
                String deptCode = item.getDeptCode();
                OrgInfo orgInfo = remoteDeptMap.get(deptCode);
                if (ObjectUtils.isEmpty(orgInfo)) {
                    //需要删除的本地部门
                    return item;
                } else {
                    return null;
                }
            }).filter(f -> f != null).collect(Collectors.toList());

            if (!ObjectUtils.isEmpty(deleteLocalDeptList)) {
                log.info("delete dept lsit size :{}", deleteLocalDeptList.size());
            }
        }

        return Rest.ok();
    }

    @Override
    public Rest<String> syncDeptByDevice(Context context) {
        //todo
        return Rest.ok();
    }

    @Override
    public Rest<String> syncDeptByDingTalk(Context context) {
        Rest<List<OapiV2DepartmentListsubResponse.DeptBaseResponse>> depts = dingPersonService.getDepts(null);
        saveSubDepts(depts);
        return Rest.ok();
    }

    @Override
    public void saveSubDepts(Rest<List<OapiV2DepartmentListsubResponse.DeptBaseResponse>> depts) {
        if (depts.getCode() == YesNoEnum.YES.getValue()) {
            List<OapiV2DepartmentListsubResponse.DeptBaseResponse> data = depts.getData();
            for (OapiV2DepartmentListsubResponse.DeptBaseResponse dept : data) {
                String name = dept.getName();
                Long parentId = dept.getParentId();
                Long deptId = dept.getDeptId();

                DeptEntity deptEntity = this.selectOne(new DeptQuery().deptCode(deptId.toString()));
                DeptEntity deptEntityParent = this.selectOne(new DeptQuery().deptCode(parentId.toString()));
                //新增
                if (ObjectUtils.isEmpty(deptEntity)) {
                    deptEntity = new DeptEntity();
                    deptEntity.initAttrValue();
                    if (!ObjectUtils.isEmpty(deptEntityParent)) {
                        deptEntity.setParentId(deptEntityParent.getId());
                    }
                    deptEntity.setDeptName(name);
                    deptEntity.setDeptCode(deptId.toString());
                    // deptEntity.setRemark(orgInfo.getParentOrgIndexCode());
                    deptEntity.setCreateTime(new Date());
                    deptEntity.setCreateUserId(1L);
                    this.save(deptEntity);
                } else {
                    //更新
                    deptEntity.setDeptName(name);
                    deptEntity.setDeptCode(deptId.toString());
                    // deptEntity.setAncestors(orgInfo.getOrgPath());
                    deptEntity.setUpdateTime(new Date());
                    deptEntity.setUpdateUserId(1L);
                    this.update(deptEntity);
                }

                Boolean createDeptGroup = dept.getCreateDeptGroup();//是否有子部门
                if (createDeptGroup) {
                    //存在子部门 继续调用
                    Rest<List<OapiV2DepartmentListsubResponse.DeptBaseResponse>> deptSub = dingPersonService.getDepts(deptId);
                    saveSubDepts(deptSub);
                }

            }

        }
    }

}
