/**
 * Creates a model object by deep-picking only the keys defined in `defaults`
 * from `source`. Keys not present in `source` keep their default value.
 *
 * Safe alternative to spread: never leaks extra properties from `source`,
 * even in nested objects or arrays of objects.
 *
 * Supported structures:
 * - Primitives (`string`, `number`, `boolean`)
 * - Nested objects (recursed with their own defaults template)
 * - Arrays of primitives (shallow-copied from source)
 * - Arrays of objects (each item recursed using `defaults[0]` as template)
 *
 * @example
 * ```ts
 * // Flat
 * pickModel(item, { id: '', name: '' });
 *
 * // Nested object
 * pickModel(item, { id: '', address: { street: '', city: '' } });
 *
 * // Array of objects
 * pickModel(item, { id: '', lines: [{ product: '', qty: 0 }] });
 *
 * // Combined
 * pickModel(item, {
 *   id: '',
 *   customer: { name: '', contact: { email: '', phone: '' } },
 *   lines: [{ product: '', tags: [''] }],
 * });
 * ```
 */
export function pickModel<T extends Record<string, unknown>>(source: unknown, defaults: T): T {
  if (!source || typeof source !== 'object') return structuredClone(defaults);

  const src = source as Record<string, unknown>;
  const result = {} as Record<string, unknown>;

  for (const key in defaults) {
    const defaultVal = defaults[key];
    const sourceVal = key in src ? src[key] : undefined;

    if (sourceVal === undefined || sourceVal === null) {
      result[key] = structuredClone(defaultVal);
    } else if (Array.isArray(defaultVal) && Array.isArray(sourceVal)) {
      const template = defaultVal[0];
      if (isPlainObject(template)) {
        result[key] = sourceVal.map((item) => pickModel(item, template));
      } else {
        result[key] = [...sourceVal];
      }
    } else if (isPlainObject(defaultVal) && isPlainObject(sourceVal)) {
      result[key] = pickModel(sourceVal, defaultVal);
    } else {
      result[key] = sourceVal;
    }
  }

  return result as T;
}

function isPlainObject(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null && !Array.isArray(value);
}
