package com.simuwang.manage.service;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.simuwang.base.common.exception.APIException;
import com.simuwang.base.common.util.TreeUtil;
import com.simuwang.base.components.UserAuthService;
import com.simuwang.base.config.DaqProperties;
import com.simuwang.base.pojo.dos.sys.SysMenuDO;
import com.simuwang.base.pojo.dos.sys.SysRoleDO;
import com.simuwang.base.pojo.dos.sys.SysUserDO;
import com.simuwang.base.pojo.dto.sys.UserUpdatePwdCmd;
import com.simuwang.manage.dto.MenuTreeDTO;
import com.simuwang.manage.dto.UserInfoVO;
import com.simuwang.manage.dto.UserRoleDTO;
import com.simuwang.shiro.core.ShiroUser;
import com.simuwang.shiro.utils.UserUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

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

/**
 * @author wangzaijun
 * @date 2024/9/12 20:28
 * @description 系统管理服务
 */
@Service
public class LoginService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final DaqProperties properties;
    private final UserAuthService userAuthService;

    public LoginService(DaqProperties properties, UserAuthService userAuthService) {
        this.properties = properties;
        this.userAuthService = userAuthService;
    }

    public String getRsaPublicKey() {
        return this.properties.getSecurityRsa().getPublicKey();
    }

    /**
     * 获取当前用户的权限角色信息
     *
     * @return /
     */
    public UserInfoVO getUserInfo() {
        ShiroUser shiroUser = UserUtils.getLoginUser();
        Integer userId = shiroUser.getUserId();
        String username = shiroUser.getUsername();
        SysUserDO userInfo = this.userAuthService.getUserInfoByUsername(username);
        // 用户角色信息转换
        List<SysRoleDO> roleList = this.userAuthService.listUserRoleByUserId(userId);
        List<UserRoleDTO> roles = roleList.stream()
                .map(e -> new UserRoleDTO(e.getRoleId(), e.getRoleName(), e.getRoleKey()))
                .distinct().collect(Collectors.toList());
        // 用户权限处理
        List<SysMenuDO> menuList = this.userAuthService.listUserMenuByUserId(userId);
        // 过滤按钮
        List<MenuTreeDTO> tempList = menuList.stream().filter(e -> !Objects.equals("F", e.getMenuType()))
                .map(MenuTreeDTO::new).collect(Collectors.toList());
        // 菜单列表转树结构
        List<MenuTreeDTO> trees = TreeUtil.list2Tree(tempList, MenuTreeDTO::getId, MenuTreeDTO::getPid,
                MenuTreeDTO::getChildren, MenuTreeDTO::setChildren, 0, MenuTreeDTO::getSort);
        MenuTreeDTO root = new MenuTreeDTO(0, "全部菜单", trees);
        // 返回的数据结构构建
        UserInfoVO vo = new UserInfoVO(userId, username, roles, root);
        vo.setEmail(userInfo.getEmail());
        vo.setPhonenumber(userInfo.getPhonenumber());
        return vo;
    }

    /**
     * 修改密码
     *
     * @param command /
     */
    public void updatePwd(UserUpdatePwdCmd command) {
        ShiroUser loginUser = UserUtils.getLoginUser();
        Integer userId = loginUser.getUserId();
        String oldPwd = this.decryptPwd(command.getOldPassword());
        String newPwd = this.decryptPwd(command.getNewPassword());
        String confirmPwd = this.decryptPwd(command.getConfirmPassword());
        if (!StrUtil.isAllNotBlank(oldPwd, newPwd, confirmPwd)) {
            throw new APIException("前端密码加密错误");
        }
        if (Objects.equals(oldPwd, newPwd)) {
            throw new APIException("新密码不能和旧密码一样");
        }
        if (!Objects.equals(newPwd, confirmPwd)) {
            throw new APIException("确认密码和新密码不相等");
        }
        SysUserDO entity = command.toEntity();
        entity.setUserId(userId);
        entity.setPassword(newPwd);
        this.userAuthService.updatePwd(entity);
    }

    private String decryptPwd(String pwd) {
        DaqProperties.SecurityRsa securityRsa = this.properties.getSecurityRsa();
        String privateKey = securityRsa.getPrivateKey();
        try {
            return new RSA(privateKey, null).decryptStr(pwd, KeyType.PrivateKey);
        } catch (Exception e) {
            this.logger.error("密码rsa解密错误\n{}", ExceptionUtil.stacktraceToString(e));
        }
        return null;
    }
}
