import Cookies from 'js-cookie';

import { secureLocalStorage as ls } from '@/utils/localUtils';
import { encryptKey, encryptData, decryptData } from '@/utils/storage';

import { currentJsTimestamp, currentUnixTimestamp } from './timeUtils';

export const userKey = 'user-info';
export const tokenKey = 'authorized-token';

/** 获取`token` */
export function getToken(): API.UserInfo {
    const cookieData = Cookies.get(encryptKey(tokenKey));
    const cookieDecrypted = cookieData ? decryptData(cookieData) : '';
    return cookieDecrypted ? JSON.parse(cookieDecrypted) : (ls.getLocal(userKey) as API.UserInfo);
}

/**
 * @description 设置 token 以及一些必要信息并采用无感刷新 token 方案
 * 无感刷新：后端返回 accessToken（访问接口使用的 token）、refreshToken（用于调用刷新 accessToken 的接口时所需的 token，refreshToken 的过期时间（比如30天）应大于 accessToken 的过期时间（比如2小时））、expires（accessToken 的过期时间）
 * 将 accessToken、expires、refreshToken 这三条信息放在 key 值为 authorized-token 的 cookie 里（过期自动销毁）
 * 将除了 accessToken 之外的其他信息放在 key 值为 user-info 的 localStorage 里
 */
export function setToken(data: API.UserInfo) {
    const { accessToken = '', accessExpires = 0, refreshToken = '' } = data;
    const cookieData = JSON.stringify({ accessToken, accessExpires, refreshToken });
    const cookieEncrypted = encryptData(cookieData);

    if (accessExpires > 0) {
        Cookies.set(encryptKey(tokenKey), cookieEncrypted, {
            expires: (accessExpires * 1000 - currentJsTimestamp()) / 86400000,
        });
    } else {
        Cookies.set(encryptKey(tokenKey), cookieEncrypted);
    }

    function setUserKey(data: API.UserInfo) {
        const { accessToken: _, accessExpires: __, refreshToken: ___, ...rest } = data;
        ls.setLocal(userKey, {
            refreshToken,
            accessExpires,
            ...rest,
        });
    }

    if (data.account?.username) {
        // 登录时，后端接口会返回用户信息，直接设置到 localStorage 中
        setUserKey(data);
    } else {
        // 刷新 token 时，后端接口不会返回用户信息，需要从 localStorage 中获取用户信息
        const d = ls.getLocal<API.UserInfo>(userKey);
        setUserKey({ ...d });
    }
}

/** 删除`token`以及key值为`user-info`的session信息 */
export function removeToken() {
    Cookies.remove(encryptKey(tokenKey));
    ls.removeLocal(userKey);
}

/** 实时判断当前是否已认证（accessToken 存在且未过期） */
export function isAuthenticated(): boolean {
    const token = getToken();
    if (!token?.accessToken) return false;
    if (!token.accessExpires) return false;
    return token.accessExpires - currentUnixTimestamp() > 0;
}

/** 格式化token（jwt格式） */
export const formatToken = (token: string): string => {
    return 'Bearer ' + token;
};
