import { useEffect, useLayoutEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { X, ChevronLeft, ChevronRight } from 'lucide-react'
import {
  getTourStepCopy,
  getTourTargetSelector,
  getTourTargetRetryDelay,
  isCenteredTourStep,
  useAppTour
} from '../context/AppTourContext.tsx'

interface SpotlightRect {
  top: number
  left: number
  width: number
  height: number
}

const TOOLTIP_EDGE_MARGIN = 16
const TOOLTIP_ESTIMATED_HEIGHT = 240
const TOOLTIP_WIDTH = 420
const TARGET_VIEWPORT_MARGIN = 24

function clampTooltipTop(preferred: number): number {
  const maxTop = window.innerHeight - TOOLTIP_EDGE_MARGIN - TOOLTIP_ESTIMATED_HEIGHT
  return Math.max(TOOLTIP_EDGE_MARGIN, Math.min(preferred, maxTop))
}

function computeTooltipLeft(spotlight: SpotlightRect): number {
  const tooltipWidth = Math.min(TOOLTIP_WIDTH, window.innerWidth - TOOLTIP_EDGE_MARGIN * 2)
  const ideal = spotlight.left + spotlight.width / 2 - tooltipWidth / 2
  const maxLeft = window.innerWidth - TOOLTIP_EDGE_MARGIN - tooltipWidth
  return Math.max(TOOLTIP_EDGE_MARGIN, Math.min(ideal, maxLeft))
}

function buildCutoutClipPath(rect: SpotlightRect): string {
  const right = rect.left + rect.width
  const bottom = rect.top + rect.height
  return `polygon(evenodd, 0 0, 100vw 0, 100vw 100vh, 0 100vh, 0 0, ${rect.left}px ${rect.top}px, ${right}px ${rect.top}px, ${right}px ${bottom}px, ${rect.left}px ${bottom}px, ${rect.left}px ${rect.top}px)`
}

function computeTooltipTop(spotlight: SpotlightRect): number {
  const viewportBottom = window.innerHeight - TOOLTIP_EDGE_MARGIN
  const below = spotlight.top + spotlight.height + 12
  if (below + TOOLTIP_ESTIMATED_HEIGHT <= viewportBottom) {
    return clampTooltipTop(below)
  }

  const above = spotlight.top - 12 - TOOLTIP_ESTIMATED_HEIGHT
  if (above >= TOOLTIP_EDGE_MARGIN) {
    return clampTooltipTop(above)
  }

  return clampTooltipTop(below)
}

function isTargetVisibleInViewport(rect: DOMRect): boolean {
  return (
    rect.top >= TARGET_VIEWPORT_MARGIN &&
    rect.bottom <= window.innerHeight - TARGET_VIEWPORT_MARGIN
  )
}

function measureSpotlight(el: Element): SpotlightRect | null {
  const rect = el.getBoundingClientRect()
  if (rect.width <= 0 || rect.height <= 0) return null
  const padding = 8
  return {
    top: Math.max(8, rect.top - padding),
    left: Math.max(8, rect.left - padding),
    width: rect.width + padding * 2,
    height: rect.height + padding * 2
  }
}

export default function AppTourOverlay() {
  const { t } = useTranslation()
  const {
    isActive,
    isDemoTour,
    currentStepId,
    currentStepIndex,
    totalSteps,
    layoutTick,
    nextStep,
    prevStep,
    skipTour
  } = useAppTour()

  const [spotlight, setSpotlight] = useState<SpotlightRect | null>(null)
  const skipTourRef = useRef(skipTour)
  skipTourRef.current = skipTour

  useLayoutEffect(() => {
    if (!isActive || !currentStepId || isCenteredTourStep(currentStepId)) {
      setSpotlight(null)
      return
    }

    let cancelled = false

    const updateSpotlight = () => {
      if (cancelled) return
      const selector = getTourTargetSelector(currentStepId)
      if (!selector) {
        setSpotlight(null)
        return
      }
      const el = document.querySelector(selector)
      if (!el) {
        setSpotlight(null)
        return
      }

      const rect = el.getBoundingClientRect()
      if (!isTargetVisibleInViewport(rect)) {
        el.scrollIntoView({ behavior: 'instant', block: 'center', inline: 'nearest' })
        window.requestAnimationFrame(() => {
          if (cancelled) return
          const next = measureSpotlight(el)
          setSpotlight(next)
        })
        return
      }

      setSpotlight(measureSpotlight(el))
    }

    updateSpotlight()
    window.addEventListener('resize', updateSpotlight)
    window.addEventListener('scroll', updateSpotlight, true)

    const retryDelays =
      currentStepId === 'entry_track'
        ? [400, 700, 1100, 1600]
        : [getTourTargetRetryDelay(currentStepId), 120, 280, 480]
    const timers = retryDelays.map((delay) => window.setTimeout(updateSpotlight, delay))

    return () => {
      cancelled = true
      for (const timer of timers) window.clearTimeout(timer)
      window.removeEventListener('resize', updateSpotlight)
      window.removeEventListener('scroll', updateSpotlight, true)
    }
  }, [currentStepId, isActive, layoutTick])

  useEffect(() => {
    if (!isActive) return
    document.body.classList.add('app-tour-active')
    return () => document.body.classList.remove('app-tour-active')
  }, [isActive])

  useEffect(() => {
    if (!isActive || !currentStepId || isCenteredTourStep(currentStepId)) return

    const selector = getTourTargetSelector(currentStepId)
    if (!selector) return

    const el = document.querySelector(selector)
    el?.classList.add('app-tour-target-active')
    return () => el?.classList.remove('app-tour-target-active')
  }, [currentStepId, isActive])

  useEffect(() => {
    if (!isActive) return
    const onKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') skipTourRef.current()
    }
    window.addEventListener('keydown', onKeyDown)
    return () => window.removeEventListener('keydown', onKeyDown)
  }, [isActive])

  if (!isActive || !currentStepId) return null

  const { title, body } = getTourStepCopy(currentStepId, t, { demoMode: isDemoTour })
  const centered = isCenteredTourStep(currentStepId)

  const tooltipStyle = centered
    ? undefined
    : spotlight
      ? { top: computeTooltipTop(spotlight), left: computeTooltipLeft(spotlight) }
      : { top: '20%' }

  const tooltipClassName = [
    'app-tour-tooltip',
    centered ? 'centered' : '',
    !centered && spotlight ? 'app-tour-tooltip--anchored' : ''
  ]
    .filter(Boolean)
    .join(' ')

  const backdropStyle = spotlight && !centered
    ? { clipPath: buildCutoutClipPath(spotlight) }
    : undefined

  return (
    <div className="app-tour-root" role="dialog" aria-modal="true" aria-label={title}>
      <div
        className={`app-tour-backdrop${spotlight && !centered ? ' app-tour-backdrop--cutout' : ''}`}
        style={backdropStyle}
        onClick={skipTour}
      />

      {!centered && spotlight && (
        <div
          className="app-tour-spotlight"
          style={{
            top: spotlight.top,
            left: spotlight.left,
            width: spotlight.width,
            height: spotlight.height
          }}
        />
      )}

      <div className={tooltipClassName} style={tooltipStyle}>
        <button type="button" className="app-tour-close" onClick={skipTour} aria-label={t('tour.skip')}>
          <X size={18} />
        </button>

        <p className="app-tour-progress">
          {t('tour.progress', { current: currentStepIndex + 1, total: totalSteps })}
        </p>
        <h3 className="app-tour-title">{title}</h3>
        <p className="app-tour-body">{body}</p>

        <div className="app-tour-actions">
          <button
            type="button"
            className="app-tour-link"
            onClick={skipTour}
          >
            {t('tour.skip')}
          </button>

          <div className="app-tour-nav">
            <button
              type="button"
              className="btn secondary app-tour-nav-btn"
              onClick={prevStep}
              disabled={currentStepIndex === 0}
            >
              <ChevronLeft size={16} />
              {t('tour.back')}
            </button>
            <button type="button" className="btn primary app-tour-nav-btn" onClick={nextStep}>
              {currentStepIndex === totalSteps - 1 ? t('tour.finish') : t('tour.next')}
              {currentStepIndex < totalSteps - 1 && <ChevronRight size={16} />}
            </button>
          </div>
        </div>
      </div>
    </div>
  )
}
