import React, { useEffect, useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { TutorialHint } from './tutorialSteps';

interface Rect {
  top: number;
  left: number;
  width: number;
  height: number;
  bottom: number;
}

interface TooltipPos {
  top: number;
  left: number;
}

interface TutorialOverlayProps {
  hints: TutorialHint[];
  currentIndex: number;
  onNext: () => void;
  onPrev: () => void;
  onSkip: () => void;
  groupProgress?: { groupTotal: number; groupOffset: number; isLastKeyInGroup: boolean } | null;
}

const PADDING = 8;

function getTargetRect(selector: string): Rect | null {
  const els = Array.from(document.querySelectorAll(selector));
  const el = els.find(e => {
    const r = (e as HTMLElement).getBoundingClientRect();
    return r.width > 0 && r.height > 0;
  }) ?? els[0];
  if (!el) return null;
  const r = el.getBoundingClientRect();
  return { top: r.top, left: r.left, width: r.width, height: r.height, bottom: r.bottom };
}

function getSpotlightRect(
  rect: Rect,
  padding: number,
  override?: { top?: number; right?: number; bottom?: number; left?: number }
): Rect {
  const pTop = override?.top ?? padding;
  const pRight = override?.right ?? padding;
  const pBottom = override?.bottom ?? padding;
  const pLeft = override?.left ?? padding;
  const left = Math.max(0, Math.floor(rect.left - pLeft));
  const top = Math.max(0, Math.floor(rect.top - pTop));
  const right = Math.min(window.innerWidth, Math.ceil(rect.left + rect.width + pRight));
  const bottom = Math.min(window.innerHeight, Math.ceil(rect.top + rect.height + pBottom));

  return {
    top,
    bottom,
    left,
    width: Math.max(0, right - left),
    height: Math.max(0, bottom - top),
  };
}

function calcTooltipPos(rect: Rect, position: TutorialHint['position'], tooltipW = 300, tooltipH = 160): TooltipPos {

  switch (position) {
    case 'bottom':
      return {
        top: Math.min(rect.top + rect.height + PADDING, window.innerHeight - tooltipH - 8),
        left: Math.min(Math.max(rect.left + rect.width / 2 - tooltipW / 2, 8), window.innerWidth - tooltipW - 8),
      };
    case 'top':
      return {
        top: Math.max(rect.top - tooltipH - PADDING, 8),
        left: Math.min(Math.max(rect.left + rect.width / 2 - tooltipW / 2, 8), window.innerWidth - tooltipW - 8),
      };
    case 'right':
      return {
        top: Math.min(Math.max(rect.top + rect.height / 2 - tooltipH / 2, 8), window.innerHeight - tooltipH - 8),
        left: Math.min(rect.left + rect.width + PADDING, window.innerWidth - tooltipW - 8),
      };
    case 'left':
      return {
        top: Math.min(Math.max(rect.top + rect.height / 2 - tooltipH / 2, 8), window.innerHeight - tooltipH - 8),
        left: Math.max(rect.left - tooltipW - PADDING, 8),
      };
  }
}

const TutorialOverlay: React.FC<TutorialOverlayProps> = ({
  hints,
  currentIndex,
  onNext,
  onPrev,
  onSkip,
  groupProgress,
}) => {
  const { t } = useTranslation();
  const [targetRect, setTargetRect] = useState<Rect | null>(null);
  const tooltipRef = React.useRef<HTMLDivElement>(null);
  const [tooltipSize, setTooltipSize] = useState({ w: 300, h: 160 });

  const hint = hints[currentIndex];
  const isLast = currentIndex === hints.length - 1;
  // 그룹이 있으면 그룹의 마지막 키 + 마지막 힌트일 때만 완료, 그룹 없으면 기존대로
  const isFinish = isLast && (groupProgress ? groupProgress.isLastKeyInGroup : true);

  const updateRect = useCallback(() => {
    if (!hint) return;
    setTargetRect(getTargetRect(hint.targetSelector));
  }, [hint]);

  useEffect(() => {
    updateRect();
    window.addEventListener('resize', updateRect);
    window.addEventListener('scroll', updateRect, true);
    return () => {
      window.removeEventListener('resize', updateRect);
      window.removeEventListener('scroll', updateRect, true);
    };
  }, [updateRect]);

  useEffect(() => {
    if (!hint) return;
    let retryTimer: number | undefined;
    let rectTimer: number | undefined;
    let cleanupTarget: (() => void) | undefined;

    const bindToTarget = (el: HTMLElement) => {
      el.scrollIntoView({ behavior: 'smooth', block: 'center' });
      rectTimer = window.setTimeout(updateRect, 200);

      const shouldClickAdvance = hint.clickToAdvance !== false;
      if (shouldClickAdvance) {
        el.style.cursor = 'pointer';
        el.addEventListener('click', onNext);
        cleanupTarget = () => {
          el.style.cursor = '';
          el.removeEventListener('click', onNext);
        };
      } else {
        cleanupTarget = () => {};
      }
    };

    const tryBind = (): boolean => {
      const els = Array.from(document.querySelectorAll(hint.targetSelector));
      const el = (els.find(e => {
        const r = (e as HTMLElement).getBoundingClientRect();
        return r.width > 0 && r.height > 0;
      }) ?? els[0]) as HTMLElement | null;
      if (!el) return false;
      bindToTarget(el);
      return true;
    };

    if (!tryBind()) {
      retryTimer = window.setInterval(() => {
        if (tryBind() && retryTimer) {
          window.clearInterval(retryTimer);
          retryTimer = undefined;
        }
      }, 80);
    }

    return () => {
      if (retryTimer) window.clearInterval(retryTimer);
      if (rectTimer) window.clearTimeout(rectTimer);
      cleanupTarget?.();
    };
  }, [hint, updateRect, onNext]);

  // 툴팁 DOM 크기 측정 — 힌트가 바뀔 때만 재측정
  useEffect(() => {
    const el = tooltipRef.current;
    if (!el) return;
    const { offsetWidth, offsetHeight } = el;
    if (offsetWidth && offsetHeight) {
      setTooltipSize(prev =>
        prev.w === offsetWidth && prev.h === offsetHeight
          ? prev
          : { w: offsetWidth, h: offsetHeight }
      );
    }
  }, [currentIndex, hints]);

  if (!hint) return null;

  const isTargetVisible = targetRect
    ? targetRect.top + 60 < window.innerHeight && targetRect.bottom > 60
    : true;

  if (!isTargetVisible) return null;

  const spotlightPadding = hint.spotlightPadding ?? PADDING;
  const spotlightRect = (targetRect && !hint.noSpotlight) ? getSpotlightRect(targetRect, spotlightPadding, hint.spotlightPaddingOverride) : null;

  // 툴팁은 spotlightRect 기준으로 배치해야 스포트라이트와 겹치지 않음
  const tooltipPos: TooltipPos = (spotlightRect ?? targetRect)
    ? calcTooltipPos((spotlightRect ?? targetRect)!, hint.position, tooltipSize.w, tooltipSize.h)
    : {
        top: window.innerHeight / 2 - tooltipSize.h / 2,
        left: window.innerWidth / 2 - tooltipSize.w / 2,
      };

  return (
    <div className="tutorial-overlay-root">
      {spotlightRect ? (
        <>
          <div
            className="tutorial-overlay-blocker"
            style={{ top: 0, left: 0, right: 0, height: spotlightRect.top }}
          />
          <div
            className="tutorial-overlay-blocker"
            style={{
              top: spotlightRect.top,
              left: 0,
              width: spotlightRect.left,
              height: spotlightRect.height,
            }}
          />
          <div
            className="tutorial-overlay-blocker"
            style={{
              top: spotlightRect.top,
              left: spotlightRect.left + spotlightRect.width,
              right: 0,
              height: spotlightRect.height,
            }}
          />
          <div
            className="tutorial-overlay-blocker"
            style={{
              top: spotlightRect.top + spotlightRect.height,
              left: 0,
              right: 0,
              bottom: 0,
            }}
          />
          <div
            className="tutorial-spotlight-ring"
            style={{
              top: spotlightRect.top,
              left: spotlightRect.left,
              width: spotlightRect.width,
              height: spotlightRect.height,
            }}
          />
        </>
      ) : null}

      <div
        ref={tooltipRef}
        className={`tutorial-tooltip${hint.variant === 'bubble' ? ` tutorial-tooltip-bubble tutorial-tooltip-bubble--${hint.position}` : ''}`}
        style={{ top: tooltipPos.top, left: tooltipPos.left }}
        onClick={(e) => e.stopPropagation()}
      >
        <p className="tutorial-tooltip-title">{t(hint.titleKey)}</p>
        <p className="tutorial-tooltip-desc">{t(hint.descriptionKey)}</p>
        {hint.noteKey && (
          <p className="tutorial-tooltip-note">{t(hint.noteKey)}</p>
        )}

        <div className="tutorial-tooltip-footer">
          <span className="tutorial-tooltip-counter">
            {groupProgress ? groupProgress.groupOffset + 1 : currentIndex + 1} / {groupProgress ? groupProgress.groupTotal : hints.length}
          </span>
          <div className="tutorial-tooltip-actions">
            <button className="tutorial-btn-skip" onClick={onSkip}>
              {t('tutorial.skip')}
            </button>
            {currentIndex > 0 && (
              <button className="tutorial-btn-prev" onClick={onPrev}>
                {t('tutorial.prev')}
              </button>
            )}
            {(hint.clickToAdvance !== true || isFinish) && (
              <button className="tutorial-btn-next" onClick={onNext}>
                {isFinish ? t('tutorial.finish') : t('tutorial.next')}
              </button>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

export default TutorialOverlay;

interface TutorialRestartPopupProps {
  onConfirm: () => void;
  onCancel: () => void;
}

export const TutorialRestartPopup: React.FC<TutorialRestartPopupProps> = ({ onConfirm, onCancel }) => {
  const { t } = useTranslation();
  return (
    <div className="tutorial-restart-backdrop">
      <div className="tutorial-restart-popup" onClick={(e) => e.stopPropagation()}>
        <p className="tutorial-restart-title">{t('tutorial.restart.title')}</p>
        <p className="tutorial-restart-desc">{t('tutorial.restart.desc')}</p>
        <div className="tutorial-restart-actions">
          <button className="tutorial-restart-cancel" onClick={onCancel}>
            {t('tutorial.restart.cancel')}
          </button>
          <button className="tutorial-restart-confirm" onClick={onConfirm}>
            {t('tutorial.restart.confirm')}
          </button>
        </div>
      </div>
    </div>
  );
};
