package com.infoepoch.pms.dispatchassistant.domain.basic.organization;

import com.infoepoch.pms.dispatchassistant.common.exception.ValidationException;
import com.infoepoch.pms.dispatchassistant.common.utils.LambdaTool;
import com.infoepoch.pms.dispatchassistant.common.utils.StringTool;
import com.infoepoch.pms.dispatchassistant.common.utils.StringUtils;
import com.infoepoch.pms.dispatchassistant.common.utils.TreeTool;
import org.apache.commons.collections4.CollectionUtils;
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;


    /**
     * 刷新组织
     */
    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 OrganizationRoot.getById(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 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 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);
    }

}
