// @ts-nocheck
const fs = require("fs");
const { v4: uuidv4 } = require("uuid");
const AppError = require("./appError");
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
const nodemailer = require('nodemailer');
const { OAuth2Client } = require('google-auth-library');
const axios = require('axios');

const authPrivateKey = process.env.JWT_SECRET;

function hideMailPartially(email) {
  const indexAt = email.charAt('@');
  const [localPart, domain] = email.split('@');
  const hiddenPart = localPart.slice(0, 2) + '*'.repeat(6) + localPart.slice(localPart.length - 2);
  return `${hiddenPart}@${domain}`;
}

function generateAccessToken(user, isRemember = false, days = undefined) {
  
  if (!days) {
    if (isRemember == undefined) {
      return jwt.sign(
        user,
        authPrivateKey,
      );
    }
    else if (isRemember == true) {
      return jwt.sign(
        user,
        authPrivateKey,
        { expiresIn: "7d" }
      );
    }
    else {
      return jwt.sign(
        user,
        authPrivateKey,
        { expiresIn: "1d" }
      );
    }
  } else {
    return jwt.sign(user, authPrivateKey, { expiresIn: days });
  }
}

const generateToken = (id) => generateAccessToken({ id: bcrypt.hashSync(id, 10) });

function authenticateToken(req, res, next) {
  // return next();
  const authHeader = req.headers["authorization"];
  const token = authHeader && authHeader.split(" ")[1];

  if (token == null) return res.sendStatus(401);

  jwt.verify(
    token,
    authPrivateKey,
    (err, user) => {
      if (err) {
        console.log(err.name);
        if (err.name == 'JsonWebTokenError') {
          return next(new AppError("Invalid Token"));
        }
        if (err.name == 'TokenExpiredError') {
          return next(new AppError("Authentication Expired! Please authenticate again!", 401));
        }
        return next(new AppError(err.message, 401));
      }
      else {
        req.user = user;
        return next();
      }
    }
  );
}

function generateOTP() {
  var OTP = Math.floor(100000 + Math.random() * 900000);
  return OTP;
}

/**
 * 
 * @param {number} bytes in byte
 * @param {number} decimals decimal points, default "2"
 * @returns would be like "5 GB"
 */
function formatBytes(bytes, decimals = 2) {
  if (!+bytes) return '0 Bytes';

  const k = 1024;
  const dm = decimals < 0 ? 0 : decimals;
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

  const i = Math.floor(Math.log(bytes) / Math.log(k));

  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
}

/**
 * optional format string ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
 * @param {string} size should be like "5 GB"
 * @returns byte
 */
function parseBytes(size) {
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
  const parts = size.split(' ');

  if (parts.length !== 2 || !sizes.includes(parts[1])) {
    throw new Error('Invalid byte format');
  }

  const sizeIndex = sizes.indexOf(parts[1]);
  const bytes = parseFloat(parts[0]) * Math.pow(1024, sizeIndex);

  return bytes;
}

function convertBytes(size, targetUnit) {
  try {
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
    const parts = size.split(' ');

    if (parts.length !== 2 || !sizes.includes(parts[1])) {
      throw new Error('Invalid byte format');
    }

    const sourceUnitIndex = sizes.indexOf(parts[1]);
    const bytes = parseFloat(parts[0]) * Math.pow(1024, sourceUnitIndex);

    if (!sizes.includes(targetUnit)) {
      throw new Error('Invalid target unit');
    }

    const targetUnitIndex = sizes.indexOf(targetUnit);
    const convertedSize = bytes / Math.pow(1024, targetUnitIndex);

    return convertedSize;
  } catch (error) {
    throw new Error('Invalid byte format');
  }
}

function getFileSizeInBytes(filename) {
  var stats = fs.statSync(filename);
  var fileSizeInBytes = stats.size;
  return fileSizeInBytes;
}

//Common Response Model
// @ts-ignore
function response(req, res, error, data, meta, statusCode) {
  if (error) {
    if (!statusCode)
      res.statusCode = RESPONSE_CODE.INTERNAL_SERVER_ERROR;
    else
      res.statusCode = statusCode;
    res.send({
      status: false,
      error: error,
      data: null,
      meta: meta,
    });
  } else {
    // if (Array.isArray(data) && data?.length == 0) {
    //   res.statusCode = RESPONSE_CODE.NO_CONTENT;
    // } else {
    //   res.statusCode = RESPONSE_CODE.OK;
    // }
    if (!statusCode)
      res.statusCode = RESPONSE_CODE.OK;
    else
      res.statusCode = statusCode;

    if (data) {
      res.send({
        status: true,
        length: data?.length,
        meta: meta,
        data: data,
      });
    } else {
      res.send({
        status: false,
        data: null,
        meta: meta,
      });
    }
  }
}

async function pagination(req) {
  let offset;
  let limit;
  let size;
  let page;
  let oldPage;

  size = parseInt(req.query?.size);
  oldPage = parseInt(req.query?.page);

  if (!size && !oldPage) {
    return {
      paginate: {},
      meta: {}
    };
  }

  if (isNaN(size)) {
    size = 10;
  }

  if (isNaN(oldPage)) {
    oldPage = 1;
  }

  if ((oldPage - 1) < 0) {
    page = 0;
  } else {
    page = oldPage - 1;
  }

  offset = page * size;
  limit = size;

  return {
    paginate: {
      offset,
      limit,
    },
    meta: {
      page: oldPage,
      size,
    }
  };
}

function passwordRegEx() {
  // return /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d\[\]?\<\>,.\!@#$%^&*]{8,}$/
  return /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d\\[\]?<>,.!@#$%^&*]{8,}$/;
}

function generatePassword(passwordLength) {
  const regex = passwordRegEx();
  const symbols = "[]?<>,.!@#$%^&*";

  let password = "";

  do {
    password = "";
    for (let i = 0; i < passwordLength; i++) {
      const charType = Math.floor(Math.random() * 4);

      switch (charType) {
        case 0:
          // Generate a random uppercase letter
          password += String.fromCharCode(Math.floor(Math.random() * 26) + 65);
          break;
        case 1:
          // Generate a random lowercase letter
          password += String.fromCharCode(Math.floor(Math.random() * 26) + 97);
          break;
        case 2:
          // Generate a random digit
          password += Math.floor(Math.random() * 10);
          break;
        case 3:
          // Generate a random symbol
          password += symbols.charAt(
            Math.floor(Math.random() * symbols.length)
          );
          break;
      }
    }
  } while (!regex.test(password) && password.length !== passwordLength);

  return password;
}

function getHoursDifferent(startDate, endDate) {
  var date1 = new Date(startDate);
  var date2 = new Date(endDate);
  return (date2.getTime() - date1.getTime()) / (1000 * 3600);
}

function getDayDifferent(startDate, endDate) {
  return getHoursDifferent(startDate, endDate) / 24;
}

function uuid() {
  return uuidv4();
}

function validateParams(req, next) {
  if (!req.params.id || !req.body) {
    return next(new AppError(AppError.NO_PARAMS, 400));
  }
  return true;
}

function validateValue(values, allowNull = false) {
  Object.keys(values).forEach((key) => {
    if (allowNull && values[key] === null) return;
    if (values[key] === undefined || !values[key]) {
      delete values[key];
    }
  });

  return values;
}

function nullValueCheck(values, allowNull = false, emptyString = false) {
  let output = [];
  Object.keys(values).forEach((key) => {
    if (emptyString && values[key] === "") return;
    if (allowNull && values[key] === null) return;
    if (values[key] === undefined || !values[key] || values[key] === "") {
      delete values[key];
    } else {
      output[key] = values[key];
    }
  });
  values = output;
  return values;
}
//Verify Token JWT
function verifyToken(req, res, next) {
  const bearerHeader = req.headers["authorization"];
  if (typeof bearerHeader !== "undefined") {
    const bearer = bearerHeader.split(" ");
    const bearerToken = bearer[1];
    req.token = bearerToken;
    next();
  } else {
    res.sendStatus(403);
  }
}

function sleep(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

async function sendSMS(number,otp) {
  
  try {
    if(!number && !otp){
      return null
    }
    const response = await axios.get(`http://vanakkamtamilan.com/submitsms.jsp?user=landcorner&key=b6a4bcee82XX&mobile=${number}&message=Your OTP is ${otp} for your mobile verification with LAND CORNER. Do not share this with anyone else.&senderid=LANDCN&accusage=1&entityid=1401616040000059114&tempid=${uuid()}`);
    console.log(response);
    return response
  } catch (error) {
    console.error(error);
  }
}

async function sendMail(toEmail, subject, planeBody, params = {}) {
  const result = new Promise((resolve, reject) => {
    try {
      const CLIENT_ID = process.env.CLIENT_ID;
      const CLIENT_SECRET = process.env.CLIENT_SECRET;
      const REFRESH_TOKEN = process.env.REFRESH_TOKEN;

      const oAuth2Client = new OAuth2Client(CLIENT_ID, CLIENT_SECRET);
      oAuth2Client.setCredentials({ refresh_token: REFRESH_TOKEN });


      const transport = nodemailer.createTransport({
        service: 'gmail',
        auth: {
          type: 'OAuth2',
          user: process.env.EMAIL_ADDRESS,
          clientId: CLIENT_ID,
          clientSecret: CLIENT_SECRET,
          refreshToken: REFRESH_TOKEN,
          accessToken: oAuth2Client.getAccessToken(),
        },
      });


      const mailOptions = {
        from: process.env.EMAIL_ADDRESS,
        to: toEmail,
        subject: subject,
        text: planeBody,
      };

      transport.sendMail({ ...mailOptions, ...params }, (error, info) => {
        if (error) {
          console.log(error);
          console.log('Error occurred while sending email:', error.message);
          reject(error);
        } else {
          console.log(info);
          console.log('Email sent successfully:', info.messageId);
          resolve(info);
        }
      });
    } catch (error) {
      reject(false);
    }
  });

  return result;
}

/**
 * It will convert buffer data into base64 image string.
 * @output data:image/gif;base64,R0lGODdhAQABAPAAAP8AAAAAACwAAAAAAQABAAACAkQBADs=
 * @example <img alt="red-dot" src="data:image/gif;base64,R0lGODdhAQABAPAAAP8AAAAAACwAAAAAAQABAAACAkQBADs=" />
 * @param {Array} image
 * @param {boolean} isMobile
 * @returns base64 string data
 */
function ConvertImageToString(image) {
  if (image === undefined || image === '') return null;
  if (image[0])
    image = image[0];
  // @ts-ignore
  var data = image?.buffer?.toString("base64");
  // @ts-ignore
  return `data:${image?.mimetype};base64,${data}`;
}

function isDateInRange(startDate, endDate, targetDate) {
  startDate = new Date(startDate);
  endDate = new Date(endDate);
  targetDate = new Date(targetDate);

  return targetDate >= startDate && targetDate <= endDate;
}

function ConvertStringToImage(base64) {
  var base64Data = base64.replace(/^data:image\/png;base64,/, "");

  let buff = Buffer.from(base64Data, 'base64');
  // require('fs').writeFileSync(`data/${products[i].br_code}.png`, buff);
  return buff.toString();
}

const RESPONSE_CODE = {
  CONTINUE: 100,
  SWITCHING_PROTOCOLS: 101,
  OK: 200,
  CREATED: 201,
  ACCEPTED: 202,
  NON_AUTHORITATIVE_INFORMATION: 203,
  NO_CONTENT: 204,
  RESET_CONTENT: 205,
  PARTIAL_CONTENT: 206,
  MULTIPLE_CHOICES: 300,
  MOVED_PERMANENTLY: 301,
  FOUND: 302,
  SEE_OTHER: 303,
  NOT_MODIFIED: 304,
  USE_PROXY: 305,
  TEMPORARY_REDIRECT: 307,
  BAD_REQUEST: 400,
  UNAUTHORIZED: 401,
  PAYMENT_REQUIRED: 402,
  FORBIDDEN: 403,
  NOT_FOUND: 404,
  METHOD_NOT_ALLOWED: 405,
  NOT_ACCEPTABLE: 406,
  PROXY_AUTHENTICATION_REQUIRED: 407,
  REQUEST_TIMEOUT: 408,
  CONFLICT: 409,
  GONE: 410,
  LENGTH_REQUIRED: 411,
  PRECONDITION_FAILED: 412,
  PAYLOAD_TOO_LARGE: 413,
  URI_TOO_LONG: 414,
  UNSUPPORTED_MEDIA_TYPE: 415,
  RANGE_NOT_SATISFIABLE: 416,
  EXPECTATION_FAILED: 417,
  UPGRADE_REQUIRED: 426,
  INTERNAL_SERVER_ERROR: 500,
  NOT_IMPLEMENTED: 501,
  BAD_GATEWAY: 502,
  SERVICE_UNAVAILABLE: 503,
  GATEWAY_TIMEOUT: 504,
  HTTP_VERSION_NOT_SUPPORTED: 505,
};

const STATUS_CODE = {
  CONTINUE: 100,
  SWITCHING_PROTOCOLS: 101,
  PROCESSING: 102,
  EARLY_HINTS: 103,
  OK: 200,
  CREATED: 201,
  ACCEPTED: 202,
  NON_AUTHORITATIVE_INFORMATION: 203,
  NO_CONTENT: 204,
  RESET_CONTENT: 205,
  PARTIAL_CONTENT: 206,
  MULTI_STATUS: 207,
  ALREADY_REPORTED: 208,
  IM_USED: 226,
  MULTIPLE_CHOICES: 300,
  MOVED_PERMANENTLY: 301,
  FOUND: 302,
  SEE_OTHER: 303,
  NOT_MODIFIED: 304,
  USE_PROXY: 305,
  TEMPORARY_REDIRECT: 307,
  PERMANENT_REDIRECT: 308,
  BAD_REQUEST: 400,
  UNAUTHORIZED: 401,
  PAYMENT_REQUIRED: 402,
  FORBIDDEN: 403,
  NOT_FOUND: 404,
  METHOD_NOT_ALLOWED: 405,
  NOT_ACCEPTABLE: 406,
  PROXY_AUTHENTICATION_REQUIRED: 407,
  REQUEST_TIMEOUT: 408,
  CONFLICT: 409,
  GONE: 410,
  LENGTH_REQUIRED: 411,
  PRECONDITION_FAILED: 412,
  PAYLOAD_TOO_LARGE: 413,
  URI_TOO_LONG: 414,
  UNSUPPORTED_MEDIA_TYPE: 415,
  RANGE_NOT_SATISFIABLE: 416,
  EXPECTATION_FAILED: 417,
  I_M_A_TEAPOT: 418,
  MISDIRECTED_REQUEST: 421,
  UNPROCESSABLE_ENTITY: 422,
  LOCKED: 423,
  FAILED_DEPENDENCY: 424,
  TOO_EARLY: 425,
  UPGRADE_REQUIRED: 426,
  PRECONDITION_REQUIRED: 428,
  TOO_MANY_REQUESTS: 429,
  REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
  UNAVAILABLE_FOR_LEGAL_REASONS: 451,
  EXPIRED: 498,
  INTERNAL_SERVER_ERROR: 500,
  NOT_IMPLEMENTED: 501,
  BAD_GATEWAY: 502,
  SERVICE_UNAVAILABLE: 503,
  GATEWAY_TIMEOUT: 504,
  HTTP_VERSION_NOT_SUPPORTED: 505,
  VARIANT_ALSE_NEGOTIATES: 506,
  INSUFFICIENT_STORAGE: 507,
  LOOP_DETECTED: 508,
  BANDWIDTH_LIMIT_EXCEEDED: 509,
  NOT_EXTENDED: 510,
  NETWORK_AUTHENTIICATION_REQUIRE: 511,
}

const RELATIONSHIP_TYPE = {
  CASCADE: "CASCADE",
  RESTRICT: "RESTRICT",
  NO_ACTION: "NO_ACTION",
  SET_NULL: "SET_NULL",
};

const ERROR_PAGE = `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Namma Soththu App API</title>
</head>
<style>
    
    body{
            background: #95b3bb;
            font-family: 'Exo 2', sans-serif;
            text-align: center;
          display:flex;
          height: 100%;
          margin: 0px;
          padding: 0px;
          position: relative;
          min-height: 100vh;
        background-color: #171c24;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='264' height='264' viewBox='0 0 800 800'%3E%3Cg fill='none' stroke='%231c212e' stroke-width='1'%3E%3Cpath d='M769 229L1037 260.9M927 880L731 737 520 660 309 538 40 599 295 764 126.5 879.5 40 599-197 493 102 382-31 229 126.5 79.5-69-63'/%3E%3Cpath d='M-31 229L237 261 390 382 603 493 308.5 537.5 101.5 381.5M370 905L295 764'/%3E%3Cpath d='M520 660L578 842 731 737 840 599 603 493 520 660 295 764 309 538 390 382 539 269 769 229 577.5 41.5 370 105 295 -36 126.5 79.5 237 261 102 382 40 599 -69 737 127 880'/%3E%3Cpath d='M520-140L578.5 42.5 731-63M603 493L539 269 237 261 370 105M902 382L539 269M390 382L102 382'/%3E%3Cpath d='M-222 42L126.5 79.5 370 105 539 269 577.5 41.5 927 80 769 229 902 382 603 493 731 737M295-36L577.5 41.5M578 842L295 764M40-201L127 80M102 382L-261 269'/%3E%3C/g%3E%3Cg fill='%232d4b4d'%3E%3Ccircle cx='769' cy='229' r='5'/%3E%3Ccircle cx='539' cy='269' r='5'/%3E%3Ccircle cx='603' cy='493' r='5'/%3E%3Ccircle cx='731' cy='737' r='5'/%3E%3Ccircle cx='520' cy='660' r='5'/%3E%3Ccircle cx='309' cy='538' r='5'/%3E%3Ccircle cx='295' cy='764' r='5'/%3E%3Ccircle cx='40' cy='599' r='5'/%3E%3Ccircle cx='102' cy='382' r='5'/%3E%3Ccircle cx='127' cy='80' r='5'/%3E%3Ccircle cx='370' cy='105' r='5'/%3E%3Ccircle cx='578' cy='42' r='5'/%3E%3Ccircle cx='237' cy='261' r='5'/%3E%3Ccircle cx='390' cy='382' r='5'/%3E%3C/g%3E%3C/svg%3E");
          /* background by SVGBackgrounds.com */
          
        }

        #container{
          align-self:center;
            padding: 0px 10px;
            position: relative;
            width: 90%;
            margin: 20px;
            box-sizing: border-box;
/*             border: 2px rgb(83, 133, 145) solid; */
            box-shadow: 0px 5px 15px -6px rgba(0,0,0,0.75);
            border-radius: 20px;
            max-width: 575px;
            margin: 10px auto;
            background: rgba(5, 13, 25, 0.569);
        }

        h1{
            font-weight:900;
            width: 100;
            margin: 10px 0px;
            color: rgb(83, 133, 145);
            letter-spacing: 5px;
            font-size: 75px;
            text-align: center;
            transform: translateY(-35px);
            text-shadow: 0px 2px 10px rgba(0, 0, 0, 0.25);
            
            
        }

        .toph h1{
            transform: translateY(20px);
            font-size: 25px;
            margin: 10px 25px;
            display: inline-block;
            font-weight:700;
          

        }
        .number{
            color:#CDC5BD;
        }

        #moon{
            position: relative;
        }

        #earth{
            position: relative;
        }

        svg{ 
            max-width: 100%;
            max-height: 65vh;
            min-height: 200px;
            margin: 0px auto;
            align-self: center;
        }
#details{
  display: flex;
  text-align: left;
  align-self:center;
  font-size: 0.9em;
}

#details span{
/*   display: block; */
  color: rgb(83, 133, 145);
  display: inline-block;
}

#details span:nth-child(odd){
  width: 150px;
  border-left: 2px solid rgb(83, 133, 145);
  padding-left: 10px;
  
}
#details span:nth-child(even){
  align-self: flex-end;
  color:#CDC5BD;
  text-align: right;
  width: 100px;
  border-right: 2px solid #CDC5BD;
  padding-right: 10px;
  
}

li{
  list-style: none;
  margin: 25px auto;
  padding:0px;
}
ul{
  margin: 0px auto;
  padding: 0px;
  padding-bottom: 25px;
}
</style>
<body>
     
    <div id="container">

        <div class="toph"><h1>ERROR </h1><h1 class="number">403</h1></div>
    
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1278 1080">
            <defs>
              <style>
                .cls-4{fill:#ff9}.cls-5{fill:#acedfc}.cls-10{fill:#68af2f}.cls-12{opacity:0.61}.cls-13{fill:#fff}.cls-16{fill:#5a5e5e}
              </style>
              <clipPath id="clip-path">
                <circle cx="604.59" cy="550.14" r="189.55" fill="none"/>
              </clipPath>
              <clipPath id="clip-path-2">
                <circle class="cls-1" cx="996" cy="319.44" r="81.34"/>
              </clipPath>
            </defs>
            <g id="Layer_2" data-name="Layer 2">
              <rect width="1278" height="1080" fill="none" id="background"/>
              <g opacity="0.85" id="stars">
                <polygon class="cls-4" points="377 296 386.19 312.81 403 322 386.19 331.19 377 348 367.81 331.19 351 322 367.81 312.81 377 296"/>
                <polygon class="cls-5" points="378.5 410 383.98 420.02 394 425.5 383.98 430.98 378.5 441 373.02 430.98 363 425.5 373.02 420.02 378.5 410"/>
                <polygon class="cls-4" points="386 713 395.19 729.81 412 739 395.19 748.19 386 765 376.81 748.19 360 739 376.81 729.81 386 713"/>
                <polygon class="cls-4" points="773 768 782.19 784.81 799 794 782.19 803.19 773 820 763.81 803.19 747 794 763.81 784.81 773 768"/>
                <polygon class="cls-5" points="498.5 785 503.27 793.73 512 798.5 503.27 803.27 498.5 812 493.73 803.27 485 798.5 493.73 793.73 498.5 785"/>
                <polygon class="cls-5" points="893 441 902.55 458.45 920 468 902.55 477.55 893 495 883.45 477.55 866 468 883.45 458.45 893 441"/>
                <polygon class="cls-5" points="615.5 784 621.69 795.31 633 801.5 621.69 807.69 615.5 819 609.31 807.69 598 801.5 609.31 795.31 615.5 784"/>
                <polygon class="cls-4" points="536 836 539.54 842.46 546 846 539.54 849.54 536 856 532.46 849.54 526 846 532.46 842.46 536 836"/>
                <polygon class="cls-4" points="818 413 821.54 419.46 828 423 821.54 426.54 818 433 814.46 426.54 808 423 814.46 419.46 818 413"/>
                <polygon class="cls-5" points="877 722 881.24 729.76 889 734 881.24 738.24 877 746 872.76 738.24 865 734 872.76 729.76 877 722"/>
                <polygon class="cls-5" points="697 822 701.24 829.76 709 834 701.24 838.24 697 846 692.76 838.24 685 834 692.76 829.76 697 822"/>
                <polygon class="cls-4" points="845 640 849.6 648.4 858 653 849.6 657.6 845 666 840.4 657.6 832 653 840.4 648.4 845 640"/>
                <polygon class="cls-4" points="284.5 503 291.04 514.96 303 521.5 291.04 528.04 284.5 540 277.96 528.04 266 521.5 277.96 514.96 284.5 503"/>
                <polygon class="cls-4" points="374.5 604 379.27 612.73 388 617.5 379.27 622.27 374.5 631 369.73 622.27 361 617.5 369.73 612.73 374.5 604"/>
                <polygon class="cls-4" points="491.5 326 496.27 334.73 505 339.5 496.27 344.27 491.5 353 486.73 344.27 478 339.5 486.73 334.73 491.5 326"/>
                <polygon class="cls-4" points="679 285 688.19 301.81 705 311 688.19 320.19 679 337 669.81 320.19 653 311 669.81 301.81 679 285"/>
                <polygon class="cls-5" points="555.5 255 559.92 263.08 568 267.5 559.92 271.92 555.5 280 551.08 271.92 543 267.5 551.08 263.08 555.5 255"/>
                <polygon class="cls-5" points="803.5 276 810.75 289.25 824 296.5 810.75 303.75 803.5 317 796.25 303.75 783 296.5 796.25 289.25 803.5 276"/>
                <polygon class="cls-4" points="933 580 940.07 592.93 953 600 940.07 607.07 933 620 925.93 607.07 913 600 925.93 592.93 933 580"/>
              </g>
              <g id="moon2">
                <circle cx="995.66" cy="319.34" r="81.34" fill="#8a9091"/>
                <circle class="cls-16" cx="986.63" cy="285.27" r="22.25"/>
                <circle class="cls-16" cx="937.96" cy="304.74" r="6.95"/>
                <circle class="cls-16" cx="969.94" cy="360.35" r="20.86"/>
                <circle class="cls-16" cx="1027.64" cy="329.07" r="11.82"/>
                <circle class="cls-16" cx="1019.3" cy="370.78" r="7.65"/>
                <circle class="cls-16" cx="1039.46" cy="285.27" r="4.17"/>
                <g clip-path="url(#clip-path-2)">
                    <circle cx="1074.12" cy="319.44" r="81.34" fill="#202121" id="moon-shadow2" opacity="0.53"/>
                  </g>
              </g>
              <g id="Layer_1-2" data-name="Layer 1">
                <g id="earth">
                  <circle cx="604.59" cy="550.14" r="189.55" fill="#25aece"/>
                  <g clip-path="url(#clip-path)">
                    <g id="land">
                      <path d="M760.55,545.48a49.08,49.08,0,0,0-11.44-14l-8.45-6.61a28.85,28.85,0,0,0-16.56-5.24l-40.6,2.06a67.06,67.06,0,0,1-18.17-2.08l-17.24-4.93a29.93,29.93,0,0,0-17.4,1.19l-33.13,14.58c-4.67,2.05-9.63,7.74-11,12.65l-8.93,31.27c-1.4,4.9.22,12,3.61,15.84L601,612.42a26.44,26.44,0,0,0,15.4,7.62s35.12-.31,36,16.45c.21,4.13-4.11,21.74-4.11,21.74.55,5.07-3.27,13.11-5.09,17.87l-3.62,16.75a12.29,12.29,0,0,0,4.36,13.86l15.71,10.64a11.61,11.61,0,0,0,14.18-1.4L732.86,656a38.46,38.46,0,0,0,8.56-15.64l5.91-26A73.46,73.46,0,0,1,754,597.3l12.75-22c2.55-4.41,2.78-11.75.5-16.31Z" fill="#7f6545"/>
                      <path d="M685.83,353.64a9.44,9.44,0,0,1-4.25,12.49s-30.64,15.32-34.35,16.25S611.68,392,611.68,392a54.09,54.09,0,0,0-16.2,8.2L583.12,410c-4,3.17-8.73,1.85-10.52-2.92l-1.83-4.89c-1.79-4.77-1.79-11.81,0-15.63s-.76-8.13-5.65-9.57l-29.49-8.67c-4.89-1.44-6.27-5.86-3.06-9.82,0,0,29.39-36.36,32.18-36.36s102,10.18,102,10.18c5.07.52,11,4.7,13.26,9.29Z" fill="#ccc6be"/>
                      <path class="cls-10" d="M480.82,357.74a27.23,27.23,0,0,0,15.27,8l32.55,3.55c5.07.55,6.66,4.3,3.54,8.33L514.8,400.07a72.64,72.64,0,0,0-8.9,16l-12.1,32.67a40.52,40.52,0,0,1-10.39,14.57l-32,26.25A65.86,65.86,0,0,0,440.53,501c-2,3.06-4,1.4-4.3-3.69l-.66-10.23A11.28,11.28,0,0,0,425.74,477l-1-.1a13.87,13.87,0,0,0-13,7.57l-.73,1.63c-2.09,4.65-4.24,4.3-4.76-.77l-7.35-70.54c-.53-5.07,1.95-12.21,5.5-15.86l52.89-54.37a8.36,8.36,0,0,1,12.51.38Z"/>
                      <path class="cls-10" d="M409.84,638.66c1.58-4.85,4.32-12.72,6.08-17.51l6.57-17.83a8.46,8.46,0,0,1,11.63-4.83l17.45,8a60,60,0,0,1,14.9,10.5l26.9,27.53c3.56,3.65,6.25,10.79,6,15.88l-.85,15.78A82.2,82.2,0,0,0,500,694.52l4.37,19.9a14,14,0,0,1-5.91,13.9l-25,15.33a12.17,12.17,0,0,1-14.37-1.79l-55.66-57.16c-3.56-3.65-5.17-10.61-3.59-15.45Z"/>
                      <path class="cls-10" d="M752.86,397.22a13.55,13.55,0,0,0-14.3-4.43L691.22,409a53.85,53.85,0,0,0-15.64,9.23l-15.92,14.43c-3.78,3.42-6.3,10.36-5.62,15.41l.28,2a14.87,14.87,0,0,1-6.8,13.78l-16.35,9.34a12.69,12.69,0,0,0-5.64,13.55l1.67,6.2c1.33,4.92,4.6,11.24,7.28,14s8.47,3,12.87.42l14.12-8.26c4.4-2.57,8.54-8.81,9.2-13.87l.38-2.94a11.94,11.94,0,0,1,10.44-9.9l5.62-.43c5.08-.39,12.25,2.18,15.93,5.71l9.8,9.41c3.68,3.53,9.56,9.45,13.06,13.15l3.93,4.15a36.59,36.59,0,0,0,15.4,8.86l48.7,11.5c5,1.17,8.9-2,8.76-7.14l-1.32-46.35a34.56,34.56,0,0,0-5.8-16.7Z"/>
                    </g>
                    <g id="clouds" opacity="0.46">
                      <g class="cls-12">
                        <path class="cls-13" d="M450.61,620.71c-23.39,10.13-31.48,29.68-18,43.44s45.19,22,70.41,18.26l21.38-3.16c25.22-3.72,25.83-12.61,1.36-19.76L510,654.9c-24.47-7.15-23.89-16.29,1.28-20.32l73.46-11.76c25.17-4,27.87-18,6-31.15l-37.28-22.34c-21.87-13.1-59.72-17.79-84.12-10.41l-35.48,10.72c-24.4,7.37-23.52,14.19,1.95,15.14l43.63,1.63c25.47,1,27.17,10,3.78,20.15Z"/>
                      </g>
                      <g class="cls-12">
                        <path class="cls-13" d="M456.63,497.79c-24.15,8.15-23.27,15.65,2,16.67s64.8-6.92,87.92-17.65l18.8-8.72c23.12-10.73,51-30.66,62-44.3s-.91-25.65-26.38-26.71l-8.42-.35C567,415.67,562,401.19,581.29,384.54l4-3.42c19.3-16.65,16.66-20.52-5.88-8.61L450.91,440.43c-22.53,11.91-20.21,23.59,5.17,26l27.28,2.54c25.38,2.36,26.38,11,2.23,19.11Z"/>
                      </g>
                      <g class="cls-12">
                        <path class="cls-13" d="M622.66,546.43C600,555.1,600.85,569.75,624.61,579l5.38,2.09c23.76,9.24,58,8.46,76.1-1.74s49.32-31.4,69.39-47.11l4-3.1c20.07-15.72,15.64-28.94-9.85-29.38l-40.8-.71c-25.49-.44-32.09-16-14.67-34.64l51.6-55.14c17.42-18.61,13.84-23-7.94-9.78L625.66,479.73c-21.79,13.23-22.09,30.11-.68,37.5S645.35,537.77,622.66,546.43Z"/>
                      </g>
                      <path class="cls-13" d="M610,774.69c-14.34,21.07-11.55,39,6.21,39.9S659,809,671.69,800.27,707,772.73,721.91,758.5s11.83-40.09-6.8-57.49l-.64-.6C695.84,683,693,659,708.27,647s7.32-17.21-17.56-11.64l-44.57,10c-24.87,5.57-30.22,17.92-11.87,27.44s21.62,34.55,7.27,55.63Z" opacity="0.63"/>
                    </g>
                  </g>
                </g>
                <g id="moon">
                  <circle cx="995.66" cy="319.34" r="81.34" fill="#8a9091"/>
                  <circle class="cls-16" cx="986.63" cy="285.27" r="22.25"/>
                  <circle class="cls-16" cx="937.96" cy="304.74" r="6.95"/>
                  <circle class="cls-16" cx="969.94" cy="360.35" r="20.86"/>
                  <circle class="cls-16" cx="1027.64" cy="329.07" r="11.82"/>
                  <circle class="cls-16" cx="1019.3" cy="370.78" r="7.65"/>
                  <circle class="cls-16" cx="1039.46" cy="285.27" r="4.17"/>
                  <g clip-path="url(#clip-path-2)">
                    <circle cx="1074.12" cy="319.44" r="81.34" fill="#202121" id="moon-shadow" opacity="0.53"/>
                  </g>
                </g>
              </g>
            </g>
          </svg>
          <h1>FORBIDDEN</h1>
          <div id="details">
            <ul>
              <li><span>AGE</span><span>4.543B</span></li>
              <li><span>POPULATION</span><span>7.53B</span></li>
              <li><span>DISTANCE FROM SUN</span><span>92.96M</span></li>
            </ul>
            
          </div>
    
          </div>
</body>
</html>`;

function passwordRegEx() {
  // return /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d\[\]?\<\>,.\!@#$%^&*]{8,}$/
  return /^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d\\[\]?<>,.!@#$%^&*]{8,}$/;
}

module.exports = {
  response,
  verifyToken,
  sleep,
  ConvertImageToString,
  ConvertStringToImage,
  uuid,
  sendMail,
  generatePassword,
  validateParams,
  validateValue,
  nullValueCheck,
  isDateInRange,
  generateAccessToken,
  generateToken,
  getHoursDifferent,
  getDayDifferent,
  authenticateToken,
  generateOTP,
  pagination,
  formatBytes,
  parseBytes,
  convertBytes,
  getFileSizeInBytes,
  ERROR_PAGE,
  RELATIONSHIP_TYPE,
  STATUS_CODE,
  hideMailPartially,
  passwordRegEx,
  sendSMS
};
