// ----------------------------------------------
// jwt.middleware.js
// ----------------------------------------------
// JWT Middleware.js
// Check the autorization ( Bearer token ).

import JWT from "jsonwebtoken";

import models from "$models/index.js";
import { appConfig } from "$config/index.js";
import {
  identityHelpers,
  testModeHelpers,
  tokenBlacklistHelpers,
} from "$helpers/index.js";

const jwt = async (req, res, next) => {
  // ----------------------------------------------
  // jwt()
  // ----------------------------------------------
  // First chec that the request contains autorization or not.
  // Then, chec that user is exist or not.
  // If all got ok, the request autotization is valid.

  const { authorization } = req.headers;

  if (!authorization) {
    return res.status(401).send({ message: "Unauthorized" });
  }

  const token = authorization.split(" ")[1];

  // Check if token is revoked
  if (await tokenBlacklistHelpers.isTokenRevoked(token)) {
    return res.status(401).send({ message: "Token has been revoked" });
  }

  try {
    const { id } = JWT.verify(token, appConfig.secret);

    const user = await models.user.findById(id).populate("role");

    if (user === null) {
      return res.status(401).send({ message: "Unauthorized" });
    }

    const { identifier, identifierField, identifierLabel } =
      identityHelpers.buildUserIdentityPayload(user);

    if (!identifier) {
      return res.status(401).send({
        message: "شناسه هویتی کاربر کامل نیست",
      });
    }

    if (
      appConfig.testMode &&
      !testModeHelpers.isTestNationalCodeAllowed(identifier)
    ) {
      return res.status(403).send({
        message: "Access denied in test mode",
      });
    }

    req.user = user;
    req.token = token; // Store token for logout
    req.identifier = identifier;
    req.identifierField = identifierField;
    req.identifierLabel = identifierLabel;
    next();
  } catch (error) {
    return res.status(401).send({ message: "Unauthorized" });
  }
};

export default jwt;
