// Zależności
import jwt from 'jsonwebtoken'
import { encrypt, setBase64, getBase64 } from '@contentpi/lib'

// Konfiguracja
import { $security } from '../../config'

// Interfejs
import { IUser } from '../types'

const { secretKey } = $security

export function jwtVerify(accessToken: string, cb: any): void {
  // Sprawdzanie, czy token JWT używa atrybutów accessToken i secretKey
  jwt.verify(
    accessToken,
    secretKey,
    (error: any, accessTokenData: any = {}) => {
      const { data: user } = accessTokenData

      // Jeśli wystąpi błąd lub użytkownik nie zostanie znaleziony, zwracana jest wartość false
      if (error || !user) {
        return cb(false)
      }

      // Dane o użytkowniku bazują na kodowaniu base64, a funkcja getBase64 uzyska informacje jako obiekt JSON

      const userData = getBase64(user)

      return cb(userData)
    }
  )
}

export async function getUserData(accessToken: string): Promise<any> {
  // Określana jest wartość obiektu Promise funkcji jwtVerify w celu uzyskania danych o użytkowniku
  const UserPromise = new Promise(resolve =>
    jwtVerify(accessToken, (user: any) => resolve(user))
  )

  // Umożliwia uzyskanie danych o użytkowniku lub zwrócenie wartości false (jeśli użytkownik nie jest połączony)
  const user = await UserPromise

  return user
}

export const createToken = async (user: IUser): Promise<string[]> => {
  // Wyodrębnianie danych o użytkowniku
  const { id, username, password, email, privilege, active } = user

  // Szyfrowanie hasła przez połączenie go z atrybutem secretKey i przekształcanie hasła do formatu kodowania base64

  const token = setBase64(`${encrypt($security.secretKey)}${password}`)

  // W tym wypadku token to alias hasła
  const userData = {
    id,
    username,
    email,
    privilege,
    active,
    token
  }

  // Logowanie za pomocą tokenu JWT i przekazywanie czasu ważności, który wynosi 7 dni w użytej konfiguracji
    const _createToken = jwt.sign(
    { data: setBase64(userData) },
    $security.secretKey,
    { expiresIn: $security.expiresIn }
  )

  return Promise.all([_createToken])
}
