// src/utils/domUtils.js
// DOM 요소 관련 유틸리티 함수들 (크로미움68 호환)

/**
 * 특정 spotlight-id를 가진 요소를 재시도 메커니즘과 함께 찾습니다.
 * @param {string} spotlightId - 찾을 spotlight id
 * @param {number} maxRetries - 최대 재시도 횟수
 * @param {number} interval - 재시도 간격 (ms)
 * @returns {Promise<Element|null>} 찾은 DOM 요소 또는 null
 */
export const findElementWithRetry = (spotlightId, maxRetries = 10, interval = 100) => {
  return new Promise((resolve) => {
    let attempts = 0;
    
    const checkElement = () => {
      const selector = `[data-spotlight-id="${spotlightId}"]`;
      const element = document.querySelector(selector);
      
      if (element) {
        resolve(element);
        return;
      }
      
      attempts++;
      if (attempts < maxRetries) {
        setTimeout(checkElement, interval);
      } else {
        console.warn(`[domUtils] Element not found after ${maxRetries} attempts: ${selector}`);
        resolve(null);
      }
    };
    
    checkElement();
  });
};

/**
 * DOM 요소의 위치와 크기 정보를 안전하게 가져옵니다.
 * @param {Element} element - 위치를 계산할 DOM 요소
 * @returns {Object|null} 위치 정보 객체 또는 null
 */
export const getElementPosition = (element) => {
  if (!element) {
    return null;
  }
  
  try {
    const rect = element.getBoundingClientRect();
    return {
      width: rect.width,
      height: rect.height,
      top: rect.top,
      left: rect.left,
      right: rect.right,
      bottom: rect.bottom,
    };
  } catch (error) {
    console.error('[domUtils] Error getting element position:', error);
    return null;
  }
};

/**
 * spotlight-id로 요소를 찾고 위치 정보를 반환합니다.
 * @param {string} spotlightId - 찾을 spotlight id
 * @param {number} maxRetries - 최대 재시도 횟수
 * @param {number} interval - 재시도 간격 (ms)
 * @returns {Promise<Object|null>} 위치 정보 객체 또는 null
 */
export const getElementPositionById = async (spotlightId, maxRetries = 10, interval = 100) => {
  const element = await findElementWithRetry(spotlightId, maxRetries, interval);
  return getElementPosition(element);
};

/**
 * 모달 스타일 객체를 생성합니다.
 * @param {Object} position - 위치 정보 객체
 * @param {number} scale - 스케일 값 (선택적)
 * @returns {Object} 모달 스타일 객체
 */
export const createModalStyle = (position, scale = 1) => {
  if (!position) {
    return {};
  }
  
  return {
    width: position.width + "px",
    height: position.height + "px",
    top: position.top + "px", 
    left: position.left + "px",
    position: "fixed",
    overflow: "visible",
    transform: scale !== 1 ? `scale(${scale})` : undefined,
  };
};

/**
 * 배너별 기본 위치 정보를 반환합니다. (fallback용)
 * @param {string} bannerId - 배너 ID (banner0, banner1, etc.)
 * @returns {Object} 기본 위치 정보
 */
export const getDefaultBannerPosition = (bannerId) => {
  const defaultPositions = {
    banner0: { width: 640, height: 360, top: 100, left: 100 },
    banner1: { width: 640, height: 360, top: 100, left: 760 },
    banner2: { width: 640, height: 360, top: 500, left: 100 },
    banner3: { width: 640, height: 360, top: 500, left: 760 },
  };
  
  return defaultPositions[bannerId] || defaultPositions.banner0;
};

/**
 * 모든 배너의 위치 정보를 수집합니다.
 * @param {Array<string>} bannerIds - 수집할 배너 ID 배열
 * @returns {Promise<Object>} 배너별 위치 정보 맵
 */
export const collectBannerPositions = async (bannerIds = ['banner0', 'banner1', 'banner2', 'banner3']) => {
  const positions = {};
  
  for (const bannerId of bannerIds) {
    const position = await getElementPositionById(bannerId, 5, 50); // 빠른 수집
    if (position) {
      positions[bannerId] = position;
    } else {
      // fallback 위치 사용
      positions[bannerId] = getDefaultBannerPosition(bannerId);
      console.warn(`[domUtils] Using fallback position for ${bannerId}`);
    }
  }
  
  return positions;
};

/**
 * 크로미움68 호환 - Optional Chaining 대신 안전한 객체 접근
 * @param {Object} obj - 접근할 객체
 * @param {string} path - 접근 경로 (예: 'a.b.c')
 * @param {*} defaultValue - 기본값
 * @returns {*} 값 또는 기본값
 */
export const safeGet = (obj, path, defaultValue = null) => {
  try {
    const keys = path.split('.');
    let result = obj;
    
    for (const key of keys) {
      if (result === null || result === undefined) {
        return defaultValue;
      }
      result = result[key];
    }
    
    return result !== undefined ? result : defaultValue;
  } catch (error) {
    return defaultValue;
  }
};
