import { identity } from '../../function/identity.ts';
import { mapKeys as mapKeysToolkit } from '../../object/mapKeys.ts';
import { ListIteratee } from '../_internal/ListIteratee.ts';
import { ObjectIteratee } from '../_internal/ObjectIteratee.ts';
import { iteratee } from '../util/iteratee.ts';

/**
 * Creates an object with the same values as `object` and keys generated by running each own enumerable string keyed property through `iteratee`.
 *
 * @template T
 * @param object - The object to iterate over.
 * @param [iteratee] - The function invoked per iteration.
 * @returns Returns the new mapped object.
 *
 * @example
 * mapKeys([1, 2, 3], (value, index) => `key${index}`);
 * // => { 'key0': 1, 'key1': 2, 'key2': 3 }
 */
export function mapKeys<T>(object: ArrayLike<T> | null | undefined, iteratee?: ListIteratee<T>): Record<string, T>;

/**
 * Creates an object with the same values as `object` and keys generated by running each own enumerable string keyed property through `iteratee`.
 *
 * @template T
 * @param object - The object to iterate over.
 * @param [iteratee] - The function invoked per iteration.
 * @returns Returns the new mapped object.
 *
 * @example
 * mapKeys({ a: 1, b: 2 }, (value, key) => key + value);
 * // => { 'a1': 1, 'b2': 2 }
 */
export function mapKeys<T extends object>(
  object: T | null | undefined,
  iteratee?: ObjectIteratee<T>
): Record<string, T[keyof T]>;

/**
 * Creates a new object with the same values as the given object, but with keys generated
 * by running each own enumerable property of the object through the iteratee function.
 *
 * @template T - The type of the object.
 * @template K1 - The type of the keys in the object.
 * @template K2 - The type of the new keys generated by the iteratee function.
 *
 * @param object - The object to iterate over.
 * @param [getNewKey] - The function invoked per own enumerable property, or a path to generate new keys.
 * @returns Returns the new mapped object.
 *
 * @example
 * // Example usage:
 * const obj = { a: 1, b: 2 };
 * const result = mapKeys(obj, (value, key) => key + value);
 * console.log(result); // { a1: 1, b2: 2 }
 */
export function mapKeys(object: any, getNewKey: ListIteratee<any> = identity): Record<string, any> {
  if (object == null) {
    return {};
  }

  return mapKeysToolkit(object, iteratee(getNewKey));
}
