import {IToken, Token} from "../../models/Token";
import {IUser, Rank, User} from "../../models/User";
import {NextFunction, Request, Response} from "express";

export interface AuthenticatedRequest extends Request {
    token: IToken
    user: IUser
}

/** Authenticate the user using the authorization header */
module.exports.authenticate = async (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
    // Get the token header
    const authHeader = req.headers["authorization"];
    if (!authHeader) return res.status(400).json({message: "You need to provide the 'authorization' header"});

    // Validate token header
    const splitHeader = authHeader.split(" ");
    if (splitHeader.length !== 2) return res.status(400).json({message: "You need to provide the token in the 'authorization' header"});

    // Check if the provided token is wrong
    req.token = await Token.findOne({token: splitHeader[1]}).exec() as IToken;
    if (req.token == null) return res.status(401).json({message: "The provided token is wrong"});

    // Check if the provided user exists
    req.user = await User.findOne({clientId: req.token.clientId}) as IUser;
    if (req.user == null) return res.status(401).json({message: "The provided token is wrong"});

    next();
}

/**
 * Check if the current user has the provided rank
 * @param rank The rank which is required to use the route
 */
export const hasRank = (rank: Rank) => (req: AuthenticatedRequest, res: Response, next: NextFunction) => {
    // Admins have access to all routes
    if (req.user.rank === Rank.ADMIN) return next();

    if (req.user.rank === rank) return next();

    res.status(401).json({message: "You don't have the permission to use this route"});
}