package com.sptg.permissions.biz.service.impl;

import com.baomidou.mybatisplus.enums.SqlLike;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.sptg.common.core.beans.PageBean;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.beans.ResultEnum;
import com.sptg.common.core.constant.OperationConstant;
import com.sptg.common.core.util.JsonUtils;
import com.sptg.permissions.api.dto.RoleDto;
import com.sptg.permissions.api.entity.*;
import com.sptg.permissions.api.enums.PermissionsEnum;
import com.sptg.permissions.biz.mapper.RoleMapper;
import com.sptg.permissions.biz.service.AccountRoleServiceInterface;
import com.sptg.permissions.biz.service.RoleMenuServiceInterface;
import com.sptg.permissions.biz.service.RoleServiceInterface;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * title: RoleServiceImpl
 * package: com.sptg.permissions.biz.security.impl
 * description: 角色-服务层接口实现类
 *
 *                  
 *                 
 */
@Setter
@Service
@RequiredArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleServiceInterface {


    /**
     * 角色缓存名称
     */
    private final static String ROLE_CACHE_NAME = "sptg:permissions:role";

    private final RoleMenuServiceInterface roleMenuServiceInterface;
    private final RedisTemplate<String,String> redisTemplate;
    private final AccountRoleServiceInterface accountRoleServiceInterface;

    /* ------------------------------------- 重写父类查询方法，过滤已删除的数据 ------------------------------------- */
    /* -------------------------------------------------------------------------------------------------------------- */

    @Override
    public Role selectOne(Wrapper<Role> wrapper) {
        //  过滤掉被删除的记录
        wrapper.notIn("i_status", OperationConstant.MINUS_ONE);
        return super.selectOne(wrapper);
    }

    @Override
    public Page<Role> selectPage(Page<Role> page, Wrapper<Role> wrapper) {
        //  过滤掉被删除的记录
        wrapper.notIn("i_status", OperationConstant.MINUS_ONE);
        return super.selectPage(page, wrapper);
    }

    @Override
    public boolean updateById(Role entity) {
        boolean result = super.updateById(entity);
        if (result){
            this.redisTemplate.opsForHash().delete(ROLE_CACHE_NAME,entity.getId().toString());
        }
        return result;
    }

    @Override
    public List<Role> selectList(Wrapper<Role> wrapper) {
        wrapper.notIn("i_status", OperationConstant.MINUS_ONE);
        return super.selectList(wrapper);
    }

    @Override
    public boolean updateBatchById(List<Role> entityList) {
        boolean result = super.updateBatchById(entityList);
        if (result){
            HashOperations<String, String, String> hashOperations = this.redisTemplate.opsForHash();
            entityList.forEach(entity -> hashOperations.delete(ROLE_CACHE_NAME,entity.getId().toString()));
        }
        return result;
    }

    /* -------------------------------------------------- 业务代码 -------------------------------------------------- */
    /* -------------------------------------------------------------------------------------------------------------- */

    @Override
    public Role selectById(Serializable id) {
        //  查询缓存
        HashOperations<String, String, String> hashOperations = this.redisTemplate.opsForHash();
        String hashKey = id.toString();
        String json = hashOperations.get(ROLE_CACHE_NAME, hashKey);
        if (StringUtils.isEmpty(json)) {
            //  构建查询数据库
            Wrapper<Role> wrapper = new EntityWrapper<>();
            //  根据Id查询
            wrapper.eq("l_id", id);
            Role role = this.selectOne(wrapper);
            if (null != role) {
                //  保存到缓存中
                json = JsonUtils.objectToJson(role);
                hashOperations.put(ROLE_CACHE_NAME,hashKey,json);
            }
            return role;
        }
        return JsonUtils.jsonToPojo(json,Role.class);
    }

    @Override
    public ResultBean<Page> pagingQuery(PageBean<Role,RoleDto> pageBean) {
        RoleDto dto = pageBean.getDto();
        //  创建查询条件
        Wrapper<Role> wrapper = new EntityWrapper<>();
        if (!StringUtils.isEmpty(dto.getName())){
            //  根据角色名称模糊查询
            wrapper.like("s_name",dto.getName(), SqlLike.DEFAULT);
        }
        if (dto.getIsEnable() != null){
            wrapper.eq("i_is_enable",dto.getIsEnable());
        }
        //  用户所属机构Id
        wrapper.eq("l_org_id",dto.getOnLineUser().getOrgId());
        Page<Role> page = this.selectPage(pageBean,wrapper);
        return new ResultBean<>(ResultEnum.SUCCESS,page);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public ResultBean<Boolean> addEntity(RoleDto dto) {
        //  获取当前操作用户
        Account onLineUser = dto.getOnLineUser();
        //  校验角色名称是否存在
        if (null != this.selectByNameAndOrgId(dto.getName(),onLineUser.getOrgId())){
            return new ResultBean<>(PermissionsEnum.ROLE_IS_EXIST);
        }
        //  是否可用
        if (null == dto.getIsEnable()){
            dto.setIsEnable(OperationConstant.ONE);
        }
        //  机构信息
        dto.setOrgId(onLineUser.getOrgId());
        dto.setOrgName(onLineUser.getOrgName());
        dto.setOrgPosition(onLineUser.getOrgPosition());
        dto.setRootOrgId(onLineUser.getRootOrgId());
        //  未删除状态
        dto.setStatus(OperationConstant.ZERO);
        //  创建人,创建时间
        dto.setCreateAccountId(onLineUser.getId());
        dto.setCreateDate(new Date());
        //  保存角色
        if (this.insert(dto)){
            //  保存角色与菜单的关联
            this.roleMenuServiceInterface.insertBatch(dto);
            return new ResultBean<>(ResultEnum.SUCCESS,true);
        }
        return new ResultBean<>(ResultEnum.ERROR);
    }

    @Override
    public Role selectByNameAndOrgId(String name,Long orgId) {
        Wrapper<Role> wrapper = new EntityWrapper<>();
        wrapper.eq("s_name",name);
        wrapper.eq("l_org_id",orgId);
        return this.selectOne(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public ResultBean<Boolean> updateEntity(RoleDto dto) {
        //  获取当前用户
        Account onLineUser = dto.getOnLineUser();
        //  获取修改前的数据
        Role dbRole = this.selectById(dto.getId());
        Assert.notNull(dbRole,"角色Id不存在");
        //  判断权限
        if (!dbRole.getOrgId().equals(onLineUser.getOrgId())){
            return new ResultBean<>(ResultEnum.FORBIDDEN);
        }
        //  判断是否修改了用户名
        if (!StringUtils.isEmpty(dto.getName()) && !dbRole.getName().equals(dto.getName())){
            //  校验角色名称是否存在
            if (null != this.selectByNameAndOrgId(dto.getName(),onLineUser.getOrgId())){
                return new ResultBean<>(PermissionsEnum.ROLE_IS_EXIST);
            }
        }
        //  保存修改
        if (this.updateById(dto)){
            //  更改角色与菜单的关联
            this.roleMenuServiceInterface.updateRoleMenu(dto);
            return new ResultBean<>(ResultEnum.SUCCESS,true);
        }
        return new ResultBean<>(ResultEnum.ERROR);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public ResultBean<Boolean> deleteEntity(RoleDto dto) {
        //  获取当前用户
        Account onLineUser = dto.getOnLineUser();
        //  获取修改前的数据
        Role dbRole = this.selectById(dto.getId());
        Assert.notNull(dbRole,"角色不存在");
        //  判断权限
        if (!dbRole.getOrgId().equals(onLineUser.getOrgId())){
            return new ResultBean<>(ResultEnum.FORBIDDEN);
        }
        //  判断该角色是否绑定了账号
        if (this.accountRoleServiceInterface.checkRoleIsWasUse(dbRole.getId())){
            return new ResultBean<>(PermissionsEnum.ROLE_WAS_USE);
        }
        //  标记为删除状态
        dbRole.setStatus(OperationConstant.MINUS_ONE);
        if (this.updateById(dbRole)){
            //  删除角色与菜单的关联
            this.roleMenuServiceInterface.deleteByRoleId(dbRole.getId());
            return new ResultBean<>(ResultEnum.SUCCESS,true);
        }
        return new ResultBean<>(ResultEnum.ERROR);
    }

    @Override
    public List<Role> getListByOrgId(Serializable orgId) {
        Wrapper<Role> wrapper = new EntityWrapper<>();
        wrapper.eq("l_org_id",orgId);
        return this.selectList(wrapper);
    }

    @Override
    public List<Role> getListByAccountId(Serializable accountId) {
        //  获取账号的所有角色Id
        List<Long> roleIdList = this.accountRoleServiceInterface.selectRoleIdListByAccountId(accountId);
        List<Role> roleList = new ArrayList<>(roleIdList.size());
        //  获取角色信息
        roleIdList.forEach(item -> {
            Role role = this.selectById(item);
            if (null != role) {
                role.setMenuList(null);
                roleList.add(role);
            }
        });
        return roleList;
    }

    @Override
    public void updateBatch(List<Role> roleList) {
        this.updateBatchById(roleList);
    }

    @Override
    public List<Role> selectByOrgPosition(String position) {
        Wrapper<Role> wrapper = new EntityWrapper<>();
        wrapper.like("s_org_position",position,SqlLike.RIGHT);
        return this.selectList(wrapper);
    }

    /* -------------------------------------------------- 公共方法 -------------------------------------------------- */
    /* -------------------------------------------------------------------------------------------------------------- */


}
