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

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

import cn.hutool.core.util.StrUtil;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.service.ICacheService;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.framework.util.DataUtil;
import com.mortals.xhx.base.system.menu.model.MenuEntity;
import com.mortals.xhx.base.system.menu.model.MenuQuery;
import com.mortals.xhx.base.system.menu.model.MenuTreeSelect;
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.model.ResourceQuery;
import com.mortals.xhx.base.system.resource.service.ResourceService;
import com.mortals.xhx.base.system.role.dao.RoleAuthDao;
import com.mortals.xhx.base.system.role.model.RoleAuthEntity;
import com.mortals.xhx.base.system.role.model.RoleAuthQuery;
import com.mortals.xhx.base.system.role.model.RoleUserQuery;
import com.mortals.xhx.base.system.role.service.RoleAuthService;
import com.mortals.xhx.base.system.role.service.RoleUserService;
import com.mortals.xhx.common.key.RedisKey;
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;

import static com.mortals.xhx.common.utils.MenuEncodeUtil.generateMenuUrlCode;

/**
 * <p>Title: 角色资源权限</p>
 * <p>Description: RoleAuthServiceImpl service接口 </p>
 * <p>Copyright: Copyright &reg;  </p>
 * <p>Company: </p>
 *
 * @author
 * @version 1.0.0
 */
@Service("roleAuthService")
public class RoleAuthServiceImpl extends AbstractCRUDServiceImpl<RoleAuthDao, RoleAuthEntity, Long> implements RoleAuthService {

    @Autowired
    private ICacheService cacheService;
    @Autowired
    private MenuService menuService;
    @Autowired
    private RoleUserService roleUserService;

    @Autowired
    @Lazy
    private ResourceService resourceService;

    @Override
    public void doDistributionSource(RoleAuthQuery query, Context context) {
        if (ObjectUtils.isEmpty(query.getRoleId())) throw new AppException("角色不能为空!");
        // 删除角色资源老数据
        Long roleId = query.getRoleId();
        RoleAuthQuery roleAuthQuery = new RoleAuthQuery();
        roleAuthQuery.setRoleId(roleId);
        Long[] delIds = this.find(roleAuthQuery).stream()
                .filter(f -> f.getMenuId() == null)
                .map(f -> f.getId()).toArray(Long[]::new);
        if (!ObjectUtils.isEmpty(delIds)) {
            this.remove(delIds, context);
        }

        List<RoleAuthEntity> list = new ArrayList<>();
        for (Long sourceId : query.getResourceIdList()) {
            RoleAuthEntity entity = new RoleAuthEntity();
            entity.setRoleId(roleId);
            entity.setResourceId(sourceId);
            entity.setCreateUserId(this.getContextUserId(context));
            entity.setCreateTime(new Date());
            list.add(entity);
        }
        this.dao.insertBatch(list);


        //查询所有有这个用户角色的用户

        // this.find(new RoleAuthQuery().roleId(roleId)).stream().filter(f->f.get)
        List<Long> userIdList = roleUserService.find(new RoleUserQuery().roleId(query.getRoleId())).stream()
                .map(m -> m.getUserId())
                .filter(f -> f != null)
                .distinct().collect(Collectors.toList());

        this.updateUserMenuUrlCache(userIdList);
    }

    @Override
    public void doDistributionMenu(RoleAuthQuery query, Context context) {
        if (ObjectUtils.isEmpty(query.getRoleId())) throw new AppException("角色不能为空!");
        // 删除角色资源老数据
        Long roleId = query.getRoleId();
        RoleAuthQuery roleAuthQuery = new RoleAuthQuery();
        roleAuthQuery.setRoleId(roleId);
        Long[] delIds = this.find(roleAuthQuery).stream()
                .filter(f -> f.getMenuId() != null)
                .map(f -> f.getId()).toArray(Long[]::new);
        if (!ObjectUtils.isEmpty(delIds)) {
            this.remove(delIds, context);
        }

        List<RoleAuthEntity> list = new ArrayList<>();
        for (Long menuId : query.getMenuIdList()) {
            //todo 一个菜单可以对应多个资源
            MenuEntity menuEntity = menuService.get(menuId, context);
            if(!ObjectUtils.isEmpty(menuEntity)){
                String resourceUrl = menuEntity.getResourceUrl();
                if(!ObjectUtils.isEmpty(resourceUrl)){
                    List<String> split = StrUtil.split(resourceUrl, ",");
                    for (String s : split) {
                        RoleAuthEntity entity = new RoleAuthEntity();
                        entity.setRoleId(roleId);
                        entity.setMenuId(menuId);
                        entity.setCreateTime(new Date());
                        entity.setCreateUserId(1L);
                        //判断资源路径类型 如果是/xxx开头 查询资源是否存在，不存在则创建
                        if (StrUtil.startWith(s, "/")) {
                            //根据路径查询资源是否存在
                            ResourceEntity resourceEntity = resourceService.selectOne(new ResourceQuery().url(s));
                            if(ObjectUtils.isEmpty(resourceEntity)){
                                ResourceEntity resource = new ResourceEntity();
                                resource.initAttrValue();
                                resource.setName(menuEntity.getName());
                                resource.setGroupName("菜单自定义");
                                resource.setUrl(s);
                                resource.setCreateTime(new Date());
                                resource.setCreateUserId(1L);
                                resourceService.save(resource, context);
                                entity.setResourceId(resource.getId());
                            }else{
                                entity.setResourceId(resourceEntity.getId());
                            }
                        }else{
                            //查询下id是否存在 如果存在 添加
                            ResourceEntity resource = resourceService.get(DataUtil.converStr2Long(s, 0L), context);
                            if(ObjectUtils.isEmpty(resource)) continue;
                            entity.setResourceId(resource.getId());
                        }
                        list.add(entity);
                    }
                }else{
                    RoleAuthEntity entity = new RoleAuthEntity();
                    entity.setRoleId(roleId);
                    entity.setMenuId(menuId);
                    entity.setCreateTime(new Date());
                    entity.setCreateUserId(1L);
                    list.add(entity);
                }
            }
        }
        this.dao.insertBatch(list);
        List<Long> userIdList = roleUserService.find(new RoleUserQuery().roleId(query.getRoleId())).stream()
                .map(m -> m.getUserId())
                .filter(f -> f != null)
                .distinct().collect(Collectors.toList());
        this.updateUserMenuUrlCache(userIdList);
    }

    @Override
    public List<MenuTreeSelect> editMenu(RoleAuthQuery query, Context context) {
        if (ObjectUtils.isEmpty(query.getRoleId())) throw new AppException("角色不能为空!");

        RoleAuthQuery roleAuthQuery = new RoleAuthQuery();
        roleAuthQuery.setRoleId(query.getRoleId());
        Set<Long> menuIdList = this.find(roleAuthQuery).stream()
                .map(f -> f.getMenuId())
                .filter(f -> f != null)
                .collect(Collectors.toSet());
        if (!ObjectUtils.isEmpty(menuIdList)) {
            List<MenuEntity> allMenuList = menuService.find(new MenuQuery());
            List<MenuTreeSelect> menuTreeSelects = menuService.buildMenuTreeChecked(allMenuList, menuIdList);
            return menuTreeSelects;
        }
        return Collections.emptyList();

    }

    private void updateUserMenuUrlCache(List<Long> userIdList) {
        for (Long userId : userIdList) {
            Set<String> urls = resourceService.findUrlSetByUserId(userId);
            String menuUrlCode = generateMenuUrlCode(urls);
            cacheService.hset(RedisKey.KEY_USER_MENU_CACHE, userId.toString(), menuUrlCode);
        }
    }


    public static void main(String[] args) {
        String s = "1";
        System.out.println(StrUtil.split(s, ","));
    }

}