export function mockThis(input) {
  const defaultValues = {
    string: 'default string',
    number: 0,
    boolean: false,
    object: {},
    array: [],
    function: () => {}, // Default empty function
  };

  const nativeTypes = new Set([
    'Map',
    'Set',
    'WeakMap',
    'WeakSet',
    'Date',
    'RegExp',
    'ArrayBuffer',
    'SharedArrayBuffer',
    'DataView',
    'Promise',
    'Int8Array',
    'Uint8Array',
    'Uint8ClampedArray',
    'Int16Array',
    'Uint16Array',
    'Int32Array',
    'Uint32Array',
    'Float32Array',
    'Float64Array',
    'BigInt64Array',
    'BigUint64Array',
  ]);

  function getDefaultValue(value) {
    const valueType = Array.isArray(value) ? 'array' : typeof value;
    return defaultValues[valueType] !== undefined
      ? defaultValues[valueType]
      : null;
  }

  function createGenericMock() {
    return new Proxy(() => {}, {
      get(target, prop) {
        return createGenericMock();
      },
      apply() {
        return createGenericMock();
      },
    });
  }

  function mockFunction(func) {
    return new Proxy(func, {
      apply(target, thisArg, argumentsList) {
        const returnValue = target.apply(thisArg, argumentsList);
        return mockValue(returnValue);
      },
      get(target, prop) {
        return createGenericMock();
      },
    });
  }

  function mockObject(obj) {
    if (nativeTypes.has(obj.constructor.name)) {
      return obj; // Return native types without modification
    }

    return new Proxy(obj, {
      get(target, prop) {
        if (prop === 'getProvider') {
          return () => ({
            getImmediate: (arg) => {
              // Handle different argument types passed to getImmediate
              if (arg && arg.identifier === '(default)') {
                return {
                  triggerHeartbeat: () => ({
                    isInitialized: () => true,
                  }),
                };
              }
              // Return a generic mock for other cases
              return createGenericMock();
            },
          });
        }

        if (prop in target) {
          return mockValue(target[prop]);
        }
        return createGenericMock();
      },
    });
  }

  function mockValue(value) {
    if (typeof value === 'function') {
      return mockFunction(value);
    } else if (typeof value === 'object' && value !== null) {
      return mockObject(value);
    } else {
      return getDefaultValue(value);
    }
  }

  return mockValue(input);
}

export default mockThis;
