package top.continew.admin.common.util.helper;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.JakartaServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import jakarta.servlet.http.HttpServletRequest;
import top.continew.admin.common.constant.CacheConstants;
import top.continew.admin.common.model.dto.LoginUser;
import top.continew.admin.common.util.AiBotUtil;
import top.continew.starter.core.util.ExceptionUtils;
import top.continew.starter.core.util.IpUtils;
import top.continew.starter.extension.crud.service.CommonUserService;
import top.continew.starter.web.util.ServletUtils;
import top.continew.starter.web.util.SpringWebUtils;

import java.time.LocalDateTime;

/**
 * 登录助手
 *
 * @author Charles7c
 * @author Lion Li（<a href="https://gitee.com/dromara/RuoYi-Vue-Plus">RuoYi-Vue-Plus</a>）
 * @since 2022/12/24 12:58
 */
public class LoginHelper {

    private LoginHelper() {
    }

    /**
     * 用户登录并缓存用户信息
     *
     * @param loginUser 登录用户信息
     * @return 令牌
     */
    public static LoginUser login(LoginUser loginUser) {
        // 记录登录信息
        HttpServletRequest request = SpringWebUtils.getRequest();
        loginUser.setIp(JakartaServletUtil.getClientIP(request));
        loginUser.setAddress(ExceptionUtils.exToNull(() -> IpUtils.getIpv4Address(loginUser.getIp())));
        loginUser.setBrowser(ServletUtils.getBrowser(request));
        loginUser.setLoginTime(LocalDateTime.now());
        loginUser.setOs(StrUtil.subBefore(ServletUtils.getOs(request), " or", false));

        // 非管理员登录第三方平台
        if (!loginUser.isAdmin()) {
            String aiBotToken = AiBotUtil.login(loginUser.getUsername(), loginUser.getPassword());
            loginUser.setAiBotToken(aiBotToken);
        }

        // 登录并缓存用户信息
        StpUtil.login(loginUser.getId());
        SaHolder.getStorage().set(CacheConstants.LOGIN_USER_KEY, loginUser);
        String tokenValue = StpUtil.getTokenValue();
        loginUser.setToken(tokenValue);
        StpUtil.getTokenSession().set(CacheConstants.LOGIN_USER_KEY, loginUser);
        return loginUser;
    }

    /**
     * 更新登录用户信息
     *
     * @param loginUser
     *                  登录用户信息
     * @param token     令牌
     */
    public static void updateLoginUser(LoginUser loginUser, String token) {
        SaHolder.getStorage().delete(CacheConstants.LOGIN_USER_KEY);
        StpUtil.getTokenSessionByToken(token).set(CacheConstants.LOGIN_USER_KEY, loginUser);
    }

    /**
     * 获取登录用户信息
     *
     * @return 登录用户信息
     * @throws NotLoginException 未登录异常
     */
    public static LoginUser getLoginUser() throws NotLoginException {
        StpUtil.checkLogin();
        LoginUser loginUser = (LoginUser)SaHolder.getStorage().get(CacheConstants.LOGIN_USER_KEY);
        if (null != loginUser) {
            return loginUser;
        }
        SaSession tokenSession = StpUtil.getTokenSession();
        loginUser = (LoginUser)tokenSession.get(CacheConstants.LOGIN_USER_KEY);
        SaHolder.getStorage().set(CacheConstants.LOGIN_USER_KEY, loginUser);
        return loginUser;
    }

    /**
     * 安全获取登录用户信息，如果未登录返回null
     *
     * @return 登录用户信息，未登录时返回null
     */
    public static LoginUser getLoginUserSafely() {
        try {
            if (!StpUtil.isLogin()) {
                return null;
            }
            LoginUser loginUser = (LoginUser)SaHolder.getStorage().get(CacheConstants.LOGIN_USER_KEY);
            if (null != loginUser) {
                return loginUser;
            }
            SaSession tokenSession = StpUtil.getTokenSession();
            loginUser = (LoginUser)tokenSession.get(CacheConstants.LOGIN_USER_KEY);
            SaHolder.getStorage().set(CacheConstants.LOGIN_USER_KEY, loginUser);
            return loginUser;
        } catch (NotLoginException e) {
            // 捕获未登录异常，返回null
            return null;
        } catch (Exception e) {
            // 捕获其他异常，返回null
            return null;
        }
    }

    /**
     * 根据 Token 获取登录用户信息
     *
     * @param token 用户 Token
     * @return 登录用户信息
     */
    public static LoginUser getLoginUser(String token) {
        SaSession tokenSession = StpUtil.getStpLogic().getTokenSessionByToken(token, false);
        if (null == tokenSession) {
            return null;
        }
        return (LoginUser)tokenSession.get(CacheConstants.LOGIN_USER_KEY);
    }

    /**
     * 获取登录用户 ID
     *
     * @return 登录用户 ID
     */
    public static Long getUserId() {
        return getLoginUser().getId();
    }

    /**
     * 获取登录用户名
     *
     * @return 登录用户名
     */
    public static String getUsername() {
        return getLoginUser().getUsername();
    }

    /**
     * 获取登录用户昵称
     *
     * @return 登录用户昵称
     */
    public static String getNickname() {
        return getNickname(getUserId());
    }

    /**
     * 获取登录用户昵称
     *
     * @param userId 登录用户 ID
     * @return 登录用户昵称
     */
    public static String getNickname(Long userId) {
        return ExceptionUtils.exToNull(() -> SpringUtil.getBean(CommonUserService.class).getNicknameById(userId));
    }
}