/* eslint-disable no-underscore-dangle */
const jwt = require('jsonwebtoken');
const { createAuthToken } = require('@abtnode/auth/lib/auth');
const { isUserPassportRevoked } = require('@abtnode/auth/lib/passport');

const getUser = async (node, teamDid, userDid) => {
  const user = await node.getUser({ teamDid, user: { did: userDid } });
  if (user && user.approved) {
    return user;
  }
  return null;
};

// eslint-disable-next-line no-unused-vars
const initJwt = (node, options) => {
  const secret = options.sessionSecret;
  const ttl = options.sessionTtl || '1d';

  if (!secret) {
    throw new Error('Auth service require a non-empty session secret to start');
  }

  const login = async (did, { role, passport }) =>
    createAuthToken({
      did,
      passport,
      role,
      secret,
      expiresIn: ttl,
    });

  const verify = (token, teamDid) =>
    // eslint-disable-next-line implicit-arrow-linebreak
    new Promise((resolve, reject) => {
      jwt.verify(token, secret, async (err, decoded) => {
        if (err) {
          return reject(err);
        }

        const { did, role, passport } = decoded;
        if (!did) {
          return reject(new Error('Invalid jwt token: invalid did'));
        }

        const user = await getUser(node, teamDid, did);
        if (!user) {
          return reject(new Error('Invalid jwt token: invalid user'));
        }

        if (passport && passport.id && isUserPassportRevoked(user, passport)) {
          return reject(new Error(`Passport ${passport.name} has been revoked`));
        }

        user.role = role;

        // backward compatible
        if (!role && passport && !passport.id) {
          user.role = passport.name;
        }

        return resolve(user);
      });
    });

  return {
    login,
    verify,
  };
};

initJwt.getUser = getUser;

module.exports = initJwt;
