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

import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import com.cpop.core.base.enums.UserType;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.base.table.User;
import com.cpop.core.constant.Constants;
import com.cpop.core.service.UserService;
import com.cpop.core.utils.RsaUtils;
import com.cpop.core.utils.SpringUtils;
import com.cpop.core.utils.bean.BeanUtils;
import com.cpop.oam.business.bo.LoginForm;
import com.cpop.oam.business.entity.Staff;
import com.cpop.oam.business.service.LoginService;
import com.cpop.oam.business.service.StaffService;
import com.cpop.oam.business.vo.loginInfo.SysStaffLoginInfo;
import com.cpop.oam.business.entity.Menu;
import com.cpop.oam.business.service.MenuService;
import com.cpop.oam.business.vo.LoginUserInfoVo;
import com.cpop.oam.business.vo.MenuRouteVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.cpop.core.base.table.table.UserTableDef.USER;
import static com.cpop.oam.business.entity.table.StaffTableDef.STAFF;
import static com.cpop.oam.business.entity.table.MenuTableDef.MENU;
import static com.cpop.oam.business.entity.table.RoleMenuTableDef.ROLE_MENU;
import static com.cpop.oam.business.entity.table.RoleTableDef.ROLE;

/**
 * @author DB
 * @createTime 2023/09/10 11:19
 * @description
 */
@Service("loginService")
public class LoginServiceImpl implements LoginService {

    @Autowired
    private RsaUtils rsaUtils;

    /**
     * 系统登录
     * @author DB
     * @since 2024/4/24
     * @param loginForm 登录表单
     * @return SysStaffLoginInfo
     */
    @Override
    public SysStaffLoginInfo login(LoginForm loginForm) {
        //获取用户信息
        User user = SpringUtils.getBean(UserService.class).queryChain()
                .select(USER.ID, USER.USERNAME, USER.PASSWORD, USER.PHONE, USER.AVATAR)
                .where(USER.USERNAME.eq(loginForm.getUsername()))
                .one();
        if (user == null){
            throw new ServiceException("用户名或密码错误!");
        }
        //rsa解密
        String password = rsaUtils.decrypt(loginForm.getPassword());
        // 使用checkpw方法检查被加密的字符串是否与原始字符串匹配：
        if (!BCrypt.checkpw(password, user.getPassword())) {
            throw new ServiceException("用户名或密码错误!");
        }
        return getStaffLoginInfo(user);
    }

    /**
     * 获取系统用户信息
     * @author DB
     * @since 2024/3/21
     * @param user 用户
     * @return SysStaffLoginInfo
     */
    private SysStaffLoginInfo getStaffLoginInfo(User user){
        //获取员工信息
        SysStaffLoginInfo staffLoginInfo = BeanUtils.mapToClass(user, SysStaffLoginInfo.class);
        if (!staffLoginInfo.getUsername().equals(Constants.SUPER_ADMIN)) {
            Staff staff = SpringUtils.getBean(StaffService.class).queryChain()
                    .where(STAFF.USER_ID.eq(user.getId()))
                    .one();
            staffLoginInfo.setRoleId(staff.getRoleId());
            staffLoginInfo.setIsSuper(false);
            staffLoginInfo.setName(staff.getRoleId());
            staffLoginInfo.setId(staff.getId());
        } else {
            staffLoginInfo.setRoleId(Constants.SUPER_ROLE_ID);
            staffLoginInfo.setIsSuper(true);
            staffLoginInfo.setName(Constants.SUPER_ADMIN);
            staffLoginInfo.setId(Constants.SUPER_ADMIN_ID);
        }
        staffLoginInfo.setUserId(user.getId())
                .setAvatar(user.getAvatar())
                .setPhone(user.getPhone())
                .setUserType(UserType.OAM_USER);
        return staffLoginInfo;
    }

    /**
     * 获取用户信息
     * @author LOST.yuan
     * @since 23:01 2022/9/26
     * @return {@link String}
     **/
    @Override
    public LoginUserInfoVo getUserInfo() {
        SaSession session = StpUtil.getSession();
        return new LoginUserInfoVo()
                .setId(session.getString("id"))
                .setUserId(session.getString("userId"))
                .setUsername(session.getString("username"))
                .setRealName(session.getString("name"))
                .setAvatar(session.getString("avatar"))
                .setPermissions(StpUtil.getPermissionList());
    }

    /**
     * 获取权限码
     * @author DB
     * @since 2023-11-30 14:32:57
     * @version 1.0.0
     */
    @Override
    public Set<String> getPermCode() {
        SaSession session = StpUtil.getSession();
        if (StringUtils.equals(Constants.SUPER_ADMIN, session.getString("username"))) {
            Set<String> permCodes = new HashSet<>();
            permCodes.add("*.*.*");
            return permCodes;
        } else {
            List<Menu> menuPermissions = SpringUtils.getBean(MenuService.class)
                .queryChain()
                .select(MENU.PERMISSION)
                .leftJoin(ROLE_MENU)
                .on(ROLE_MENU.MENU_ID.eq(MENU.ID))
                .leftJoin(ROLE)
                .on(ROLE.ID.eq(ROLE_MENU.ROLE_ID))
                .where(ROLE.ID.eq(session.getString("roleId")))
                .and(MENU.TYPE.in(1, 2))
                .and(MENU.PERMISSION.isNotNull())
                .list();
            return menuPermissions.stream().map(Menu::getPermission).collect(Collectors.toSet());
        }

    }

    /**
     * 获取菜单列表
     */
    @Override
    public List<MenuRouteVo> getSysMenuList() {
        return SpringUtils.getBean(MenuService.class).getSysMenuList();
    }
}
