package com.qmth.sop.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.boot.api.exception.ApiException;
import com.qmth.sop.business.bean.dto.RoleDto;
import com.qmth.sop.business.bean.params.SysRolePrivilegeParam;
import com.qmth.sop.business.bean.result.RoleResult;
import com.qmth.sop.business.cache.CommonCacheService;
import com.qmth.sop.business.entity.*;
import com.qmth.sop.business.mapper.SysRoleMapper;
import com.qmth.sop.business.service.*;
import com.qmth.sop.common.enums.ExceptionResultEnum;
import com.qmth.sop.common.enums.FieldUniqueEnum;
import com.qmth.sop.common.enums.RoleTypeEnum;
import com.qmth.sop.common.util.ResultUtil;
import com.qmth.sop.common.util.ServletUtil;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2023-07-17
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    @Resource
    CommonCacheService commonCacheService;

    @Resource
    SysRolePrivilegeService sysRolePrivilegeService;

    @Resource
    SysUserRoleService sysUserRoleService;

    @Resource
    SysUserService sysUserService;

    @Resource
    TBUserArchivesService tbUserArchivesService;

    @Resource
    TBUserArchivesAllocationService tbUserArchivesAllocationService;

    /**
     * 根据userId查询角色
     *
     * @param userId
     * @return
     */
    @Override
    public List<RoleDto> listRolesByUserId(Long userId) {
        return this.baseMapper.listRolesByUserId(userId);
    }

    /**
     * 查询角色列表
     *
     * @param iPage
     * @param name
     * @param enable
     * @return
     */
    @Override
    public IPage<RoleDto> query(IPage<Map> iPage, String name, Boolean enable) {
        return this.baseMapper.query(iPage, name, enable);
    }

    /**
     * 新增/修改角色
     *
     * @param sysRolePrivilegeParams
     * @return
     */
    @Override
    @Transactional
    public Boolean saveRole(SysRolePrivilegeParam sysRolePrivilegeParams) {
        boolean success = false;
        try {
            SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
            SysRole role = new SysRole(sysRolePrivilegeParams);
            //编辑
            if (Objects.nonNull(sysRolePrivilegeParams.getId())) {
                SysRole sysRoleDb = this.getById(sysRolePrivilegeParams.getId());
                Optional.ofNullable(sysRoleDb).orElseThrow(() -> ExceptionResultEnum.ROLE_NO_EXISTS.exception());

                role.setType(sysRoleDb.getType());
                role.setDefaultRole(sysRoleDb.getDefaultRole());
                role.setInterpret(sysRoleDb.getType().getTitle());
                role.updateInfo(sysUser.getId());
                success = this.updateById(role);
                if (success) {
                    commonCacheService.updateRoleCache(role.getId());
                    boolean isChange = sysRolePrivilegeService.saveBatch(role);//角色权限
                    if (isChange) {
                        commonCacheService.updateRolePrivilegeCache(role.getId());
                        //绑定该角色的用户都需要清除鉴权缓存
                        List<SysUserRole> sysUserRoleList = sysUserRoleService.listByRoleId(role.getId());
                        sysUserService.removeUserInfoBatch(sysUserRoleList.stream().map(SysUserRole::getUserId).collect(Collectors.toList()), true);
                    }
                }
            } else {
                role.insertInfo(sysUser.getId());
                success = this.save(role);
                if (success) {
                    sysRolePrivilegeService.saveBatch(role);//角色权限
                }
            }
        } catch (Exception e) {
            if (e instanceof DuplicateKeyException) {
                String errorColumn = e.getCause().toString();
                String columnStr = errorColumn.substring(errorColumn.lastIndexOf("key") + 3, errorColumn.length()).replaceAll("'", "");
                throw ExceptionResultEnum.SQL_ERROR.exception("[" + FieldUniqueEnum.convertToTitle(columnStr) + "]数据不允许重复插入");
            } else if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, ((ApiException) e).getCode(), e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return success;
    }

    /**
     * 根据id删除角色
     *
     * @param roleId
     * @return
     * @throws NoSuchAlgorithmException
     */
    @Override
    @Transactional
    public Boolean deleteRole(Long roleId) throws NoSuchAlgorithmException {
        SysRole sysRole = this.getById(roleId);
        Optional.ofNullable(sysRole).orElseThrow(() -> ExceptionResultEnum.ROLE_NO_EXISTS.exception());
        if (sysRole.getDefaultRole()) {
            throw ExceptionResultEnum.EXCEPTION_ERROR.exception("系统默认角色不允许删除");
        }

        List<SysUserRole> sysUserRoleList = sysUserRoleService.listByRoleId(roleId);
        if (!CollectionUtils.isEmpty(sysUserRoleList)) {
            throw ExceptionResultEnum.EXCEPTION_ERROR.exception("该角色已绑定用户，不允许删除");
        }
        boolean success = this.removeById(roleId);
        if (success) {
            sysRolePrivilegeService.remove(new QueryWrapper<SysRolePrivilege>().lambda().eq(SysRolePrivilege::getRoleId, roleId));
            commonCacheService.removeRoleCache(roleId);
            sysUserRoleList.forEach(s -> {
                commonCacheService.removeUserRolePrivilegeCache(s.getUserId());
            });
        }
        return success;
    }

    @Override
    public RoleResult findRoleInfoByArchivesType(RoleTypeEnum roleTypeEnum) {
        RoleResult result = new RoleResult();
        if (RoleTypeEnum.REGION_COORDINATOR.equals(roleTypeEnum) || RoleTypeEnum.ASSISTANT_ENGINEER.equals(roleTypeEnum) || RoleTypeEnum.EFFECT_ENGINEER.equals(roleTypeEnum)) {
            List<SysRole> sysRoleList = this.list(new QueryWrapper<SysRole>().lambda().eq(SysRole::getType, roleTypeEnum));
            if (sysRoleList.size() != 1) {
                throw ExceptionResultEnum.ERROR.exception("角色类型对应的角色异常[" + roleTypeEnum + "]");
            }
            SysRole sysRole = sysRoleList.get(0);
            result.setRoleId(sysRole.getId());
            result.setRoleType(sysRole.getType().name());
            result.setRoleName(sysRole.getName());
        }
        return result;
    }

    @Override
    public RoleTypeEnum findRoleTypeByUserCrm(Long userId, String crmNo) {
        RoleTypeEnum result = null;
        List<TBUserArchivesAllocation> tbUserArchivesAllocationList = tbUserArchivesAllocationService.list(new QueryWrapper<TBUserArchivesAllocation>().lambda()
                .eq(TBUserArchivesAllocation::getUserId, userId)
                .eq(TBUserArchivesAllocation::getCrmNo, crmNo));
        if (!CollectionUtils.isEmpty(tbUserArchivesAllocationList)) {
            TBUserArchivesAllocation tbUserArchivesAllocation = tbUserArchivesAllocationList.get(0);
            Long roleId = tbUserArchivesAllocation.getRoleId();
            SysRole role = this.getById(roleId);
            if (Objects.nonNull(role)) {
                result = role.getType();
            }
        }
        return result;
    }
}
