import {Inject, Singleton} from "typescript-ioc";
import {HandlerInterceptor} from "./HandlerInterceptor";
import {Context, RedisTokenRepository} from "mslib";
import {StringUtils} from "utils/StringUtils";


/**
 * 登录拦截器
 */
@Singleton
class LoginInterceptor implements HandlerInterceptor {

    @Inject
    private redisTokenRepository: RedisTokenRepository

    async preService(request, reply): Promise<boolean> {
        if ('NODE' !== Context.getEnv('auth.mode')) {//NODE 鉴权模式下才需要处理用户登录
            return true
        }
        if (request.headers['kong-user-base64']) {
            return true
        }
        //是否忽略登录
        const isIgnoreLogin = this.isIgnoreService(request.headers['sid']);
        const token = request.headers['Authorization'] || request.headers['authorization'] || ''

        if (!token) {
            if (!isIgnoreLogin) {
                reply.code(200).send({code: 3000, message: 'Unauthorized'})
                return false
            } else {
                return true
            }
        }
        //忽略登录设置下如果传Token，同样需要转换成当前用户信息
        const getUserResult = await this.redisTokenRepository.getUserToken(token)
        if (!getUserResult.isSuccess()) {
            if (!isIgnoreLogin) {
                reply.code(200).send({code: 3001, message: 'Invalid Token'})
                return false
            }else{
                return true
            }
        } else {
            //塞回到headers中，由index.ts处理，放到Zone.js中
            request.headers["kong-user-base64"] = Buffer.from(JSON.stringify(getUserResult.data)).toString('base64')
            await this.redisTokenRepository.resetExpires(getUserResult.data);

            return true;
        }
    }


    /**
     * 判断是否需要登录校验
     */
    private isIgnoreService(sid?: string): boolean {
        if (StringUtils.isEmpty(sid)) {
            return true;
        }
        const serviceCode = StringUtils.substringAfterLast(".", sid).toLowerCase()
        const ignoreLoginServices = Context.getEnv("auth.ignore.logins") || Context.getEnv("autu.ignore.logins")
        if (!ignoreLoginServices) {
            return false
        }
        return ignoreLoginServices.toLowerCase().split("|").includes(serviceCode)
    }


}

export {LoginInterceptor}