import jwt from 'jsonwebtoken';
import NodeCache from 'node-cache';
import { Info, IRoutePayLoad, IUserData } from './types';

export class CacheClient {
  client: NodeCache;

  constructor() {
    this.client = new NodeCache();
  }

  async set(token: string, time: number) {
    return this.client.set(token, true, time);
  }

  async get(token: string) {
    return this.client.get(token);
  }
}

export const generateToken = (payload: IUserData) => {
  const pass = process.env.JWT_KEY!;
  return jwt.sign(payload, pass, { expiresIn: process.env.JWT_EXPIRES_IN! });
};

export const generatePasswordResetCode = () => Math.floor(Math.random() * (10000 - 1000) + 1000);

export const orderToken = (user: IUserData) => {
  const { _id, company_id, firstName, lastName, isCompany, userType, email } =
    user;
  const payload = {
    _id,
    company_id,
    firstName,
    lastName,
    isCompany,
    userType,
    email,
  };
  const pass = process.env.JWT_ORDER_KEY!;
  return jwt.sign(payload, pass, {
    expiresIn: process.env.JWT_ORDER_EXPIRES_IN!,
  });
};

export const mailVerificationToken = (payload: Info) => {
  const pass = process.env.JWT_KEY!;
  return jwt.sign(payload, pass, {
    expiresIn: process.env.JWT_MAIL_TOKEN_EXPIRATION!,
  });
};

export const verifyToken = async (payload: string) => {
  const pass = process.env.JWT_KEY!;
  return new Promise((resolve, reject) => {
    jwt.verify(payload, pass, (error, decode) => {
      if (error) reject(error);
      resolve(decode);
    });
  });
};

export const getOrderCount = ({
  startPoint,
  checkPoints,
  endPoint,
}: IRoutePayLoad) => {
  const checkPointIds = checkPoints
    .map((location) =>
      location.orderInfo
        ? location.orderInfo.map((order) => order.orderId)
        : [],
    )
    .flat()
    .filter(Boolean);

  const startPointId = startPoint.orderInfo
    ? startPoint.orderInfo
        .map((order) => order.orderId)
        .flat()
        .filter(Boolean)
    : [];

  const endPointId =
    endPoint && endPoint.orderInfo
      ? endPoint.orderInfo
          .map((order) => order.orderId)
          .flat()
          .filter(Boolean)
      : [];

  return checkPointIds.concat(startPointId, endPointId).length;
};
