package ink.wgink.service.role.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.interfaces.consts.ISystemConstant;
import ink.wgink.interfaces.role.IRoleUserDeleteAfterHandler;
import ink.wgink.interfaces.role.IRoleUserSaveAfterHandler;
import ink.wgink.interfaces.user.IUserBaseService;
import ink.wgink.interfaces.user.mongo.IMongoLoginUserService;
import ink.wgink.pojo.ListPage;
import ink.wgink.pojo.dtos.department.DepartmentUserDTO;
import ink.wgink.pojo.dtos.role.RoleSimpleDTO;
import ink.wgink.pojo.dtos.role.RoleUserDTO;
import ink.wgink.pojo.dtos.user.UserDTO;
import ink.wgink.pojo.pos.RolePO;
import ink.wgink.pojo.result.SuccessResultList;
import ink.wgink.service.department.service.IDepartmentUserService;
import ink.wgink.service.role.dao.IRoleUserDao;
import ink.wgink.service.role.service.IRoleService;
import ink.wgink.service.role.service.IRoleUserService;
import ink.wgink.service.user.pojo.pos.UserPO;
import ink.wgink.util.thread.CachedThreadPoolUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: RoleUserServiceImpl
 * @Description: 角色用户
 * @Author: WangGeng
 * @Date: 2021/2/18 11:24
 * @Version: 1.0
 **/
@Service
public class RoleUserServiceImpl extends DefaultBaseService implements IRoleUserService {

    @Autowired
    private IRoleUserDao roleUserDao;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private IUserBaseService userBaseService;
    @Autowired
    private IDepartmentUserService departmentUserService;
    @Autowired(required = false)
    private IRoleUserSaveAfterHandler roleUserSaveAfterHandler;
    @Autowired(required = false)
    private IRoleUserDeleteAfterHandler roleUserDeleteAfterHandler;
    @Autowired(required = false)
    private IMongoLoginUserService mongoLoginUserService;

    @Override
    public void save(String roleId, List<String> saveUserIds) {
        // 判断是否已经添加
        List<String> existUserIds = listUserIdByRoleIdAndUserIds(roleId, saveUserIds);
        Map<String, Object> params = getHashMap(4);
        for (int i = 0; i < saveUserIds.size(); i++) {
            String saveUserId = saveUserIds.get(i);
            boolean isExist = false;
            for (String existUserId : existUserIds) {
                if (StringUtils.equals(saveUserId, existUserId)) {
                    isExist = true;
                    existUserIds.remove(existUserId);
                    break;
                }
            }
            if (!isExist) {
                params.put("roleId", roleId);
                params.put("userId", saveUserId);
                roleUserDao.save(params);
            } else {
                saveUserIds.remove(i);
                i--;
            }
        }
        updateMongoLoginUser(saveUserIds);
        if (roleUserSaveAfterHandler != null) {
            roleUserSaveAfterHandler.handle(roleId, saveUserIds);
        }
    }

    @Override
    public void save(String roleId, String saveUserId) {
        save(roleId, Arrays.asList(saveUserId));
    }

    @Override
    public void update(String roleId, List<String> saveUserIds, List<String> deleteUserIds) {
        if (deleteUserIds != null && !deleteUserIds.isEmpty()) {
            delete(roleId, deleteUserIds);
        }
        if (saveUserIds != null && !saveUserIds.isEmpty()) {
            Map<String, Object> params = getHashMap(4);
            params.put("roleId", roleId);
            for (String userId : saveUserIds) {
                params.put("userId", userId);
                roleUserDao.save(params);
            }
            updateMongoLoginUser(saveUserIds);
        }
        if (roleUserSaveAfterHandler != null) {
            roleUserSaveAfterHandler.handle(roleId, saveUserIds);
        }
    }

    @Override
    public void delete(String roleId) {
        List<String> userIds = listUserId(roleId);
        delete(roleId, userIds);
    }

    @Override
    public void delete(List<String> roleIds) {
        roleIds.forEach(roleId -> {
            delete(roleId);
        });
    }

    @Override
    public void delete(String roleId, List<String> userIds) {
        Map<String, Object> params = getHashMap(4);
        params.put("roleId", roleId);
        params.put("userIds", userIds);
        roleUserDao.delete(params);
        updateMongoLoginUser(userIds);
        if (roleUserDeleteAfterHandler != null) {
            roleUserSaveAfterHandler.handle(roleId, userIds);
        }
    }

    @Override
    public List<DepartmentUserDTO> listDepartmentUser(Map<String, Object> params) {
        params = params == null ? getHashMap(2) : params;
        return roleUserDao.listDepartmentUser(params);
    }

    @Override
    public List<UserDTO> listUser(Map<String, Object> requestParams) {
        requestParams = requestParams == null ? getHashMap(0) : requestParams;
        return roleUserDao.listUser(requestParams);
    }

    @Override
    public SuccessResultList<List<UserDTO>> listPageUser(ListPage page) {
        PageHelper.startPage(page.getPage(), page.getRows());
        List<UserDTO> userDTOs = listUser(page.getParams());
        PageInfo<UserDTO> pageInfo = new PageInfo<>(userDTOs);
        return new SuccessResultList<>(userDTOs, pageInfo.getPageNum(), pageInfo.getTotal());
    }

    @Override
    public List<String> listUserId(String roleId) {
        Map<String, Object> params = getHashMap(2);
        params.put("roleId", roleId);
        return roleUserDao.listUserId(params);
    }

    @Override
    public List<String> listUserId(List<String> roleIds) {
        Map<String, Object> params = getHashMap(2);
        params.put("roleIds", roleIds);
        return roleUserDao.listUserId(params);
    }

    @Override
    public SuccessResultList<List<RoleUserDTO>> listPage(String roleId, ListPage page) {
        SuccessResultList<List<UserDTO>> successResultList;
        if (StringUtils.equals(roleId, ISystemConstant.TREE_BASE_ROOT_ID_VALUE)) {
            successResultList = listPageUserDTOByExcludeRole(page);
        } else {
            successResultList = listPageUser(roleId, page);
        }
        List<UserDTO> userDTOs = successResultList.getRows();
        List<RoleUserDTO> roleUserDTOs = new ArrayList<>();
        for (UserDTO userDTO : userDTOs) {
            RoleUserDTO roleUserDTO = new RoleUserDTO(userDTO);
            roleUserDTOs.add(roleUserDTO);
        }
        return new SuccessResultList<>(roleUserDTOs, successResultList.getPage(), successResultList.getTotal());
    }

    @Override
    public List<RolePO> listRolePOByUserId(String userId) {
        Map<String, Object> params = getHashMap(2);
        params.put("userId", userId);
        List<String> roleIds = roleUserDao.listRoleId(params);
        if (roleIds.isEmpty()) {
            return new ArrayList<>();
        }
        return roleService.listPO(roleIds);
    }

    @Override
    public List<RolePO> listRolePOByRoleIds(List<String> roleIds) {
        if (roleIds.isEmpty()) {
            return new ArrayList<>();
        }
        return roleService.listPO(roleIds);
    }

    @Override
    public List<RoleSimpleDTO> listSimple(List<RolePO> rolePOs) {
        if (rolePOs == null || rolePOs.isEmpty()) {
            return new ArrayList<>();
        }
        List<RoleSimpleDTO> roleSimpleDTOs = new ArrayList<>();
        rolePOs.forEach(rolePO -> {
            RoleSimpleDTO roleSimpleDTO = new RoleSimpleDTO();
            roleSimpleDTO.setRoleId(rolePO.getRoleId());
            roleSimpleDTO.setRoleParentId(rolePO.getRoleParentId());
            roleSimpleDTO.setRoleName(rolePO.getRoleName());
            roleSimpleDTO.setRoleCode(rolePO.getRoleCode());
            roleSimpleDTO.setRoleDataRight(rolePO.getRoleDataRight());
            roleSimpleDTOs.add(roleSimpleDTO);
        });
        return roleSimpleDTOs;
    }

    @Override
    public List<String> listUserIdByRoleIdAndUserIds(String roleId, List<String> userIds) {
        if (StringUtils.isBlank(roleId)) {
            return new ArrayList<>();
        }
        if (userIds == null || userIds.isEmpty()) {
            return new ArrayList<>();
        }
        Map<String, Object> params = getHashMap(4);
        params.put("roleId", roleId);
        params.put("userIds", userIds);
        return roleUserDao.listUserId(params);
    }

    @Override
    public List<String> listUserIdByRoleIdsAndUserIds(List<String> roleIds, List<String> userIds) {
        if (roleIds == null || roleIds.isEmpty()) {
            return new ArrayList<>();
        }
        if (userIds == null || userIds.isEmpty()) {
            return new ArrayList<>();
        }
        Map<String, Object> params = getHashMap(4);
        params.put("roleIds", roleIds);
        params.put("userIds", userIds);
        return roleUserDao.listUserId(params);
    }

    @Override
    public List<String> listRoleIdByUserId(String userId) {
        Map<String, Object> params = getHashMap(2);
        params.put("userId", userId);
        return roleUserDao.listRoleId(params);
    }

    @Override
    public List<UserDTO> listUserByRoleId(String roleId) {
        Map<String, Object> params = getHashMap(2);
        params.put("roleId", roleId);
        return roleUserDao.listUser(params);
    }

    @Override
    public SuccessResultList<List<UserDTO>> listPageUserByRoleId(String roleId, ListPage page) {
        PageHelper.startPage(page.getPage(), page.getRows());
        List<UserDTO> userDTOs = listUserByRoleId(roleId);
        PageInfo<UserDTO> pageInfo = new PageInfo<>(userDTOs);
        return new SuccessResultList<>(userDTOs, pageInfo.getPageNum(), pageInfo.getTotal());
    }

    @Override
    public List<UserDTO> listUserNoDepartmentAndNoRole(Map<String, Object> params) {
        params = params == null ? getHashMap(2) : params;
        params.put("noDepartment", true);
        params.put("noRole", true);
        return roleUserDao.listUser(params);
    }

    @Override
    public SuccessResultList<List<UserDTO>> listPageUserNoDepartmentAndNoRole(ListPage page) {
        PageHelper.startPage(page.getPage(), page.getRows());
        List<UserDTO> userDTOs = listUserNoDepartmentAndNoRole(page.getParams());
        PageInfo<UserDTO> pageInfo = new PageInfo<>(userDTOs);
        return new SuccessResultList<>(userDTOs, pageInfo.getPageNum(), pageInfo.getTotal());
    }

    @Override
    public List<UserPO> listUserPO(Map<String, Object> params) {
        params = params == null ? getHashMap(0) : params;
        return roleUserDao.listUserPO(params);
    }

    @Override
    public List<UserPO> listUserPOByRoleId(String roleId) {
        Map<String, Object> params = getHashMap(2);
        params.put("roleId", roleId);
        return listUserPO(params);
    }

    @Override
    public List<UserPO> listUserPOByRoleIds(List<String> roleIds) {
        Map<String, Object> params = getHashMap(2);
        params.put("roleIds", roleIds);
        return listUserPO(params);
    }

    /**
     * 更新mongo
     *
     * @param userIds
     */
    private void updateMongoLoginUser(List<String> userIds) {
        if (mongoLoginUserService != null) {
            CachedThreadPoolUtil.execute(() -> {
                mongoLoginUserService.updateByUserIds(userIds);
            });
        }
    }

    private List<String> listGroupUserId(Map<String, Object> params) {
        return roleUserDao.listGroupUserId(params);
    }

    /**
     * 没有用户组的用户分页列表
     *
     * @param page
     * @return
     */
    private SuccessResultList<List<UserDTO>> listPageUserDTOByExcludeRole(ListPage page) {
        List<String> hasRoleUserIds = listGroupUserId(new HashMap<>(0));
        return userBaseService.listPageByExcludeIds(hasRoleUserIds, page);
    }

    /**
     * 用户组的用户分页列表
     *
     * @param roleId 用户组ID
     * @param page
     * @return
     */
    private SuccessResultList<List<UserDTO>> listPageUser(String roleId, ListPage page) {
        List<String> userIds = listUserId(roleId);
        if (userIds.isEmpty()) {
            return new SuccessResultList<>(new ArrayList<>(), 1, 0L);
        }
        return userBaseService.listPageByIds(userIds, page);
    }

}
