/**
 * 文件：UserServiceImpl.java
 * 版本：1.0.0
 * 日期：
 * Copyright &reg;
 * All right reserved.
 */

package com.mortals.xhx.base.system.user.service.impl;

import com.mortals.framework.ap.SysConstains;
import com.mortals.framework.common.Rest;
import com.mortals.framework.common.code.UserType;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.model.PageInfo;
import com.mortals.framework.model.Result;
import com.mortals.framework.service.IUser;
import com.mortals.framework.service.impl.AbstractCRUDCacheServiceImpl;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.framework.util.SecurityUtil;
import com.mortals.framework.util.StringUtils;
import com.mortals.xhx.base.system.menu.model.MenuEntity;
import com.mortals.xhx.base.system.menu.service.MenuService;
import com.mortals.xhx.base.system.resource.model.ResourceEntity;
import com.mortals.xhx.base.system.resource.service.ResourceService;
import com.mortals.xhx.base.system.role.dao.RoleUserDao;
import com.mortals.xhx.base.system.role.model.RoleUserEntity;
import com.mortals.xhx.base.system.role.model.RoleUserQuery;
import com.mortals.xhx.base.system.role.service.RoleUserService;
import com.mortals.xhx.base.system.user.dao.UserDao;
import com.mortals.xhx.base.system.user.model.UserEntity;
import com.mortals.xhx.base.system.user.model.UserQuery;
import com.mortals.xhx.base.system.user.service.UserService;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.common.pdu.RespData;
import com.mortals.xhx.common.pdu.user.UserPdu;
import com.mortals.xhx.feign.user.IUserFeign;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

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

/**
 * <p>Title: 用户信息</p>
 * <p>Description: UserServiceImpl service接口 </p>
 * <p>Copyright: Copyright &reg;  </p>
 * <p>Company: </p>
 *
 * @author
 * @version 1.0.0
 */
@Service("userService")
@Slf4j
public class UserServiceImpl extends AbstractCRUDCacheServiceImpl<UserDao, UserEntity, Long> implements UserService {


    @Autowired
    private MenuService menuService;
    @Autowired
    private ResourceService resourceService;

    @Autowired
    private RoleUserService roleUserService;

    @Lazy
    @Autowired
    private IUserFeign userFeign;

    @Override
    protected String getExtKey(UserEntity data) {
        return data.getLoginName();
    }


    @Override
    public UserEntity doCheckUser(String loginName, String password) throws AppException {

        UserQuery params = new UserQuery();
        params.setLoginName(loginName);
        UserEntity sysUser = this.selectOne(params);
        if (sysUser == null || !sysUser.getLoginName().equals(loginName)) {
            return null;
        }
        try {
            if (!sysUser.getLoginPwd().equals(SecurityUtil.md5DoubleEncoding(password))) {
                return null;
            }
        } catch (Exception e) {
            log.error("查询用户异常，loginName:" + loginName, e);
            return null;
        }
        return sysUser;
    }


    @Override
    protected void saveAfter(UserEntity entity, Context context) throws AppException {
        updateUserRole(entity);
    }

    @Override
    protected void updateAfter(UserEntity entity, Context context) throws AppException {
        updateUserRole(entity);
    }

    private void updateUserRole(UserEntity entity) {
        if (!ObjectUtils.isEmpty(entity.getId()) && entity.getId().longValue() != SysConstains.ADMIN_ID && !ObjectUtils.isEmpty(entity.getRoleIds())) {
            RoleUserQuery roleUserQuery = new RoleUserQuery();
            roleUserQuery.setUserId(entity.getId());
            List<Long> idList = Arrays.asList(entity.getRoleIds().split(",")).stream().map(Long::parseLong).collect(Collectors.toList());
            roleUserQuery.setRoleIdList(idList);
            roleUserService.doDistributionRole(roleUserQuery);
        }
    }

    @Override
    protected void findAfter(UserEntity params, PageInfo pageInfo, Context context, List<UserEntity> list) throws AppException {
        list.stream().peek(item -> {
            RoleUserQuery roleUserQuery = new RoleUserQuery();
            roleUserQuery.setUserId(item.getId());
            String roleIds = roleUserService.find(roleUserQuery).stream().map(RoleUserEntity::getRoleId).map(String::valueOf).collect(Collectors.joining(","));
            item.setRoleIds(roleIds);
        }).count();
    }


    @Override
    public Set<Long> findAllAuthIds(UserEntity userEntity) throws AppException {
        Set<Long> authIds = new HashSet<Long>();
        if (userEntity.isAdmin()) {
            return authIds;
        }
        authIds.addAll(dao.getAuthListById(userEntity.getId()));
        return authIds;
    }

    @Override
    public List<MenuEntity> findOutlookBarList(IUser user) {
        Set<String> urls = new HashSet<String>();
        if (!user.isAdmin()) {
            List<ResourceEntity> resList = resourceService.findListByUserId(user.getId());
            for (ResourceEntity res : resList) {
                String url = res.getUrl();
                if (StringUtils.isEmpty(url)) {
                    continue;
                }
                url = url.replaceAll("，", ",");
                urls.addAll(StringUtils.converStr2Set(url));
            }
        }
        Set<Long> authIds = new HashSet<Long>();
        Map<Long, MenuEntity> menuMap = new HashMap<Long, MenuEntity>();
        List<MenuEntity> userModuleList = this.menuService.findAllEnable();
        for (MenuEntity sysModule : userModuleList) {
            if (sysModule == null) {
                continue;
            }
            menuMap.put(sysModule.getId(), sysModule);
            if (!user.isAdmin() && urls.contains(StringUtils.trim(sysModule.getUrl()))) {
                authIds.add(sysModule.getId());
            }
        }
        if (!user.isAdmin()) {
            Long[] ids = authIds.toArray(new Long[authIds.size()]);
            for (Long id : ids) {
                MenuEntity menu = menuMap.get(id);
                while (menu != null) {
                    authIds.add(menu.getId());
                    menu = menuMap.get(menu.getParentId());
                }
            }
        }
        List<MenuEntity> outlookBar = new ArrayList<MenuEntity>();
        List<MenuEntity> norightList = new ArrayList<MenuEntity>();
        for (MenuEntity sysModule : userModuleList) {
            if (!user.isAdmin() && !authIds.contains(sysModule.getId())) {
                norightList.add(sysModule);
                continue;
            }
            if (sysModule.getParentId() == null || sysModule.getParentId().longValue() == 0) {
                outlookBar.add(sysModule);
                continue;
            }
            MenuEntity sysModuleParent = menuMap.get(sysModule.getParentId());
            if (sysModuleParent != null) {
                sysModuleParent.getChildList().add(sysModule);
            }
        }
        return outlookBar;
    }

    @Override
    public Rest<Void> refreshUser() {
        UserPdu userPdu = new UserPdu();
        userPdu.setPage(1);
        userPdu.setSize(-1);
        Rest<RespData<List<UserPdu>>> resp = userFeign.list(userPdu);
        if (resp.getCode() == YesNoEnum.YES.getValue()) {
            List<UserPdu> userPduList = resp.getData().getData();
            log.info("用户总数量：{}", userPduList.size());
            if (!ObjectUtils.isEmpty(userPduList)) {
                List<UserEntity> newUserList = userPduList.stream().map(newUser -> {
                    UserEntity userEntity = new UserEntity();
                    userEntity.initAttrValue();
                    BeanUtils.copyProperties(newUser, userEntity, new String[]{"id", "lastLoginTime", "lastLoginAddress"});
                    return userEntity;
                }).collect(Collectors.toList());

                List<UserEntity> saveUpdateUserList = newUserList.parallelStream().map(item -> {
                    UserEntity extCache = this.getExtCache(item.getLoginName());
                    if (ObjectUtils.isEmpty(extCache)) {
                        item.setCreateUserId(1L);
                        item.setCreateUserName("系统管理员");
                        item.setCreateTime(new Date());
                        return item;
                    } else {
                        //更新用户列表
                        item.setId(extCache.getId());
                        item.setUpdateUserId(1L);
                        item.setUpdateUserName("系统管理员");
                        item.setUpdateTime(new Date());
                        return item;
                    }
                }).collect(Collectors.toList());
                Map<Boolean, List<UserEntity>> saveUpdateCollect = saveUpdateUserList.stream().collect(Collectors.partitioningBy(x -> x.getId() == null));
                if (!ObjectUtils.isEmpty(saveUpdateCollect.get(true))) {
                    //需要新增的用户
                    log.info("需要新增用户数量：{}", saveUpdateCollect.get(true).size());
                    saveUpdateCollect.get(true).stream().forEach(item -> {
                        this.getUserDao().insert(item);
                        this.putCache(item.getId() == null ? "" : item.getId().toString(), item);
                        RoleUserQuery roleUserQuery = new RoleUserQuery();
                        roleUserQuery.setUserId(item.getId());
                        roleUserQuery.setRoleIdList(Arrays.asList(1L));
                        roleUserService.doDistributionRole(roleUserQuery);
                    });
                }

                if (!ObjectUtils.isEmpty(saveUpdateCollect.get(false))) {
                    //需要新增的用户
                    log.info("需要更新用户数量：{}", saveUpdateCollect.get(false).size());
                    saveUpdateCollect.get(false).stream().forEach(item -> {
                        this.getUserDao().update(item);
                        this.putCache(item.getId() == null ? "" : item.getId().toString(), item);
                    });
                }
                //差集删除
                Set<String> collectSet = newUserList.parallelStream().map(x -> x.getLoginName()).collect(Collectors.toSet());
                Long[] removeUserIds = this.getCacheList().parallelStream().filter(f -> !collectSet.contains(f.getLoginName())).map(i -> i.getId()).distinct().toArray(Long[]::new);
                if (!ObjectUtils.isEmpty(removeUserIds)) {
                    log.info("需要删除的本地用户数量:{}", removeUserIds.length);
                    this.remove(removeUserIds, null);
                }
            }
            //查找新增 与更新
        }
        return Rest.ok();
    }

    @Override
    protected void removeAfter(Long[] ids, Context context, int result) throws AppException {
        super.removeAfter(ids, context, result);
        RoleUserQuery roleUserQuery = new RoleUserQuery();
        roleUserQuery.setUserIdList(Arrays.asList(ids));
        Long[] userIds = roleUserService.find(roleUserQuery).stream().map(RoleUserEntity::getId).toArray(Long[]::new);
        roleUserService.remove(userIds, context);
    }


    @Override
    public UserDao getUserDao() {
        return this.getDao();
    }
}