// src/server/shared/lib/case.ts
// Утилиты для преобразования имен полей между snake_case (DB) и camelCase (API)

/**
 * Преобразует snake_case в camelCase
 * @example snakeToCamel('room_id') => 'roomId'
 * @example snakeToCamel('has_hood') => 'hasHood'
 */
export function snakeToCamel(str: string): string {
  return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
}

/**
 * Преобразует camelCase в snake_case
 * @example camelToSnake('roomId') => 'room_id'
 * @example camelToSnake('hasHood') => 'has_hood'
 */
export function camelToSnake(str: string): string {
  return str.replace(/([A-Z])/g, '_$1').toLowerCase();
}

/**
 * Рекурсивно преобразует все ключи объекта из snake_case в camelCase
 * Также конвертирует все объекты Date в ISO строки
 * @param obj - Исходный объект
 * @returns Новый объект с ключами в camelCase и датами в ISO формате
 */
export function mapKeysToCamel<T extends Record<string, any>>(obj: T): any {
  // Early return for null and undefined
  if (obj === null || obj === undefined) {
    return obj;
  }

  // Convert Date to ISO string
  if (obj instanceof Date) {
    return obj.toISOString();
  }

  // Return primitives as-is
  if (typeof obj !== 'object') {
    return obj;
  }

  // Handle arrays recursively
  if (Array.isArray(obj)) {
    return obj.map(item => mapKeysToCamel(item));
  }

  // Handle objects
  const result: Record<string, any> = {};
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      const camelKey = snakeToCamel(key);
      result[camelKey] = mapKeysToCamel(obj[key]);
    }
  }

  return result;
}

/**
 * Рекурсивно преобразует все ключи объекта из camelCase в snake_case
 * @param obj - Исходный объект
 * @returns Новый объект с ключами в snake_case
 */
export function mapKeysToSnake<T extends Record<string, any>>(obj: T): Record<string, any> {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }

  if (Array.isArray(obj)) {
    return obj.map(item => mapKeysToSnake(item));
  }

  const result: Record<string, any> = {};
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      const snakeKey = camelToSnake(key);
      result[snakeKey] = mapKeysToSnake(obj[key]);
    }
  }

  return result;
}
