package com.cpop.oam.business.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.cpop.core.base.entity.PageDomain;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.utils.StringUtils;
import com.cpop.core.utils.bean.BeanUtils;
import com.cpop.oam.framework.enums.InitRoleEnum;
import com.cpop.core.utils.SpringUtils;
import com.cpop.core.utils.SqlUtils;
import com.cpop.oam.business.bo.RoleBo;
import com.cpop.oam.business.bo.RolePageBo;
import com.cpop.oam.business.bo.RoleStatusBo;
import com.cpop.oam.business.entity.RoleMenu;
import com.cpop.oam.business.service.RoleMenuService;
import com.cpop.oam.business.vo.RolePageVo;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.cpop.oam.business.entity.Role;
import com.cpop.oam.business.mapper.RoleMapper;
import com.cpop.oam.business.service.RoleService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.cpop.oam.business.entity.table.RoleMenuTableDef.ROLE_MENU;
import static com.cpop.oam.business.entity.table.RoleTableDef.ROLE;

/**
 * 系统角色表 服务层实现。
 *
 * @author DB
 * @since 2023-10-19
 */
@Service("roleService")
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {

    /**
     * 查询角色分页列表
     * @author DB
     * @since 2023/09/10 16:51
     * @param bo 请求参数
     * @return R<PageVo<SysRolePageVo>>
     */
    @Override
    public Page<RolePageVo> getSysRolePage(RolePageBo bo) {
        PageDomain pageDomain = SqlUtils.getInstance().getPageDomain();
        Page<RolePageVo> page = this.mapper.paginateAs(pageDomain.getPageNum(), pageDomain.getPageSize(),
                QueryWrapper.create()
                        .select(ROLE.ALL_COLUMNS)
                        .where(ROLE.ID.ne(InitRoleEnum.SUPER_OAM_ROLE.getId()))
                        .and(ROLE.ROLE_NAME.likeLeft(bo.getRoleName()))
                        .and(ROLE.STATUS.eq(bo.getStatus()))
                        .and(ROLE.USER_TYPE.eq(StpUtil.getSession().get("userType")))
                        .orderBy(ROLE.ORDER_NO.asc())
                , RolePageVo.class);
        if (!page.getRecords().isEmpty()) {
            //根据角色查询中间表
            List<RoleMenu> roleMenuList = SpringUtils.getBean(RoleMenuService.class).list(QueryWrapper.create()
                    .where(ROLE_MENU.ROLE_ID.in(page.getRecords().stream().map(RolePageVo::getId).collect(Collectors.toSet()))));
            page.getRecords().forEach(item -> {
                List<String> filterMenuIds = roleMenuList.stream()
                        .filter(s -> StringUtils.equals(s.getRoleId(), item.getId()))
                        .map(RoleMenu::getMenuId).collect(Collectors.toList());
                item.setMenuIds(filterMenuIds);
            });
        }
        return page;
    }

    /**
     * 新增角色
     * @author DB
     * @since  2023/10/12 10:48
     * @param bo 请求参数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertSysRole(RoleBo bo) {
        Role role = BeanUtils.mapToClass(bo, Role.class);
        role.setUserType((UserType) StpUtil.getSession().get("userType"));
        this.save(role);
        //将菜单信息录入中间表
        if (!bo.getMenuIds().isEmpty()) {
            List<RoleMenu> roleMenus = new ArrayList<>();
            bo.getMenuIds().forEach(item -> {
                RoleMenu roleMenu = new RoleMenu();
                roleMenu.setMenuId(item);
                roleMenu.setRoleId(role.getId());
                roleMenus.add(roleMenu);
            });
            SpringUtils.getBean(RoleMenuService.class).saveBatch(roleMenus);
        }
    }

    /**
     * 修改角色
     * @author DB
     * @since 2023/09/10 17:45
     * @param bo 请求参数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSysRole(RoleBo bo) {
        Role entity = new Role();
        BeanUtils.copyBeanProp(entity, bo);
        this.updateById(entity);
        //将菜单信息录入中间表
        if (!bo.getMenuIds().isEmpty()) {
            //先删后存
            RoleMenuService sysRoleMenuService = SpringUtils.getBean(RoleMenuService.class);
            sysRoleMenuService.remove(QueryWrapper.create()
                    .where(ROLE_MENU.ROLE_ID.eq(entity.getId())));
            List<RoleMenu> roleMenus = new ArrayList<>();
            bo.getMenuIds().forEach(item -> {
                RoleMenu roleMenu = new RoleMenu();
                roleMenu.setMenuId(item);
                roleMenu.setRoleId(entity.getId());
                roleMenus.add(roleMenu);
            });
            sysRoleMenuService.saveBatch(roleMenus);
        }
    }

    /**
     * 删除角色
     * @author DB
     * @since 2024/4/17
     * @param id 主键
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeSysRole(String id) {
        this.removeById(id);
        //删除相关联菜单
        SpringUtils.getBean(RoleMenuService.class).remove(QueryWrapper.create().where(ROLE_MENU.ROLE_ID.eq(id)));
    }

    /**
     * 设置角色状态
     * @param bo 请求参数
     * @author DB
     * @since 2023/5/9 14:13
     **/
    @Override
    public void setSysRoleStatus(RoleStatusBo bo) {
        this.updateById(BeanUtils.mapToClass(bo, Role.class));
    }

}
