package com.infoepoch.pms.agent.domain.baisc.organization;


import com.infoepoch.pms.agent.common.utils.LambdaTool;
import com.infoepoch.pms.agent.common.utils.StringTool;
import com.infoepoch.pms.agent.common.utils.TreeTool;
import com.infoepoch.pms.agent.domain.baisc.user.User;
import com.infoepoch.pms.agent.domain.baisc.user.organizationRela.IUserOrganizationRelaRepository;
import com.infoepoch.pms.agent.domain.baisc.user.organizationRela.UserOrganizationRela;
import com.infoepoch.pms.agent.domain.baisc.user.organizationRela.UserOrganizationRelaCriteria;
import com.infoepoch.pms.agent.platform.shared.exception.ValidationException;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 组织Service
 */
@Service
public class OrganizationService {

    @Autowired
    private IOrganizationRepository organizationRepository;
    @Autowired
    private IUserOrganizationRelaRepository userOrganizationRelaRepository;


    /**
     * 刷新组织
     */
    public void freshOrganization() {
        OrganizationRoot.fresh();
        updateOrganizationLevel();
    }

    /**
     * 根据组织名称获取指定组织，只查询分公司下一层
     *
     * @param orgName
     * @param branchCompanyId
     * @return
     */
    public Organization getDepartmentByName(String orgName, String branchCompanyId) {
        if (StringUtils.isBlank(orgName))
            return null;
        Organization branchCompany = organizationRepository.selectById(branchCompanyId);
        if (branchCompany == null)
            return null;
        if (StringTool.getString(branchCompany.getShortName()).contains(orgName)) {
            return branchCompany;
        }
        List<Organization> children = organizationRepository.selectByParentId(branchCompanyId);
        if (CollectionUtils.isEmpty(children))
            return null;
        for (Organization child : children) {
            if (StringTool.getString(child.getShortName()).contains(orgName)) {
                return child;
            }
        }
        return null;
    }

    /**
     * 根据组织名称向下获取组织（递归）
     *
     * @param orgName
     * @param organizationId
     * @return
     */
    public Organization getOrganizationByNameDown(String orgName, String organizationId) {
        if (StringUtils.isBlank(orgName))
            return null;
        Organization organization = organizationRepository.selectById(organizationId);
        return getOrganizationByNameDown(orgName, organization);
    }

    /**
     * 根据组织名称向下获取组织（递归）
     *
     * @param orgName
     * @param organization
     * @return
     */
    public Organization getOrganizationByNameDown(String orgName, Organization organization) {
        if (StringUtils.isBlank(orgName))
            return null;
        if (organization == null)
            return null;
        if (StringTool.getString(organization.getShortName()).contains(orgName)) {
            return organization;
        }
        List<Organization> children = organizationRepository.selectByParentId(organization.getId());
        return getOrganizationByNameDown(orgName, children);
    }

    /**
     * 根据组织名称向下获取组织（递归）
     *
     * @param orgName
     * @param organizationList
     * @return
     */
    public Organization getOrganizationByNameDown(String orgName, List<Organization> organizationList) {
        if (CollectionUtils.isEmpty(organizationList))
            return null;
        for (Organization organization : organizationList) {
            if (StringTool.getString(organization.getShortName()).contains(orgName)) {
                return organization;
            }
        }
        List<String> parentIdList = organizationList.stream().map(Organization::getId).collect(Collectors.toList());
        OrganizationCriteria criteria = new OrganizationCriteria();
        criteria.setParentIdList(parentIdList);
        List<Organization> children = organizationRepository.selectByCriteria(criteria);
        return getOrganizationByNameDown(orgName, children);
    }

    public Organization getByOaCode(String oaCode) {
        if (oaCode == null)
            return null;
        return organizationRepository.selectByOaOrgCode(oaCode);
    }

    /**
     * @param criteria
     * @return
     */
    public List<Organization> queryByCriteria(OrganizationCriteria criteria) {
        return organizationRepository.selectByCriteria(criteria);
    }

    /**
     * @param criteria
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public List<Organization> queryByCriteriaPage(OrganizationCriteria criteria, int pageIndex, int pageSize) {
        return organizationRepository.selectByCriteriaPage(criteria, pageIndex, pageSize);
    }

    /**
     * @param criteria
     * @param pageIndex
     * @param pageSize
     * @return
     */
    public List<Organization> queryByCriteriaPage(OrganizationCriteria criteria, int pageIndex, int pageSize, String orderBy, boolean isDesc) {
        return organizationRepository.selectByCriteriaPage(criteria, pageIndex, pageSize, orderBy, isDesc);
    }

    /**
     * @param criteria
     * @return
     */
    public int queryByCriteriaCount(OrganizationCriteria criteria) {
        return organizationRepository.selectCountByCriteria(criteria);
    }

    /**
     * 组织详情
     *
     * @param id
     * @return
     */
    public Organization detail(String id) {
        return organizationRepository.selectById(id);
    }

    /**
     * @param organization
     */
    public void create(Organization organization) {
        Organization add = new Organization(
                organization.getName(),
                organization.getShortName(),
                organization.isDisabled(),
                organization.getDescription(),
                organization.getOaOrgCode(),
                organization.getHrOrgCode(),
                organization.getpId(),
                organization.getDisplayOrder(),
                organization.getParentOrgCode(),
                organization.getLevel()
        );
        organizationRepository.insert(add);
        // 刷新组织树
        this.freshOrganization();
    }

    /**
     * @param organization
     */
    public void modify(Organization organization) {
        Organization old = OrganizationRoot.getById(organization.getId());
        old.modify(
                organization.getName(),
                organization.getShortName(),
                organization.isDisabled(),
                organization.getDescription(),
                organization.getOaOrgCode(),
                organization.getHrOrgCode(),
                organization.getDisplayOrder(),
                organization.getParentOrgCode(),
                organization.getLevel()
        );
        organizationRepository.update(old);
        // 刷新组织树
        this.freshOrganization();
    }

    /**
     * 删除组织
     *
     * @param id
     */
    public void remove(String id) {
        Organization organization = OrganizationRoot.getById(id);
        if (organization.hasChildren()) {
            throw new ValidationException("不可删除含有子组织的节点");
        }
        // 删除组织信息
        organizationRepository.deleteById(id);
        // 刷新组织树
        this.freshOrganization();
    }

    /**
     * 根据名称获取组织
     *
     * @param shortName
     * @return
     */
    public Organization getByShortName(String shortName) {
        return organizationRepository.selectByShortName(shortName);
    }

    /**
     * 获取所有父节点的ID，直到根节点
     *
     * @param organization
     * @return
     */
    public List<String> getParentsId(Organization organization) {
        List<String> resultList = new ArrayList<>();
        resultList.add(organization.getId());
        if (organization.getpId().equals("0"))
            return resultList;
        Organization parentOrg = organizationRepository.selectById(organization.getpId());
        if (parentOrg != null) {
            resultList.addAll(getParentsId(parentOrg));
        }
        return resultList;
    }

    /**
     * 获取组织下所有子组织ID
     *
     * @param orgId
     * @return
     */
    public List<String> getChildrenOrgIdList(String orgId) {
        return getChildrenOrgList(orgId).stream().map(Organization::getId).collect(Collectors.toList());
    }

    /**
     * 获取组织下所有子组织
     *
     * @param orgId
     * @return
     */
    public List<Organization> getChildrenOrgList(String orgId) {
        List<Organization> resultList = new ArrayList<>();
        List<Organization> children = organizationRepository.selectByParentId(orgId);
        if (CollectionUtils.isEmpty(children)) {
            return resultList;
        } else {
            resultList.addAll(children);
            List<String> orgIdList = children.stream().map(Organization::getId).collect(Collectors.toList());
            List<Organization> list = getChildrenLoop(orgIdList);
            resultList.addAll(list);
        }
        return resultList;
    }

    /**
     * 循环获取组织子节点列表
     *
     * @param orgIdList
     * @return
     */
    public List<Organization> getChildrenLoop(List<String> orgIdList) {
        List<Organization> resultList = new ArrayList<>();
        if (CollectionUtils.isEmpty(orgIdList)) {
            return resultList;
        } else {
            List<Organization> children = organizationRepository.selectByParentIdList(orgIdList);
            if (CollectionUtils.isEmpty(children)) {
                return resultList;
            } else {
                resultList.addAll(children);
                List<String> idList = children.stream().map(Organization::getId).collect(Collectors.toList());
                List<Organization> list = getChildrenLoop(idList);
                resultList.addAll(list);
            }
        }
        return resultList;
    }

    /**
     * @param orgIdList
     * @return
     */
    public List<String> getChildrenIdLoop(List<String> orgIdList) {
        Set<String> orgIdSet = new HashSet<>();
        if (CollectionUtils.isEmpty(orgIdList)) {
            return new ArrayList<>(orgIdSet);
        } else {
            List<Organization> children = organizationRepository.selectByParentIdList(orgIdList);
            if (CollectionUtils.isEmpty(children)) {
                return new ArrayList<>(orgIdSet);
            } else {
                orgIdSet.addAll(children.stream().map(Organization::getId).collect(Collectors.toList()));
                List<String> idList = children.stream().map(Organization::getId).collect(Collectors.toList());
                List<Organization> list = getChildrenLoop(idList);
                orgIdSet.addAll(list.stream().map(Organization::getId).collect(Collectors.toList()));
            }
        }
        return new ArrayList<>(orgIdSet);
    }

    /**
     * @return
     */
    public List<Map<String, Object>> getRootOrganizationMapList() {
        List<Organization> organizationList = OrganizationRoot.getRootOrganizations();
        List<Map<String, Object>> resultList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(organizationList)) {
            resultList = getChildrenOrg(organizationList, null);
        }
        return resultList;
    }

    /**
     * @param organizationId
     * @return
     */
    public List<Map<String, Object>> getCurrentDepartmentOrg(String organizationId) {
        List<Organization> organizationList = new ArrayList<>();
        Organization organization = OrganizationRoot.getCompanyById(organizationId);
        if (organization == null) {
            return new ArrayList<>();
        }
        if (OrganizationRoot.judgeBranchCompany(organization.getId())) {
            organizationList.add(organization);
        } else {
            organizationList = OrganizationRoot.getRootOrganizations();
        }

        List<Map<String, Object>> resultList = new ArrayList<>();
        // 只获取到部门
        if (CollectionUtils.isNotEmpty(organizationList)) {
            resultList = getChildrenOrg(organizationList, 3);
        }
        return resultList;
    }

    /**
     * 获取当前公司组织树 权限设置省公司返回全省组织 分公司返回分公司组织 只返回到部门层级 去掉根组织
     *
     * @param loginUser
     * @return
     */
    public Map<String, Object> getCurrentCompanyOrgNotRoot(User loginUser) {
        List<Organization> organizationList = new ArrayList<>();
        String companyId = "";
        List<Organization> rootOrganizations = OrganizationRoot.getRootOrganizations();
        if (CollectionUtils.isNotEmpty(rootOrganizations)) {
            organizationList = rootOrganizations.get(0).getChildren();
        }
        List<Map<String, Object>> resultList = new ArrayList<>();
        Organization organization = OrganizationRoot.getCompanyById(loginUser.getOrganizationId());
        if (OrganizationRoot.judgeBranchCompany(organization.getId())) {//省公司看全省，分公司看分公司，如果是分公司则筛选一下
            organizationList = organizationList.stream().filter(f -> f.getId().equals(organization.getId())).collect(Collectors.toList());
            companyId = organization.getId();
        } else {
            Map<String, Object> map = new HashMap<>();
            map.put("value", "");
            map.put("label", "所有");
            resultList.add(map);
        }
        // 只获取到部门
        if (CollectionUtils.isNotEmpty(organizationList)) {
            resultList.addAll(getChildrenOrgHome(organizationList, 3));
        }
        Map<String, Object> map = new HashMap<>();
        map.put("orgList", resultList);
        map.put("companyId", companyId);
        return map;
    }

    /**
     * 获取当前部门组织树 权限设置部门返回部门组织 人力部门返回全组织 只返回到部门层级 去掉根组织
     *
     * @param loginUser
     * @return
     */
    public Map<String, Object> getCurrentDepOrgNotRoot(User loginUser) {
        List<Organization> organizationList = new ArrayList<>();
        String depId = "";
        List<Organization> rootOrganizations = OrganizationRoot.getRootOrganizations();
        if (CollectionUtils.isNotEmpty(rootOrganizations)) {
            organizationList = rootOrganizations.get(0).getChildren();
        }
        List<Map<String, Object>> resultList = new ArrayList<>();
        Organization organization = OrganizationRoot.getDepartmentById(loginUser.getOrganizationId());//查询部门
        Organization companyOrg = OrganizationRoot.getCompanyById(loginUser.getOrganizationId());//查询公司
        if (OrganizationRoot.judgeBranchCompany(companyOrg) && organization.getName().contains("工会")) {//分公司人力
            organizationList = organizationList.stream().filter(f -> f.getId().equals(companyOrg.getId())).collect(Collectors.toList());
            depId = companyOrg.getId();
        } else if (OrganizationRoot.judgeHeadquarters(companyOrg) && organization.getName().contains("工会")) {//省公司人力
            Map<String, Object> map = new HashMap<>();
            map.put("value", "");
            map.put("label", "所有");
            resultList.add(map);
        } else {//返回部门
            organizationList = organizationList.stream().filter(f -> f.getId().equals(organization.getpId())).collect(Collectors.toList());
            for (Organization o : organizationList) {
                o.setFrontDisabled(true);//禁用2级组织
                o.setChildren(o.getChildren().stream().filter(f -> f.getId().equals(organization.getId())).collect(Collectors.toList()));
            }
            depId = organization.getId();
        }
        // 只获取到部门
        if (CollectionUtils.isNotEmpty(organizationList)) {
            resultList.addAll(getChildrenOrgHome(organizationList, 3));
        }
        Map<String, Object> map = new HashMap<>();
        map.put("orgList", resultList);
        map.put("depId", depId);
        return map;
    }

    /**
     * @param organizationList
     * @return
     */
    public List<Map<String, Object>> getOrganizationMapList(List<Organization> organizationList) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(organizationList)) {
            resultList = getChildrenOrg(organizationList, null);
        }
        return resultList;
    }

    /**
     * @param organizationList
     * @return
     */
    private List<Map<String, Object>> getChildrenOrg(List<Organization> organizationList, Integer level) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        for (Organization organization : organizationList) {
            if (organization.getName().contains("公司领导")) {
                continue;
            }
            Map<String, Object> map = new HashMap<>();
            map.put("value", organization.getId());
            map.put("label", organization.getShortName());
            List<Map<String, Object>> children = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(organization.getChildren()) && (level != null && organization.getLevel() < level)) {
                children = getChildrenOrg(organization.getChildren(), level);
            }
            if (CollectionUtils.isNotEmpty(children)) {
                map.put("children", children);
            }
            resultList.add(map);
        }
        return resultList;
    }

    private List<Map<String, Object>> getChildrenOrgHome(List<Organization> organizationList, Integer level) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        for (Organization organization : organizationList) {
            if (organization.getName().contains("公司领导")) {
                continue;
            }
            if (organization.isDisabled()) {
                continue;
            }
            Map<String, Object> map = new HashMap<>();
            map.put("value", organization.getId());
            map.put("label", organization.getShortName());
            if (organization.getFrontDisabled() != null && organization.getFrontDisabled()) {
                map.put("disabled", true);
            }
            List<Map<String, Object>> children = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(organization.getChildren()) && (level != null && organization.getLevel() < level)) {
                children = getChildrenOrgHome(organization.getChildren(), level);
            }
            if (CollectionUtils.isNotEmpty(children)) {
                map.put("children", children);
            }
            resultList.add(map);
        }
        return resultList;
    }

    /**
     * 更新组织层级
     */
    private void updateOrganizationLevel() {
        List<Organization> updateList = new ArrayList<>();
        TreeTool.loopCallback(OrganizationRoot.getRootOrganizations(), Organization::getChildren, (Consumer<Organization>) updateList::add);
        organizationRepository.batchUpdateLevel(updateList);
    }

    /**
     * 更新省本部下组织的名称
     */
    public void updateProvinceOrganizationName() {
        // 查询省本部组织信息
        Organization provinceOrg = organizationRepository.selectByOaOrgCode("00230010000000000000");
        OrganizationCriteria criteria = new OrganizationCriteria();
        // 只查询省本部下的组织
        List<String> orgIdList = OrganizationRoot.getChildrenLoopId(provinceOrg.getId());
        criteria.setOrgIdList(orgIdList);
        List<Organization> organizationList = organizationRepository.selectByCriteria(criteria);

        // 按照组织级别分组
        Map<Integer, List<Organization>> organizationListMap = LambdaTool.changeCollectionToHashListMap(organizationList, Organization::getLevel);
        int maxLevel = 0;
        for (Organization org : organizationList) {
            if (org.getLevel() > maxLevel) {
                maxLevel = org.getLevel();
            }
        }
        List<Organization> updateList = new ArrayList<>();
        Map<String, Organization> organizationMap = new HashMap<>();
        // 将省本部放入map中
        organizationMap.put(provinceOrg.getId(), provinceOrg);
        // 从第三层组织开始处理（省本部组织层级为2）
        for (int level = 3; level <= maxLevel; level++) {
            List<Organization> list = organizationListMap.get(level);
            for (Organization o : list) {
                Organization parent = organizationMap.get(o.getpId());
                if (parent != null) {
                    o.setName(parent.getName() + "\\" + o.getShortName());
                    updateList.add(o);
                }
            }
            // 将处理好的层级放入map，用于下一层级循环时使用
            organizationMap = LambdaTool.changeCollectionToHashMap(list, Organization::getId);
        }
        organizationRepository.batchUpdate(updateList);
    }

    /**
     * 根据组织ID获取部门和部门之下的组织列表
     *
     * @param orgIds
     * @return
     */
    public List<Organization> getOrganizationUnderDepartmentByIds(List<String> orgIds) {
        List<Organization> organizationList = organizationRepository.selectByIds(orgIds);
        // 根节点默认为部门级，如果是部门之下的组织，需要查询对应的部门
        Set<String> roomIdSet = new HashSet<>();
        for (Organization organization : organizationList) {
            if (organization.getLevel() > 3) {
                roomIdSet.add(organization.getpId());
            }
        }
        if (CollectionUtils.isNotEmpty(roomIdSet)) {
            List<Organization> pList = getOrganizationUnderDepartmentByIds(new ArrayList<>(roomIdSet));
            Set<String> oldIdSet = new HashSet<>();
            for (Organization organization : organizationList) {
                oldIdSet.add(organization.getId());
            }
            for (Organization organization : pList) {
                if (!oldIdSet.contains(organization.getId())) {
                    organizationList.add(organization);
                }
            }
        }
        return organizationList;
    }

    /**
     * 获取用户关联组织
     *
     * @param userId 用户ID
     * @return 组织列表
     */
    public List<UserOrganizationRela> getUserOrganizationList(String userId) {
        if (StringUtils.isBlank(userId))
            return new ArrayList<>();
        UserOrganizationRelaCriteria criteria = new UserOrganizationRelaCriteria();
        criteria.setUserId(userId);
        List<UserOrganizationRela> resultList = userOrganizationRelaRepository.selectByCriteria(criteria);
        if (CollectionUtils.isEmpty(resultList))
            return resultList;
        List<String> orgIdList = resultList.stream().map(UserOrganizationRela::getOrganizationId).collect(Collectors.toList());
        List<Organization> organizationList = organizationRepository.selectByIds(orgIdList);
        if (CollectionUtils.isEmpty(organizationList))
            return resultList;
        Map<String, Organization> organizationMap = LambdaTool.changeCollectionToHashMap(organizationList, Organization::getId);
        for (UserOrganizationRela organizationRela : resultList) {
            Organization organization = organizationMap.get(organizationRela.getOrganizationId());
            if(organization != null) {
                organizationRela.setOrganizationName(organization.getName());
            }
        }
        return resultList;
    }

}
