// spotlight-utils.js
import {getTargetByContainer} from '@enact/spotlight/src/target';
import {getTargetBySelector} from '@enact/spotlight/src/target';
import {getContainerConfig} from '@enact/spotlight/src/container';
import {isContainer, getContainerId} from '@enact/spotlight/src/container';
import {getContainersForNode} from '@enact/spotlight/src/container';
import {isNavigable} from '@enact/spotlight/src/container';
import {setLastContainer} from '@enact/spotlight/src/container';
import Spotlight from '@enact/spotlight';

// lodash 없이 last 함수 직접 구현
const last = (array) => {
  return array && array.length > 0 ? array[array.length - 1] : undefined;
};

// focusElement 함수는 spotlight 내부 함수이므로, 직접 구현하거나 spotlight의 focus를 사용
const focusElement = (target, containerIds) => {
  console.log("focusElement called with:", target, containerIds);
  if (target && typeof target.focus === 'function') {
    try {
      target.focus();
      return true;
    } catch (e) {
      console.error("Focus failed:", e);
      return false;
    }
  }
  return false;
};

/**
 * Predicts which element would be focused by Spotlight.focus() without actually
 * changing the focus.
 *
 * @param {String|Node} [elem] The spotlight ID or selector for either a spottable
 * component or a spotlight container, or spottable node. If not supplied, the default
 * container's target will be used.
 * @returns {Node|null} The DOM element that would be focused, or null if no
 * navigable target is found.
 */
export const getPredictedFocus = (elem) => {
    let target = elem;
  
    if (!elem) {
      target = getTargetByContainer();
    } else if (typeof elem === 'string') {
      if (getContainerConfig(elem)) {
        // String is a container ID
        target = getTargetByContainer(elem);
      } else if (/^[\w\d-]+$/.test(elem)) {
        // Support component IDs consisting of alphanumeric, dash, or underscore
        target = getTargetBySelector(`[data-spotlight-id=${elem}]`);
      } else {
        // Treat as a CSS selector
        target = getTargetBySelector(elem);
      }
    } else if (isContainer(elem)) {
      // elem is a container element
      target = getTargetByContainer(getContainerId(elem));
    }
  
    // Check navigability without attempting to focus
    const nextContainerIds = getContainersForNode(target);
    const nextContainerId = last(nextContainerIds);
  
    if (isNavigable(target, nextContainerId, true)) {
      return target;
    }
  
    return null;
  };

// 메인 focus 함수
export const focus = (elem) => {
  console.log("focus test", elem);
  var target = elem;
  var wasContainerId = false;

  if (!elem) {
    // elem이 없으면 기본 컨테이너의 타겟을 가져옴
    target = getTargetByContainer();
  } else if (typeof elem === 'string') {
    if (getContainerConfig(elem)) {
      // 문자열이 컨테이너 ID인 경우
      target = getTargetByContainer(elem);
      wasContainerId = true;
    } else if (/^[\w\d-]+$/.test(elem)) {
      // 알파벳, 숫자, 대시, 언더스코어로 구성된 컴포넌트 ID 지원
      target = getTargetBySelector("[data-spotlight-id=".concat(elem, "]"));
    } else {
      // CSS 셀렉터로 처리
      target = getTargetBySelector(elem);
    }
  } else if (isContainer(elem)) {
    // elem이 컨테이너 요소인 경우
    target = getTargetByContainer(getContainerId(elem));
  }

  // 타겟 노드의 컨테이너들을 가져옴
  var nextContainerIds = getContainersForNode(target);
  var nextContainerId = last(nextContainerIds); // 마지막 컨테이너 ID

  if (isNavigable(target, nextContainerId, true)) {
    // 네비게이션 가능한 경우 포커스 설정
    var focused = focusElement(target, nextContainerIds);

    if (!focused && wasContainerId) {
      // 포커스 실패했지만 컨테이너 ID였던 경우 마지막 컨테이너로 설정
      setLastContainer(elem);
    }

    return focused;
  } else if (wasContainerId) {
    // 제공된 컨테이너 내에서 spottable 타겟을 찾지 못한 경우
    // 내용이 변경될 때 자체적으로 포커스할 수 있도록 활성 컨테이너로 설정
    setLastContainer(elem);
  }

  return false;
};

// spotlight-utils.js에 추가할 함수

/**
 * spotlightId로 직접 포커스를 설정하는 함수
 * 
 * @param {String} spotlightId - data-spotlight-id 속성값
 * @param {Boolean} force - 강제 포커스 여부 (기본값: false)
 * @returns {Boolean} 포커스 성공 여부
 */
export const focusById = (spotlightId, force = false) => {
    // spotlightId 유효성 검사
    if (!spotlightId || typeof spotlightId !== 'string') {
      console.error('[focusById] spotlightId는 반드시 문자열이어야 합니다.');
      return false;
    }
  
    try {
      // data-spotlight-id 속성을 가진 요소 직접 검색
      const targetElement = document.querySelector(`[data-spotlight-id="${spotlightId}"]`);
      
      if (!targetElement) {
        console.warn(`[focusById] spotlightId "${spotlightId}"를 가진 요소를 찾을 수 없습니다.`);
        return false;
      }
  
      // 요소가 현재 보이고 활성화되어 있는지 확인
      if (!isElementVisible(targetElement)) {
        console.warn(`[focusById] 요소 "${spotlightId}"가 보이지 않거나 비활성화되어 있습니다.`);
        if (!force) return false;
      }
  
      // Spotlight의 isSpottable로 포커스 가능 여부 확인
      if (typeof Spotlight !== 'undefined' && Spotlight.isSpottable) {
        if (!Spotlight.isSpottable(targetElement) && !force) {
          console.warn(`[focusById] 요소 "${spotlightId}"가 현재 spottable하지 않습니다.`);
          return false;
        }
      }
  
      // 직접 DOM 포커스 시도
      if (force) {
        // 강제 모드: DOM focus() 직접 호출
        console.log(`[focusById] 강제 포커스 모드: "${spotlightId}"`);
        targetElement.focus();
        return true;
      } else {
        // 일반 모드: Spotlight 시스템 사용
        console.log(`[focusById] Spotlight 포커스: "${spotlightId}"`);
        
        // Spotlight.focus() 사용 (선택자 형태로 전달)
        const focusResult = focus(`[data-spotlight-id="${spotlightId}"]`);
        
        if (!focusResult) {
          // Spotlight 포커스 실패 시 직접 포커스 시도
          console.log(`[focusById] Spotlight 포커스 실패, 직접 포커스 시도: "${spotlightId}"`);
          targetElement.focus();
          return document.activeElement === targetElement;
        }
        
        return focusResult;
      }
  
    } catch (error) {
      console.error(`[focusById] 포커스 설정 중 오류 발생: "${spotlightId}"`, error);
      return false;
    }
  };
  
  /**
   * 요소가 보이고 포커스 가능한 상태인지 확인하는 헬퍼 함수
   * 
   * @param {Element} element - 확인할 DOM 요소
   * @returns {Boolean} 요소의 가시성 및 활성화 상태
   */
  const isElementVisible = (element) => {
    if (!element) return false;
    
    // 요소가 DOM에 연결되어 있는지 확인
    if (!element.isConnected) return false;
    
    // disabled 속성 확인
    if (element.disabled) return false;
    
    // display: none 또는 visibility: hidden 확인
    const style = window.getComputedStyle(element);
    if (style.display === 'none' || style.visibility === 'hidden') return false;
    
    // opacity가 0인지 확인
    if (parseFloat(style.opacity) === 0) return false;
    
    // 요소의 크기가 0인지 확인
    const rect = element.getBoundingClientRect();
    if (rect.width === 0 && rect.height === 0) return false;
    
    return true;
  };
  
  /**
   * 현재 포커스된 요소의 spotlightId를 반환하는 헬퍼 함수
   * 
   * @returns {String|null} 현재 포커스된 요소의 spotlightId 또는 null
   */
  export const getCurrentSpotlightId = () => {
    const current = document.activeElement;
    if (current && current.hasAttribute('data-spotlight-id')) {
      return current.getAttribute('data-spotlight-id');
    }
    return null;
  };
  
  /**
   * 특정 spotlightId를 가진 요소가 현재 포커스되어 있는지 확인하는 함수
   * 
   * @param {String} spotlightId - 확인할 spotlightId
   * @returns {Boolean} 해당 요소가 현재 포커스되어 있는지 여부
   */
  export const isCurrentlyFocused = (spotlightId) => {
    return getCurrentSpotlightId() === spotlightId;
  };