import { isDevMode } from '@angular/core';

export const log = (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
  if (!isDevMode()) {
    return descriptor;
  }

  // log the function name the input and return value

  // get the function that is being decorated
  const originalMethod = descriptor.value;

  // replace the function being decorated with a new function
  descriptor.value = function (...args: any[]) {
    const now = Date.now();
    let result;
    console.groupCollapsed(`Method: ${propertyKey}`);

    // log the input
    console.log(`args:`, args);

    try {
      // call the original function
      result = originalMethod.apply(this, args);

      // log the output
      console.log(`returned:`, result);

      // return the result of calling the original method
    } catch (error) {
      console.error(`error:`, error);

      throw error;
    }

    console.log(`execution time in ms:`, Date.now() - now);
    console.groupEnd();

    return result;
  };

  // return the descriptor
  return descriptor;
};

export const logAsync = (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
  if (!isDevMode()) {
    return descriptor;
  }

  // log the function name the input and return value

  // get the function that is being decorated
  const originalMethod = descriptor.value;

  // replace the function being decorated with a new function
  descriptor.value = async function (...args: any[]) {
    const now = Date.now();
    let result;
    console.group(`Method: ${propertyKey}`);

    // log the input
    console.log(`args:`, args);

    try {
      // call the original function
      result = await originalMethod.apply(this, args);

      // log the output
      console.log(`returned:`, result);

      // return the result of calling the original method
    } catch (error) {
      console.error(`error: ${error}`);

      throw error;
    }

    console.log(`execution time in ms:`, Date.now() - now);
    console.groupEnd();

    return result;
  };

  // return the descriptor
  return descriptor;
};
