import { useCallback, useEffect, useRef, useState } from 'react';

interface SectionInfo {
  id: string; // aria-label
  top: number; // iframe内での絶対位置 (px)
  height: number; // セクションの実際の高さ (px)
  bottom: number; // top + height (px)
}

interface CardAlignment {
  sectionId: string; // 対応するセクションID
  translateY: number; // transform値 (px)
  visible: boolean; // 表示制御フラグ
}

interface UsePreciseSectionAlignmentOptions {
  enabled?: boolean; // フック有効化フラグ
  debounceMs?: number; // デバウンス時間 (デフォルト: 150ms)
  offsetTop?: number; // 追加オフセット (デフォルト: 0px)
}

interface UsePreciseSectionAlignmentReturn {
  iframeRef: React.RefObject<HTMLIFrameElement | null>;
  sectionInfos: SectionInfo[];
  cardAlignments: CardAlignment[];
  isReady: boolean;
  updatePositions: () => void;
  error: Error | null;
}

// デバウンス関数
function debounce<T extends (...args: any[]) => any>(func: T, wait: number): (...args: Parameters<T>) => void {
  let timeout: NodeJS.Timeout | null = null;

  return (...args: Parameters<T>) => {
    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(() => func(...args), wait);
  };
}

export function usePreciseSectionAlignment(options: UsePreciseSectionAlignmentOptions = {}): UsePreciseSectionAlignmentReturn {
  const { enabled = true, debounceMs = 150, offsetTop = 0 } = options;

  const iframeRef = useRef<HTMLIFrameElement>(null);

  const [sectionInfos, setSectionInfos] = useState<SectionInfo[]>([]);
  const [cardAlignments, setCardAlignments] = useState<CardAlignment[]>([]);
  const [isReady, setIsReady] = useState(false);
  const [error, setError] = useState<Error | null>(null);

  // Observer refs
  const mutationObserverRef = useRef<MutationObserver | null>(null);
  const resizeObserverRef = useRef<ResizeObserver | null>(null);
  const retryTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  // iframe内セクション位置を測定
  const measureSectionPositions = useCallback((): SectionInfo[] => {
    if (!iframeRef.current?.contentDocument) {
      console.warn('[PreciseSectionAlignment] iframe document not available');
      return [];
    }

    try {
      const iframeDoc = iframeRef.current.contentDocument;
      const iframeWindow = iframeRef.current.contentWindow;

      if (!iframeWindow) {
        console.warn('[PreciseSectionAlignment] iframe window not available');
        return [];
      }

      const sections = iframeDoc.querySelectorAll('section[aria-label]');

      if (sections.length === 0) {
        console.warn('[PreciseSectionAlignment] No sections found in iframe');
        return [];
      }

      const infos: SectionInfo[] = [];

      // iframe自体のビューポート情報を取得
      const iframeRect = iframeRef.current.getBoundingClientRect();

      sections.forEach((section) => {
        const ariaLabel = section.getAttribute('aria-label');
        if (!ariaLabel) return;

        // 方法1: offsetTopを使用（より信頼性が高い）
        const offsetTop = (section as HTMLElement).offsetTop;
        const offsetHeight = (section as HTMLElement).offsetHeight;

        // 方法2: getBoundingClientRectとscrollTopを組み合わせる（フォールバック）
        const rect = section.getBoundingClientRect();
        const scrollTop = iframeWindow.pageYOffset || iframeDoc.documentElement.scrollTop || iframeDoc.body.scrollTop || 0;

        // offsetTopが有効な場合はそれを使用、そうでなければgetBoundingClientRectから計算
        const top = offsetTop > 0 ? offsetTop : rect.top + scrollTop;
        const height = offsetHeight > 0 ? offsetHeight : rect.height;

        console.log(`[PreciseSectionAlignment] Section "${ariaLabel}":`, {
          offsetTop,
          offsetHeight,
          rectTop: rect.top,
          rectHeight: rect.height,
          scrollTop,
          calculatedTop: top,
          calculatedHeight: height,
          iframeViewportTop: iframeRect.top,
        });

        infos.push({
          id: ariaLabel,
          top: top,
          height: height,
          bottom: top + height,
        });
      });

      console.log('[PreciseSectionAlignment] Measured sections:', infos);
      return infos;
    } catch (err) {
      console.error('[PreciseSectionAlignment] Error measuring sections:', err);
      setError(err as Error);
      return [];
    }
  }, []);

  // カード配置位置を計算
  const calculateCardAlignments = useCallback(
    (sections: SectionInfo[]): CardAlignment[] => {
      return sections.map((section) => ({
        sectionId: section.id,
        translateY: section.top + offsetTop, // iframe内セクション位置に直接対応 + オフセット
        visible: true,
      }));
    },
    [offsetTop],
  );

  // 位置を更新
  const updatePositions = useCallback(() => {
    if (!enabled) return;

    const sections = measureSectionPositions();
    if (sections.length > 0) {
      setSectionInfos(sections);
      const alignments = calculateCardAlignments(sections);
      setCardAlignments(alignments);
      setIsReady(true);
      setError(null);

      console.log('[PreciseSectionAlignment] Updated positions:', {
        sectionCount: sections.length,
        alignments: alignments,
      });
    }
  }, [enabled, measureSectionPositions, calculateCardAlignments]);

  // デバウンス付き更新
  const debouncedUpdatePositions = useCallback(debounce(updatePositions, debounceMs), [updatePositions, debounceMs]);

  // Observer設定
  const setupObservers = useCallback(() => {
    if (!iframeRef.current?.contentDocument || !enabled) return;

    const iframeDoc = iframeRef.current.contentDocument;

    // 既存のObserverをクリーンアップ
    if (mutationObserverRef.current) {
      mutationObserverRef.current.disconnect();
    }
    if (resizeObserverRef.current) {
      resizeObserverRef.current.disconnect();
    }

    // MutationObserver: DOM構造変更を監視
    mutationObserverRef.current = new MutationObserver(() => {
      debouncedUpdatePositions();
    });

    mutationObserverRef.current.observe(iframeDoc.body, {
      childList: true,
      subtree: true,
      attributes: true,
      attributeFilter: ['style', 'class', 'src', 'aria-label'],
    });

    // ResizeObserver: セクションサイズ変更を監視
    resizeObserverRef.current = new ResizeObserver(() => {
      debouncedUpdatePositions();
    });

    // 全セクションをResizeObserver対象に追加
    const sections = iframeDoc.querySelectorAll('section[aria-label]');
    sections.forEach((section) => {
      resizeObserverRef.current?.observe(section);
    });

    console.log('[PreciseSectionAlignment] Observers setup complete');
  }, [enabled, debouncedUpdatePositions]);

  // iframe読み込み監視
  useEffect(() => {
    // SSR回避: クライアントサイドでのみ実行
    if (typeof window === 'undefined') {
      return;
    }

    console.log('[PreciseSectionAlignment] useEffect running:', {
      hasIframeRef: !!iframeRef.current,
      enabled,
      iframeElementTagName: iframeRef.current?.tagName,
      iframeElementSrc: iframeRef.current?.src,
      timestamp: new Date().toISOString(),
    });

    if (!iframeRef.current || !enabled) {
      console.log('[PreciseSectionAlignment] Skipping - no iframe or disabled:', {
        noIframe: !iframeRef.current,
        disabled: !enabled,
      });
      return;
    }

    const iframe = iframeRef.current;
    let retryCount = 0;
    const maxRetries = 10;

    const trySetup = () => {
      console.log('[PreciseSectionAlignment] trySetup called:', {
        hasContentDocument: !!iframe.contentDocument,
        hasBody: !!iframe.contentDocument?.body,
        retryCount,
        maxRetries,
      });

      if (!iframe.contentDocument?.body) {
        if (retryCount < maxRetries) {
          retryCount++;
          console.log('[PreciseSectionAlignment] Waiting for iframe body, attempt:', retryCount);
          retryTimeoutRef.current = setTimeout(trySetup, 200);
        } else {
          setError(new Error('iframe setup timeout'));
          console.error('[PreciseSectionAlignment] Max retries reached - iframe body not available');
        }
        return;
      }

      // 初回測定
      updatePositions();
      // Observer設定
      setupObservers();
    };

    const handleLoad = () => {
      console.log('[PreciseSectionAlignment] iframe load event');
      retryCount = 0;
      // DOM構築を待つ
      setTimeout(trySetup, 100);
    };

    iframe.addEventListener('load', handleLoad);

    // 既に読み込み済みの場合
    console.log('[PreciseSectionAlignment] Initial check:', {
      readyState: iframe.contentDocument?.readyState,
      hasContentDocument: !!iframe.contentDocument,
    });

    if (iframe.contentDocument?.readyState === 'complete') {
      console.log('[PreciseSectionAlignment] Document already complete, calling handleLoad');
      handleLoad();
    } else {
      // srcdoc iframeの場合
      console.log('[PreciseSectionAlignment] Document not complete, scheduling trySetup');
      setTimeout(trySetup, 100);
    }

    return () => {
      iframe.removeEventListener('load', handleLoad);
      if (retryTimeoutRef.current) {
        clearTimeout(retryTimeoutRef.current);
      }
      if (mutationObserverRef.current) {
        mutationObserverRef.current.disconnect();
      }
      if (resizeObserverRef.current) {
        resizeObserverRef.current.disconnect();
      }
    };
  }, [enabled, updatePositions, setupObservers]);

  // ウィンドウリサイズ時の再計算
  useEffect(() => {
    if (!enabled) return;

    const handleResize = () => {
      console.log('[PreciseSectionAlignment] Window resized');
      debouncedUpdatePositions();
    };

    window.addEventListener('resize', handleResize);

    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, [enabled, debouncedUpdatePositions]);

  // エラー時のリトライ処理
  useEffect(() => {
    if (!error || !enabled) return;

    console.log('[PreciseSectionAlignment] Error detected, scheduling retry');
    const retryTimeout = setTimeout(() => {
      setError(null);
      updatePositions();
    }, 1000);

    return () => clearTimeout(retryTimeout);
  }, [error, enabled, updatePositions]);

  return {
    iframeRef,
    sectionInfos,
    cardAlignments,
    isReady,
    updatePositions,
    error,
  };
}
