package com.neusoft.smart.pos.user.service;

import com.neusoft.smart.pos.dto.org.response.PostOrgResponse;
import com.neusoft.smart.pos.dto.user.TreeNode;
import com.neusoft.smart.pos.framework.dto.ResponseData;
import com.neusoft.smart.pos.framework.exception.BusinessCommonException;
import com.neusoft.smart.pos.user.persistent.domain.*;
import com.neusoft.smart.pos.user.persistent.mapper.*;
import com.neusoft.smart.pos.utils.RequestHeaderUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.neusoft.smart.pos.framework.constants.ApplicationConstants.SUCCESS_CODE;
import static com.neusoft.smart.pos.framework.constants.RoleConstant.ROLE_ADMIN;
import static com.neusoft.smart.pos.framework.constants.RoleConstant.ROLE_SA;

@Service
public class PermissionService {
    @Resource
    UserMapper userMapper;
    @Resource
    private UserPermissionGroupMapper userPermissionGroupMapper;
    @Resource
    private PermissionGroupPermissionMapper permissionGroupPermissionMapper;
    @Resource
    private PermissionMapper permissionMapper;
    @Resource
    private PermissionGroupMapper permissionGroupMapper;

    @Resource
    RemoteOrgService remoteOrgService;

    public int addUserPermissionGroup(int userId, int permissionGroupId) {
        UserPermissionGroupExample userPermissionGroupExample = new UserPermissionGroupExample();
        userPermissionGroupExample.createCriteria()
                .andUserEqualTo(userId)
                .andPermissionGroupEqualTo(permissionGroupId);
        List<UserPermissionGroupKey> userPermissionKeys = userPermissionGroupMapper.selectByExample(userPermissionGroupExample);
        if (userPermissionKeys.size() > 0) {
            throw new BusinessCommonException("500", "已存在此权限");
        }
        UserPermissionGroupKey userPermissionGroupKey = new UserPermissionGroupKey();
        userPermissionGroupKey.setUser(userId);
        userPermissionGroupKey.setPermissionGroup(permissionGroupId);
        return userPermissionGroupMapper.insert(userPermissionGroupKey);
    }

    public int removeUserPermissionGroup(int userId, int permissionGroupId) {
        UserPermissionGroupExample userPermissionGroupExample = new UserPermissionGroupExample();
        userPermissionGroupExample.createCriteria()
                .andUserEqualTo(userId)
                .andPermissionGroupEqualTo(permissionGroupId);
        List<UserPermissionGroupKey> userPermissionKeys = userPermissionGroupMapper.selectByExample(userPermissionGroupExample);
        if (userPermissionKeys.isEmpty()) {
            throw new BusinessCommonException("500", "不存在此权限");
        }
        UserPermissionGroupKey userPermissionGroupKey = new UserPermissionGroupKey();
        userPermissionGroupKey.setUser(userId);
        userPermissionGroupKey.setPermissionGroup(permissionGroupId);
        return userPermissionGroupMapper.deleteByPrimaryKey(userPermissionGroupKey);
    }


    public List<Permission> selectPersissionsByUser(User user) {
        if (user != null) {
            UserPermissionGroupExample userPermissionGroupExample = new UserPermissionGroupExample();
            userPermissionGroupExample.createCriteria().andUserEqualTo(user.getId());
            List<UserPermissionGroupKey> userPermissionGroupKeys = userPermissionGroupMapper.selectByExample(userPermissionGroupExample);
            return userPermissionGroupKeys.parallelStream()
                    .flatMap(userPermissionGroupKey -> {
                        PermissionGroupPermissionExample permissionGroupPermissionExample = new PermissionGroupPermissionExample();
                        permissionGroupPermissionExample.createCriteria().andPermissionGroupEqualTo(userPermissionGroupKey.getPermissionGroup());
                        return permissionGroupPermissionMapper.selectByExample(permissionGroupPermissionExample).parallelStream();
                    })
                    .map(permissionGroupPermissionKey -> permissionMapper.selectByPrimaryKey(permissionGroupPermissionKey.getPermission()))
                    .collect(Collectors.toList());
        }
        return null;
    }

    public List<PermissionGroup> selectPermissionGroupsByUser(User user) {
        if (user != null) {
            UserPermissionGroupExample userPermissionGroupExample = new UserPermissionGroupExample();
            userPermissionGroupExample.createCriteria().andUserEqualTo(user.getId());
            List<UserPermissionGroupKey> userPermissionKeys = userPermissionGroupMapper.selectByExample(userPermissionGroupExample);
            return userPermissionKeys.parallelStream()
                    .map(userPermissionGroupKey -> permissionGroupMapper.selectByPrimaryKey(userPermissionGroupKey.getPermissionGroup())
                    ).collect(Collectors.toList());
        }
        return null;
    }

    public List<TreeNode> userPermissionList(Integer id) {
        User user = userMapper.selectByPrimaryKey(id);
        String orgType = null;
        if (user.getOrg() != null) {
            ResponseData<PostOrgResponse> orgDetail = remoteOrgService.getOrgDetail(user.getOrg(), user.getUsername());
            if (!orgDetail.getCode().equals(SUCCESS_CODE)) {
                throw new BusinessCommonException(orgDetail.getCode(), orgDetail.getMessage());
            }
            PostOrgResponse result = orgDetail.getResult();
            orgType = result.getType();
        }
        PermissionGroupExample permissionGroupExample = new PermissionGroupExample();
        PermissionGroupExample.Criteria criteria = permissionGroupExample.createCriteria();
        criteria.andParentIsNull();
        List<PermissionGroup> permissionGroups = permissionGroupMapper.selectByExample(permissionGroupExample);
        if (permissionGroups != null && !permissionGroups.isEmpty()) {
            PermissionGroup permissionGroup = permissionGroups.get(0);
            String finalOrgType = orgType;
            return subPermissionNodes(permissionGroup.getId()).stream().peek(node -> {
                if ((Integer) node.getKey() != 6) {
                    return;
                } else if (null == finalOrgType) {
                    return;
                }
                Collection<TreeNode<Integer, String>> children = node.getChildren();
                children.removeIf(child -> (child.getKey() == 63 && finalOrgType.equals("1")) ||
                        (child.getKey() == 17 && finalOrgType.equals("2")));
                node.setChildren(children);
            }).collect(Collectors.toList());
        } else {
            return Collections.emptyList();
        }
    }

    private List<TreeNode> subPermissionNodes(Integer parent) {
        PermissionGroupExample permissionGroupExample = new PermissionGroupExample();
        PermissionGroupExample.Criteria criteria = permissionGroupExample.createCriteria();
        criteria.andParentEqualTo(parent);
        List<PermissionGroup> permissionGroups = permissionGroupMapper.selectByExample(permissionGroupExample);
        String role = RequestHeaderUtil.getRole();
        Set<Integer> checked = checked(RequestHeaderUtil.getUserId());
        return permissionGroups.stream()
                .map(permissionGroup -> {
                    TreeNode treeNode = new TreeNode(permissionGroup.getId(), permissionGroup.getName());
                    treeNode.addChildren(subPermissionNodes(permissionGroup.getId()));
                    return treeNode;
                })
                .filter(treeNode -> ROLE_SA.equals(role) ||
                        !treeNode.isLeaf() ||
                        checked.contains(treeNode.getKey()) ||
                        (ROLE_ADMIN.equals(role) && Arrays.asList(46, 47, 48, 79).contains(treeNode.getKey()))
                )
                .collect(Collectors.toList());
    }

    public Set<Integer> checked(Integer id) {
        UserPermissionGroupExample example = new UserPermissionGroupExample();
        UserPermissionGroupExample.Criteria criteria = example.createCriteria();
        criteria.andUserEqualTo(id);
        List<UserPermissionGroupKey> userPermissionGroupKeys = userPermissionGroupMapper.selectByExample(example);
        return userPermissionGroupKeys.parallelStream()
                .map(UserPermissionGroupKey::getPermissionGroup)
                .collect(Collectors.toSet());
    }

    public void check(Integer id, List<Integer> checked) {
        UserPermissionGroupExample example = new UserPermissionGroupExample();
        UserPermissionGroupExample.Criteria criteria = example.createCriteria();
        criteria.andUserEqualTo(id);
        userPermissionGroupMapper.deleteByExample(example);
        checked.parallelStream().forEach(i -> {
            UserPermissionGroupKey userPermissionGroupKey = new UserPermissionGroupKey();
            userPermissionGroupKey.setUser(id);
            userPermissionGroupKey.setPermissionGroup(i);
            userPermissionGroupMapper.insert(userPermissionGroupKey);
        });
    }
}
