const {models} = require('vn-loopback/server/server');

module.exports = Self => {
    Self.remoteMethodCtx('renewToken', {
        description: 'Checks if the token has more than renewPeriod seconds to live and if so, renews it',
        accessType: 'WRITE',
        accepts: [],
        returns: {
            type: 'Object',
            root: true
        },
        http: {
            path: `/renewToken`,
            verb: 'POST'
        },
        accessScopes: ['DEFAULT', 'read:multimedia']});

    Self.renewToken = async function(ctx) {
        let createTokenOptions = {};
        let token; let isNotExceeded;
        try {
            token = ctx.req.accessToken;

            const {courtesyTime} = await models.AccessTokenConfig.findOne({
                fields: ['courtesyTime']
            });
            isNotExceeded = await Self.validateToken(ctx);
            if (isNotExceeded)
                return token;

            // Schedule to remove current token
            setTimeout(async() => {
                try {
                    await Self.logout(token.id);
                } catch (error) {
                    // FIXME: Crash if do throw new Error(error)
                }
            }, courtesyTime * 1000);

            // Get scopes
            const {scopes} = token;
            if (scopes)
                createTokenOptions = {scopes: [scopes[0]]};
            // Create new accessToken
            const user = await Self.findById(token.userId);
            const accessToken = await user.accessTokens.create(createTokenOptions);

            return {id: accessToken.id, ttl: accessToken.ttl};
        } catch (error) {
            const body = {
                error: error.message,
                userId: token?.userId ?? null,
                token: token?.id,
                scopes: token?.scopes,
                createTokenOptions,
                isNotExceeded
            };
            await handleError(JSON.stringify(body));
            throw new Error(error);
        }
    };
};

async function handleError(body) {
    await models.Application.rawSql('CALL util.debugAdd(?,?);', ['renewToken', body]);
}