'use client';

import { useState, useEffect, useCallback, useRef } from 'react';
import { findTargetElements, getElementBorderRadius } from '../utils/dom';
import { scrollToElement } from '../utils/scrollIntoView';
import type { SpotlightTarget } from '../types';

interface UseStepTargetOptions {
  scrollToTarget?: boolean;
  scrollBehavior?: ScrollBehavior;
  spotlightPadding?: number;
}

interface UseStepTargetReturn {
  targets: SpotlightTarget[];
  isReady: boolean;
}

/**
 * Hook to track target elements for current tour step.
 * Handles scroll, resize, and DOM mutations.
 */
export function useStepTarget(
  target: string | undefined,
  stepId: string | undefined,
  options: UseStepTargetOptions = {}
): UseStepTargetReturn {
  const {
    scrollToTarget = true,
    scrollBehavior = 'smooth',
    spotlightPadding = 8,
  } = options;

  const [targets, setTargets] = useState<SpotlightTarget[]>([]);
  const [isReady, setIsReady] = useState(false);
  const hasScrolledRef = useRef(false);
  const updateTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  const updateTargets = useCallback(() => {
    if (!stepId) {
      setTargets([]);
      setIsReady(false);
      return;
    }

    const elements = findTargetElements(target, stepId);
    if (elements.length === 0) {
      setTargets([]);
      setIsReady(false);
      return;
    }

    const newTargets: SpotlightTarget[] = elements.map((element) => ({
      element,
      rect: element.getBoundingClientRect(),
      padding: spotlightPadding,
      radius: getElementBorderRadius(element),
    }));

    setTargets(newTargets);
    setIsReady(true);

    // Scroll to first target on initial render
    if (scrollToTarget && !hasScrolledRef.current && elements[0]) {
      scrollToElement(elements[0], scrollBehavior);
      hasScrolledRef.current = true;
    }
  }, [target, stepId, scrollToTarget, scrollBehavior, spotlightPadding]);

  // Debounced update for performance
  const debouncedUpdate = useCallback(() => {
    if (updateTimeoutRef.current) {
      clearTimeout(updateTimeoutRef.current);
    }
    updateTimeoutRef.current = setTimeout(updateTargets, 16);
  }, [updateTargets]);

  // Reset scroll flag when step changes
  useEffect(() => {
    hasScrolledRef.current = false;
  }, [stepId]);

  // Initial update and event listeners
  useEffect(() => {
    if (!stepId) return;

    // Initial update
    updateTargets();

    // Resize listener
    window.addEventListener('resize', debouncedUpdate);

    // Scroll listener (capture phase to catch all scrolls)
    window.addEventListener('scroll', debouncedUpdate, true);

    // Mutation observer for DOM changes
    const observer = new MutationObserver(debouncedUpdate);
    observer.observe(document.body, {
      childList: true,
      subtree: true,
      attributes: true,
      attributeFilter: ['style', 'class'],
    });

    // ResizeObserver for element size changes
    const resizeObserver = new ResizeObserver(debouncedUpdate);
    resizeObserver.observe(document.body);

    return () => {
      window.removeEventListener('resize', debouncedUpdate);
      window.removeEventListener('scroll', debouncedUpdate, true);
      observer.disconnect();
      resizeObserver.disconnect();
      if (updateTimeoutRef.current) {
        clearTimeout(updateTimeoutRef.current);
      }
    };
  }, [stepId, updateTargets, debouncedUpdate]);

  return { targets, isReady };
}
