package com.securitycontrol.system.service;

import com.alibaba.nacos.common.utils.UuidUtils;
import com.securitycontrol.common.core.domain.Result;
import com.securitycontrol.common.core.utils.aes.ListHelper;
import com.securitycontrol.common.core.utils.aes.StringHelper;
import com.securitycontrol.entity.system.dto.OrgDto;
import com.securitycontrol.entity.system.vo.OrgVo;
import com.securitycontrol.system.mapper.OrgMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author HeiZi
 */
@Service
@Slf4j
public class OrgServiceImpl implements OrgService {


    @Resource
    private OrgMapper mapper;

    private final static String P_ID = "0";

    private final static int SUCCESS = 0;

    @Override
    public Result<List<OrgVo>> getOrgList(OrgDto dto) {
        List<OrgVo> list = mapper.getOrgList(dto);
        if (ListHelper.isEmpty(list)) {
            return Result.ok(new ArrayList<>());
        }
        if (StringHelper.isNotEmpty(dto.getKeyWord())) {
            List<OrgVo> allList = new ArrayList<>(list);
            List<OrgVo> list2 = mapper.getOrgList(null);
            for (OrgVo org : list) {
                if (!P_ID.equals(org.getPId())) {
                    getParentOrg(org.getPId(), list2, allList);
                }
            }
            allList = allList.stream().filter(distinctByKey(OrgVo::getOrgId)).collect(Collectors.toList());
            return Result.ok(getChildList(allList));
        }
        return Result.ok(getChildList(list));
    }


    static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>(30);
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    /**
     * 依据下级节点查询上级数据
     *
     * @param orgId
     * @return
     */
    public void getParentOrg(String orgId, List<OrgVo> list, List<OrgVo> list2) {
        OrgVo vo = list.stream().filter(org -> orgId.equals(org.getOrgId())).findFirst().orElse(null);
        assert vo != null;
        list2.add(vo);
        if (!P_ID.equals(vo.getPId())) {
            getParentOrg(vo.getPId(), list, list2);
        }

    }


    @Override
    public Result<String> addOrg(OrgVo dto) {
        try {
            if (StringHelper.isEmpty(dto.getOrgId())) {
                dto.setOrgId(UuidUtils.generateUuid().toUpperCase());
            }
            if (StringHelper.isEmpty(dto.getPId())) {
                dto.setPId("0");
            }
            int exitNum = mapper.getNumByName(dto);
            if (exitNum > SUCCESS) {
                return Result.fail("该组织机构已存在!");
            }
            int num = mapper.addOrg(dto);
            if (num > SUCCESS) {
                return Result.ok("新增成功");
            }
            return Result.fail("新增失败");
        } catch (Exception e) {
            log.error(e.toString(), e);
            return Result.fail("服务异常");
        }
    }

    @Override
    public Result<String> updateOrg(OrgVo dto) {
        try {
            OrgVo orgVo = mapper.getDetails(dto.getOrgId());
            if (orgVo == null) {
                return Result.fail("数据不存在");
            }
            if (orgVo.getOrgId().equals(dto.getPId())) {
                return Result.fail("父节点不能是自己");
            }
            if (StringHelper.isEmpty(dto.getOrgId())) {
                return Result.fail("主键不能为空");
            }
            if (StringHelper.isEmpty(dto.getPId())) {
                dto.setPId("0");
            }
            int exitNum = mapper.getNumByName(dto);
            if (exitNum > SUCCESS) {
                return Result.fail("该组织机构已存在!");
            }
            int num = mapper.updateOrg(dto);
            if (num > SUCCESS) {
                return Result.ok("修改成功");
            }
            return Result.fail("修改失败");
        } catch (Exception e) {
            log.error(e.toString(), e);
            return Result.fail("服务异常");
        }
    }

    @Override
    public Result<String> delOrg(OrgDto dto) {
        try {
            if (StringHelper.isEmpty(dto.getOrgId())) {
                return Result.ok("主键不能为空");
            }
            int childNum = mapper.getChildNum(dto);
            if (childNum > SUCCESS) {
                return Result.fail("请先删除子节点数据");
            }
            int num = mapper.delOrg(dto);
            if (num > SUCCESS) {
                return Result.ok("删除成功");
            }
            return Result.fail("删除失败");
        } catch (Exception e) {
            log.error(e.toString(), e);
            return Result.fail("服务异常");
        }
    }

    /**
     * 依据id查询详情
     *
     * @param dto
     * @return
     */
    @Override
    public Result<OrgVo> getDetails(String id) {
        try {
            OrgVo orgVo = mapper.getDetails(id);
            return Result.ok(orgVo);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }

        return Result.fail(new OrgVo());
    }


    /**
     * 遍历获取
     *
     * @param list
     * @return
     */
    public List<OrgVo> getChildList(List<OrgVo> list) {
        //map
        list.stream().map(orgVo -> {
            orgVo.setChildren(this.fromTree(orgVo, list));
            return orgVo;
        }).collect(Collectors.toList());
        //过滤出最上级的菜单
        return list.stream()
                .filter(ele -> P_ID.equals(ele.getPId()))
                .collect(Collectors.toList());

    }

    /**
     * 找寻指定菜单的下级菜单
     *
     * @param orgVo 当前菜单
     * @param list  所有的菜单list
     * @return 下级菜单
     */
    private List<OrgVo> fromTree(OrgVo orgVo, List<OrgVo> list) {
        return list.stream()
                .filter(ele -> orgVo.getOrgId().equals(ele.getPId()))
                .collect(Collectors.toList());
    }

}
