/*
 * Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yifu.cloud.plus.v1.yifu.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.unboundid.ldap.sdk.SearchResultEntry;
import com.yifu.cloud.plus.v1.yifu.admin.api.entity.SysDept;
import com.yifu.cloud.plus.v1.yifu.admin.api.entity.SysDeptRelation;
import com.yifu.cloud.plus.v1.yifu.admin.mapper.SysDeptMapper;
import com.yifu.cloud.plus.v1.yifu.admin.mapper.SysUserMapper;
import com.yifu.cloud.plus.v1.yifu.admin.service.SysDeptRelationService;
import com.yifu.cloud.plus.v1.yifu.admin.service.SysDeptService;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.ldap.util.LdapUtil;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * <p>
 * 部门管理 服务实现类
 * </p>
 *
 * @author lengleng
 * @since 2019/2/1
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements SysDeptService {

	private final SysDeptRelationService sysDeptRelationService;

	private final LdapUtil ldapUtil;

	private final SysUserMapper sysUserMapper;

	/**
	 * 添加信息部门
	 * @param dept 部门
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean saveDept(SysDept dept) {
		SysDept sysDept = new SysDept();
		BeanUtils.copyProperties(dept, sysDept);
		this.save(sysDept);
		sysDeptRelationService.saveDeptRelation(sysDept);
		return Boolean.TRUE;
	}

	/**
	 * 删除部门
	 * @param id 部门 ID
	 * @return 成功、失败
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean removeDeptById(Long id) {
		// 级联删除部门
		List<Long> idList = sysDeptRelationService
				.list(Wrappers.<SysDeptRelation>query().lambda().eq(SysDeptRelation::getAncestor, id)).stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());

		if (CollUtil.isNotEmpty(idList)) {
			this.removeByIds(idList);
		}

		// 删除部门级联关系
		sysDeptRelationService.removeDeptRelationById(id);
		return Boolean.TRUE;
	}

	/**
	 * 更新部门
	 * @param sysDept 部门信息
	 * @return 成功、失败
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean updateDeptById(SysDept sysDept) {
		// 更新部门状态
		this.updateById(sysDept);
		// 更新部门关系
		SysDeptRelation relation = new SysDeptRelation();
		relation.setAncestor(sysDept.getParentId());
		relation.setDescendant(sysDept.getDeptId());
		sysDeptRelationService.updateDeptRelation(relation);
		return Boolean.TRUE;
	}

	@Override
	public List<Long> listChildDeptId(Long deptId) {
		List<SysDeptRelation> deptRelations = sysDeptRelationService.list(Wrappers.<SysDeptRelation>lambdaQuery()
				.eq(SysDeptRelation::getAncestor, deptId).ne(SysDeptRelation::getDescendant, deptId));
		if (CollUtil.isNotEmpty(deptRelations)) {
			return deptRelations.stream().map(SysDeptRelation::getDescendant).collect(Collectors.toList());
		}
		return new ArrayList<>();
	}

	/**
	 * 查询全部部门树
	 * @return 树
	 */
	@Override
	public List<Tree<Long>> listDeptTrees() {
		return getDeptTree(this.list(Wrappers.emptyWrapper()), 0L);
	}

	/**
	 * 查询用户部门树
	 * @return
	 */
	@Override
	public List<Tree<Long>> listCurrentUserDeptTrees() {
		Long deptId = SecurityUtils.getUser().getDeptId();
		List<Long> descendantIdList = sysDeptRelationService
				.list(Wrappers.<SysDeptRelation>query().lambda().eq(SysDeptRelation::getAncestor, deptId)).stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());

		List<SysDept> deptList = baseMapper.selectBatchIds(descendantIdList);
		Optional<SysDept> dept = deptList.stream().filter(item -> item.getDeptId().intValue() == deptId).findFirst();
		return getDeptTree(deptList, dept.isPresent() ? dept.get().getParentId() : 0L);
	}

	/**
	 * 构建部门树
	 * @param depts 部门
	 * @param parentId 父级id
	 * @return
	 */
	private List<Tree<Long>> getDeptTree(List<SysDept> depts, Long parentId) {
		List<TreeNode<Long>> collect = depts.stream().filter(dept -> dept.getDeptId().intValue() != dept.getParentId())
				.sorted(Comparator.comparingInt(SysDept::getSortOrder)).map(dept -> {
					TreeNode<Long> treeNode = new TreeNode();
					treeNode.setId(dept.getDeptId());
					treeNode.setParentId(dept.getParentId());
					treeNode.setName(dept.getName());
					treeNode.setWeight(dept.getSortOrder());
					// 扩展属性
					Map<String, Object> extra = new HashMap<>(4);
					extra.put("createTime", dept.getCreateTime());
					treeNode.setExtra(extra);
					return treeNode;
				}).collect(Collectors.toList());

		return TreeUtil.build(collect, parentId);
	}

	/**
	 * 从ldap中获取部门
	 * @return R
	 */
	@Override
	public R<Boolean> updateDeptByLdap() {
		List<SearchResultEntry> entryList = ldapUtil.getAllPersonNamesWithTraditionalWay();
		List<Map<String,Object>> updUserList = new ArrayList<>();
		for (SearchResultEntry entry : entryList) {
			String dn = entry.getDN();
			String userId = "";
			if (dn.contains("uid")) {
				userId = dn.substring(4, dn.indexOf(",", 1));
				dn = dn.substring(dn.indexOf(",", 1) + 1);
			}
			List<String> saveDnList = Arrays.stream(dn.split(",")).filter(e -> (e.contains("ou=") && !e.equals("ou=wanxin"))).collect(Collectors.toList());
			String deptName = saveDnList.get(0).replace("ou=", "");
			int size = saveDnList.size();
			if (size == 1) {
				SysDept sysDept = baseMapper.selectDeptDn(dn);
				if (null == sysDept) {
					if (StringUtils.isEmpty(userId)) {
						SysDept ins = baseMapper.selectCountId(Long.valueOf(entry.getAttributeValue("x-ouid")));
						if (Common.isNotNull(ins)) {
							ins.setName(deptName);
							ins.setDeptDn(dn);
							baseMapper.updateDeptById(ins);
						} else {
							SysDept insertSysDept = new SysDept();
							insertSysDept.setName(deptName);
							insertSysDept.setParentId(0L);
							insertSysDept.setDeptDn(dn);
							if (Common.isNotNull(entry.getAttributeValue("x-ouid"))) {
								insertSysDept.setDeptId(Long.valueOf(entry.getAttributeValue("x-ouid")));
							}
							baseMapper.insert(insertSysDept);
						}
					}
				} else {
					sysDept.setName(deptName);
					baseMapper.updateDeptById(sysDept);
				}
			} else {
				try {
					SysDept sysDept = this.getOne(Wrappers.<SysDept>query().lambda().eq(SysDept::getDeptDn, dn.substring(dn.indexOf("ou=", 2), dn.length())));
					if (null != sysDept) {
						SysDept sysDeptCount = baseMapper.selectDeptDn(dn);
						if (null == sysDeptCount) {
							if (StringUtils.isEmpty(userId)) {
								SysDept ins = baseMapper.selectCountId(Long.valueOf(entry.getAttributeValue("x-ouid")));
								if (Common.isNotNull(ins)) {
									ins.setName(deptName);
									ins.setDeptDn(dn);
									ins.setParentId(sysDept.getDeptId());
									baseMapper.updateDeptById(ins);
								} else {
									SysDept insertSysDept = new SysDept();
									insertSysDept.setName(deptName);
									insertSysDept.setParentId(sysDept.getDeptId());
									insertSysDept.setDeptDn(dn);
									if (Common.isNotNull(entry.getAttributeValue("x-ouid"))) {
										insertSysDept.setDeptId(Long.valueOf(entry.getAttributeValue("x-ouid")));
									}
									baseMapper.insert(insertSysDept);
								}
							}
						} else {
							if (!StringUtils.isEmpty(userId)) {
								Map<String,Object> map = new HashMap<>();
								map.put("userId",userId);
								map.put("deptId",sysDeptCount.getDeptId());
								map.put("deptName",deptName);
								updUserList.add(map);
							}else {
								sysDeptCount.setName(deptName);
								sysDeptCount.setParentId(sysDept.getDeptId());
								sysDeptCount.setDeptDn(dn);
								baseMapper.updateDeptById(sysDeptCount);
							}
						}
					}
				} catch (Exception e) {
					log.info("更新异常：" + e.getMessage());
					return R.failed("同步信息失败！");
				}
			}
		}
		//更新用户信息
		if (!updUserList.isEmpty()) {
			sysUserMapper.updateUser(updUserList);
		}
		return R.ok();
	}
}
