import { Response, Request, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
import CacheClient from '../utils/cacheClient';
import { IRoleInfo, IUserDataEncrypt } from '../utils/types';

declare module 'express' {
  interface Request {
    user?: IUserDataEncrypt;
  }
}

export const authenticate = async (
  req: Request,
  res: Response,
  next: NextFunction,
) => {
  const { authorization } = req.headers;
  if (authorization) {
    const token = authorization.slice(7, authorization.length);
    const ifloggedOut = await CacheClient.get(token);
    if (ifloggedOut) {
      res
        .status(403)
        .send({ success: false, message: 'User already logged out' });
      return;
    }
    jwt.verify(token, process.env.JWT_KEY!, (err, decode) => {
      if (err) {
        res.status(403).send({ success: false, message: 'Invalid Token' });
      } else {
        req.user = decode as IUserDataEncrypt;
        next();
      }
    });
  } else {
    res.status(403).send({ success: false, message: 'No Token' });
  }
};

export const isCompany = (req: Request, res: Response, next: NextFunction) => {
  if (req.user && req.user.isCompany) {
    next();
  } else {
    res.status(403).send({ success: false, message: 'Unauthorised Access' });
  }
};

export const isRider = (req: Request, res: Response, next: NextFunction) => {
  if (req.user && req.user.userType && req.user.userType === 'rider') {
    next();
  } else {
    res.status(403).send({ success: false, message: 'Unauthorised Access' });
  }
};

export const verifyAccess = async (
  req: Request,
  ...access: string[]
): Promise<Boolean> => {
  if (req.user) {
    if (req.user.isCompany) {
      return true;
    }
    // Allow riders to view, start and stop adhocs
    if (req.user.userType.toLowerCase() === "rider") {
      const adhocsArray = ['view_adhocs', 'start_adhocs', 'end_adhocs'];
      return adhocsArray.some(item => access.includes(item));
    }
    
    const { role_id } = req.user!;
    if (role_id) {
      const { permissions } = role_id as IRoleInfo;
      if (permissions && permissions.length) {
        return access.some((key) => permissions.includes(key));
      }
    }
  }

  return false;
};
