package com.app.service.platform;

import com.app.dto.PageResult;
import com.app.dto.platform.*;
import com.app.entity.BaseEntity;
import com.app.entity.platform.system.Role;
import com.app.entity.platform.system.RoleDept;
import com.app.entity.platform.system.RoleResource;
import com.app.mapper.platform.ResourceMapper;
import com.app.mapper.platform.RoleDeptMapper;
import com.app.mapper.platform.RoleMapper;
import com.app.mapper.platform.RoleResourceMapper;
import com.app.util.NodeUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class RoleService {

    @Resource
    private RoleMapper roleMapper;

    @Resource
    private RoleDeptMapper roleDeptMapper;

    @Resource
    private RoleResourceMapper roleResourceMapper;

    @Resource
    private ResourceMapper resourceMapper;


    /**
     * 保存或更新【角色】
     *
     */
    @Transactional
    public Role saveOrUpdate(RoleDto dto) {
        Role _role = null;
        if (StringUtils.isEmpty(dto.getId())) {
            _role = new Role();
            _role.setName(dto.getName());
            _role.setRemarks(dto.getRemarks());
            roleMapper.insert(_role);
            for (String deptId : dto.getDeptIds()) {
                RoleDept roleDept = new RoleDept();
                roleDept.setRoleId(_role.getId());
                roleDept.setDeptId(deptId);
                roleDeptMapper.insert(roleDept);
            }

        } else {
            Optional<Role> newsOptional = Optional.ofNullable(roleMapper.selectById(dto.getId()));
            if (newsOptional.isPresent()) {
                _role = newsOptional.get();
                LambdaQueryWrapper<RoleDept> wrapper = new QueryWrapper<RoleDept>().lambda().eq(RoleDept::getRoleId, _role.getId());
                roleDeptMapper.delete(wrapper);
                _role.setName(dto.getName());
                _role.setRemarks(dto.getRemarks());
                roleMapper.updateById(_role);
                for (String deptId : dto.getDeptIds()) {
                    RoleDept roleDept = new RoleDept();
                    roleDept.setRoleId(_role.getId());
                    roleDept.setDeptId(deptId);
                    roleDeptMapper.insert(roleDept);
                }
            }
        }
        return _role;
    }

    /**
     * 保存或更新【菜单】权限
     *
     */
    public void saveMenu(RoleMenuDto dto){
        roleResourceMapper.delete(new UpdateWrapper<RoleResource>().lambda().eq(RoleResource::getRoleId,dto.getRoleId()));
        for (String menuId : dto.getMenuIds()) {
            RoleResource roleResource = new RoleResource();
            roleResource.setRoleId(dto.getRoleId());
            roleResource.setResourceId(menuId);
            roleResourceMapper.insert(roleResource);
        }
    }


    /**
     * 查询【角色】分页
     */
    public PageResult<ResponseRoleDto> page(SearchRoleDto dto) {
        LambdaQueryWrapper<Role> wrapper = new QueryWrapper<Role>().lambda();
        if(!StringUtils.isEmpty(dto.getName())){
            wrapper.like(Role::getName,dto.getName());
        }
        if(dto.getIsDel()==null){
            dto.setIsDel(false);
        }
        wrapper.eq(Role::getIsDel,dto.getIsDel());
        Page<Role> page = roleMapper.selectPage(new Page<>(dto.getPage(), dto.getSize()), wrapper);
        Page<ResponseRoleDto> dtoPage = new Page<>(dto.getPage(), dto.getSize());
        ArrayList<ResponseRoleDto> dtoList = new ArrayList<>();
        for (Role record : page.getRecords()) {
            ResponseRoleDto roleDto = new ResponseRoleDto();
            BeanUtils.copyProperties(record,roleDto);
            List<RoleDept> roleDepts = roleDeptMapper.selectList(new QueryWrapper<RoleDept>().lambda().eq(RoleDept::getRoleId, record.getId()));
            ArrayList<String> rDeptIds = new ArrayList<>();
            for (RoleDept roleDept : roleDepts) {
                rDeptIds.add(roleDept.getDeptId());
            }
            roleDto.setDeptIds(rDeptIds);
            List<RoleResource> roleResources = roleResourceMapper.selectList(new QueryWrapper<RoleResource>().lambda().eq(RoleResource::getRoleId, record.getId()));
            List<String> rResourceIds = new ArrayList<>();
            for (RoleResource roleResource : roleResources) {
                rResourceIds.add(roleResource.getResourceId());
            }
            roleDto.setMenuIds(rResourceIds);
            dtoList.add(roleDto);
        }
        dtoPage.setRecords(dtoList);
        return new PageResult<>(dto.getPage(), dto.getSize(), page.getTotal(), dtoPage.getRecords());
    }

    /**
     * 删除【角色】
     */
    public void handleIsDel(String id) {
        Optional<Role> optional = Optional.ofNullable(roleMapper.selectById(id));
        if (optional.isPresent()) {
            Role role = optional.get();
            role.setIsDel(!role.getIsDel());
            roleMapper.updateById(role);
            roleDeptMapper.update(null,new UpdateWrapper<RoleDept>().lambda().eq(RoleDept::getRoleId,role.getId()).set(BaseEntity::getIsDel,!role.getIsDel()));
        }
    }

    /**
     * 获取菜单节点
     */
    public List<ResponseNodeDto> getMenuNodes() {
        LambdaQueryWrapper<com.app.entity.platform.system.Resource> wrapper = new QueryWrapper<com.app.entity.platform.system.Resource>().lambda().eq(BaseEntity::getIsDel, Boolean.FALSE);
        List<com.app.entity.platform.system.Resource> menuList = resourceMapper.selectList(wrapper);
        List<ResponseNodeDto> list=new ArrayList<>();
        for (com.app.entity.platform.system.Resource menu : menuList) {
            ResponseNodeDto nodeDto = new ResponseNodeDto();
            BeanUtils.copyProperties(menu,nodeDto);
            nodeDto.setLabel(menu.getName());
            nodeDto.setValue(menu.getId());
            list.add(nodeDto);
        }
        return NodeUtils.buildTree(list);
    }


    public List<ResponseNodeDto> getAllNodes() {
        LambdaQueryWrapper<Role> wrapper = new QueryWrapper<Role>().lambda().eq(BaseEntity::getIsDel, Boolean.FALSE);
        List<Role> roleList = roleMapper.selectList(wrapper);
        List<ResponseNodeDto> list=new ArrayList<>();
        for (Role role : roleList) {
            ResponseNodeDto nodeDto = new ResponseNodeDto();
            nodeDto.setLabel(role.getName());
            nodeDto.setValue(role.getId());
            list.add(nodeDto);
        }
        return NodeUtils.buildTree(list);
    }
}
