import React, { useMemo, useCallback, useRef, useEffect } from 'react';

export interface MemoizedOptions<T> {
  value: T;
  dependencies?: React.DependencyList;
  maxAge?: number;
}

export function useMemoizedValue<T>(value: T, dependencies?: React.DependencyList): T {
  const cache = useRef<{ value: T; dependencies?: React.DependencyList }>({
    value,
    dependencies,
  });

  if (dependencies) {
    const depsChanged = !cache.current.dependencies || 
      dependencies.some((dep, i) => !Object.is(dep, cache.current.dependencies?.[i]));
    
    if (depsChanged) {
      cache.current = { value, dependencies };
    }
    return cache.current.value;
  }

  return value;
}

export function useMemoizedCallback<T extends (...args: any[]) => any>(
  callback: T,
  dependencies?: React.DependencyList
): T {
  const callbackRef = useRef(callback);
  const dependenciesRef = useRef<React.DependencyList | undefined>(dependencies);

  if (dependencies) {
    const depsChanged = !dependenciesRef.current ||
      dependencies.some((dep, i) => !Object.is(dep, dependenciesRef.current?.[i]));
    
    if (depsChanged) {
      callbackRef.current = callback;
      dependenciesRef.current = dependencies;
    }
  }

  return useCallback(
    ((...args: Parameters<T>) => callbackRef.current(...args)) as T,
    []
  );
}

export function createMemoizedComponent<P extends object>(
  Component: React.ComponentType<P>,
  propsToCompare: (keyof P)[]
): React.MemoExoticComponent<React.ComponentType<P>> {
  return React.memo(
    Component as React.ComponentType<P>,
    (prevProps, nextProps) => {
      return propsToCompare.every(key => 
        Object.is(prevProps[key], nextProps[key])
      );
    }
  );
}

export default useMemoizedValue;
