/**
 * Copyright (c) 2018 人人开源 All rights reserved.
 * 
 * https://www.renren.io
 * 
 * 版权所有,侵权必究!
 */
package com.zt.modules.sys.service;
import cn.hutool.core.convert.Convert;
import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.zt.common.constant.Constant;
import com.zt.common.constant.Status;
import com.zt.common.db.query.QueryFilter;
import com.zt.common.entity.MapData;
import com.zt.common.exception.ErrorCode;
import com.zt.common.exception.RenException;
import com.zt.common.service.BaseService;
import com.zt.common.servlet.Result;
import com.zt.common.utils.CacheUtils;
import com.zt.common.utils.TreeUtils;
import com.zt.core.context.User;
import com.zt.core.context.UserContext;
import com.zt.core.sys.model.SysDept;
import com.zt.core.sys.service.ISysDeptService;
import com.zt.modules.sys.dao.SysDeptDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * 部门管理
 *
 * @author hehz
 */
@Service
public class SysDeptService extends BaseService implements ISysDeptService {
    @Autowired
    private SysUserService sysUserService;
    private List getAll() {
        // 这里手动缓存,不然在当前方法内调用缓存无效
        List all = null;//(List) CacheUtils.get(Constant.Cache.DEPT, "all");
        if (all == null) {
            all = baseDao.getAll();
            //CacheUtils.put(Constant.Cache.DEPT, "all", all);
        }
        return all.stream().map(dept -> {
            try {
                return dept.clone();
            } catch (CloneNotSupportedException e) {
            }
            return null;
        }).collect(Collectors.toList());
    }
    public List getTenantAll() {
        return getAll();
//        return getAll().stream().filter(dept -> dept.getTenantId().equals(UserContext.getUser().getTenantId()))
//                .collect(Collectors.toList());
    }
    /**
     * 查询当前租户下公司树
     *
     * @return
     */
    public List getCompanyTree() {
        List list = getTenantAll().stream().filter(dept -> dept.isCompany()).collect(Collectors.toList());
        // 查询所属公司及子公司的数据
        List deptIds = this.getWithDescendantIds(UserContext.getUser().getCompanyId());
        list = list.stream().filter(dept -> deptIds.contains(dept.getId())).collect(Collectors.toList());
        List listOut = TreeUtils.build(list);
        //List listOut2 = TreeUtils.toList(listOut);
        return listOut;
    }
    /**
     * 查询当前登录用户公司部门树
     *
     * @return
     */
    public List getDeptTreeRegister() {
        List list = getTenantAll();
        List listArea = list.stream().filter(dept -> "sy".equals(dept.getCode())).collect(Collectors.toList());
        if (listArea.size() > 0) {
            Long deptId = listArea.get(0).getId();
            List deptIds = this.getWithDescendantIds(deptId);
            deptIds.remove(0);
            list = list.stream().filter(dept -> deptIds.contains(dept.getId())).collect(Collectors.toList());
        }
        return TreeUtils.build(list);
    }
    public List getDeptTree() {
        User user = UserContext.getUser();
        List list = getTenantAll();
        if (1==0 && !user.isSuperAdmin()) {
            // 查询所属部门及子部门的数据
            List deptIds = this.getWithDescendantIds(user.getDeptId());
            list = list.stream().filter(dept -> deptIds.contains(dept.getId())).collect(Collectors.toList());
        }
        return TreeUtils.build(list);
    }
    /**
     * 查询公司下部门树
     *
     * @param companyId
     * @return
     */
    public List getDeptList(Long companyId) {
        QueryFilter queryFilter = new QueryFilter();
        // 普通管理员,只能查询所属部门及子部门的数据
        User user = UserContext.getUser();
/*        if (!user.isSuperAdmin()) {
            queryFilter.addParam("deptIds", this.getWithDescendantIds(user.getDeptId()));
        }*/
        // 查询公司下部门列表
        queryFilter.addParam("isCompany", Constant.Bool.NO);
        queryFilter.addParam("companyId", companyId);
        // 查询部门列表
        List entityList = baseDao.getList(queryFilter.getParams());
        return TreeUtils.build(entityList);
    }
    @Override
    @Cacheable(value = Constant.Cache.DEPT, key = "'id:' + #id")
    public SysDept get(Long id) {
        return baseDao.getById(id);
    }
    /**
     * 通过deptId查找所有祖先,按照祖先的层级排序
     *
     * @param id
     * @return
     */
    @Override
    public List getAncestor(Long id) {
        return TreeUtils.getAncestor(getTenantAll(), id);
    }
    /**
     * 获取自己和所有下级
     *
     * @param id
     * @return
     */
    public List getWithDescendant(Long id) {
        return TreeUtils.getWithDescendant(getTenantAll(), id);
    }
    @Override
    @Cacheable(value = Constant.Cache.DEPT, key = "'withdescendant:' + #id")
    public List getWithDescendantIds(Long id) {
        return this.getWithDescendant(id).stream().map(dept -> dept.getId()).collect(Collectors.toList());
    }
    /**
     * 获取下级
     *
     * @param id
     * @return
     */
    @Override
    public List getDescendant(Long id) {
        return TreeUtils.getDescendant(getTenantAll(), id);
    }
    /**
     * 获取某部门的子节点
     *
     * @param id
     * @return
     */
    @Override
    public List getChildren(Long id) {
        return getTenantAll().stream().filter(dept -> dept.getPid().equals(id)).collect(Collectors.toList());
    }
    public List getByTypes(List types) {
        return getTenantAll().stream().filter(dept -> types.contains(dept.getNature())).collect(Collectors.toList());
    }
    /**
     * 增加部门
     *
     * @param dept
     */
    @Override
    @CacheEvict(value = Constant.Cache.DEPT, allEntries = true)
    public void insert(SysDept dept) {
        if (dept.getId() == null || dept.getId() == 0) {
            dept.setId(IdWorker.getId());
        }
        dept.setStatus(Status.ENABLE.getValue());
        resetFullNameAndInnerId(dept, null);
        // 部门类型为公司时,生成id
        if (dept.isCompany()) {
            dept.setCompanyId(dept.getId());
        }
        dept.setTenantId(1L);
        super.insert(dept);
        // 更新数据范围表
        // dataScopeService.updateByDeptAdd(dept.getId(), dept.getParentId());
    }
    /**
     * 更新部门
     *
     * @param dept
     */
    @Override
    @CacheEvict(value = Constant.Cache.DEPT, allEntries = true)
    public void update(SysDept dept) {
        Long id = dept.getId();
        if (id == 0) {
            throw new RenException("获取主键失败");
        }
        SysDept tmp = get(id);
        TreeUtils.updateValidate(getTenantAll(), dept, tmp);
        if (!tmp.getPid().equals(dept.getPid())) {// 部门层级改变了
            resetFullNameAndInnerId(dept, null);
        }
        super.update(dept);
        // if (!tmp.getPid().equals(pid)) {// 部门层级改变了
        // // 更新数据范围表
        // dataScopeService.updateByDeptUpdate(dept.getId(),
        // dept.getParentId());
        // }
    }
    /**
     * 删除部门
     *
     * @param id
     */
    @Override
    @CacheEvict(value = Constant.Cache.DEPT, allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        // 判断是否有子部门
        List subList = this.getWithDescendantIds(id);
        if (subList.size() > 1) {
            throw new RenException(ErrorCode.DEPT_SUB_DELETE_ERROR);
        }
        // 判断部门下面是否有用户
        int count = sysUserService.getByDeptId(id).size();
        if (count > 0) {
            throw new RenException(ErrorCode.DEPT_USER_DELETE_ERROR);
        }
        // 删除
        this.deleteLogic(id);
    }
    /**
     * 修改全称和内部编码
     *
     * @param dept
     * @param parent
     */
    private void resetFullNameAndInnerId(SysDept dept, SysDept parent) {
        if (parent == null) {
            parent = get(dept.getPid());
        }
        if (parent != null) {// 存在上级
            dept.setPids(parent.getPids() + "," + String.valueOf(dept.getId()));
        } else {// 没有上级
            dept.setPids(String.valueOf(dept.getId()));
        }
        resetChildFullNameAndInnerId(dept);
    }
    /**
     * 修改子类全称和内部编码
     *
     * @param parent
     */
    private void resetChildFullNameAndInnerId(SysDept parent) {
        List list = getChildren(parent.getId());
        for (SysDept dept : list) {
            resetFullNameAndInnerId(dept, parent);
            this.update(dept);
            resetChildFullNameAndInnerId(dept);
        }
    }
    public List fetchRepairer() {
        List list = this.getTenantAll();
        String factoryId = "cj".equals(UserContext.getUser().getUnitType()) ? UserContext.getUser().getCompanyId().toString() : "";
        String regionFlag = UserContext.getUser().getArea();//getSessionValue(UserContext.REGION_FLAG);
        /*
        如果属于某厂家,就返回此厂家
         */
        if (!StringUtils.isEmpty(factoryId)) {
            List collect = list
                    .stream()
                    .filter(dept -> {
                        return dept.getId().equals(new Long(factoryId));
                    })
                    .collect(Collectors.toList());
            return collect;
        }
        if (!StringUtils.isEmpty(regionFlag)) {
            List collectRegion = list
                    .stream()
                    .filter(dept -> {
                        return dept.getCode().equals(regionFlag);
                    })
                    .collect(Collectors.toList());
            if (!collectRegion.isEmpty()) {
                final SysDept regionSysDept = collectRegion.get(0);
                List collect = list
                        .stream()
                        .filter(dept -> {
                            String pids = dept.getPids();
                            String[] pidsArray = pids.split(",");
                            for (String pid : pidsArray) {
                                if (pid.equals(regionSysDept.getId().toString()) && new Integer(2).equals(dept.getNature())) {
                                    return true;
                                }
                            }
                            return false;
                        })
                        .collect(Collectors.toList());
                return collect;
            }
        }
        List collect = list
                .stream()
//                .filter(dept -> (new Integer(1).equals(dept.getNature()) && dept.isCompany())
//                        || (new Integer(2).equals(dept.getNature()) && dept.isCompany() /*&& dept.getPid().toString().equals("1271368584383188993") */)
//                        || "HBDD".equals(dept.getCode()))
                 .filter(dept -> "cj".equals(dept.getNature()))
                .collect(Collectors.toList());
        return collect;
    }
    public Long fetchRepairerId(String factoryName) {
        List list = this.fetchRepairer();
        if (list != null && !list.isEmpty()) {
            for (SysDept sysDept : list) {
                if (sysDept.getName() != null && sysDept.getName().equals(factoryName)) {
                    return sysDept.getId();
                }
            }
        }
        return null;
    }
    public List getListByParent(String pid, String pCode, String code) {
        HashMap map = new HashMap<>();
        map.put("pCode", pCode);
        map.put("code", code);
        map.put("pId", pid);
        List list = baseDao.getListByParent(map);
        return list;
    }
    public Long getCompanyIdByDeptId(Long deptId) {
        SysDept sysDept = baseDao.getById(deptId);
        if (sysDept != null)
            return sysDept.getCompanyId();
        else
            return deptId;
    }
    public Map getMapFactory(Boolean idToName) {
        List list = this.getTenantAll();
        List collect = list
                .stream()
                .filter(dept -> ("cj".equals(dept.getNature()) ))
                .collect(Collectors.toList());
        Map result = new HashMap<>();
        for (SysDept item : collect) {
            if (idToName)
                result.put(item.getId().toString(), item.getName());
            else
                result.put(item.getName(), item.getId().toString());
        }
        return result;
    }
    public Map getMapTeamFactory(Boolean idToName) {
        List list = this.getTenantAll();
        List collect = list
                .stream()
                .filter(dept -> ("cj".equals(dept.getNature()) ||"td".equals(dept.getNature())))
                .collect(Collectors.toList());
        Map result = new HashMap<>();
        for (SysDept item : collect) {
            if (idToName)
                result.put(item.getId().toString(), item.getName());
            else
                result.put(item.getName(), item.getId().toString());
        }
        return result;
    }
    public List getDeptList3() {
        return baseDao.getDeptList3();
    }
}