import React, { useEffect, useRef, useState, useCallback, lazy, Suspense } from 'react'
import { usePlayerContext } from '../contexts/PlayerContext'
import { PlayPauseButton } from './controls/PlayPauseButton'
import { ProgressBar } from './controls/ProgressBar'
import { VolumeControl } from './controls/VolumeControl'
import { TimeDisplay } from './controls/TimeDisplay'
import { FullscreenButton } from './controls/FullscreenButton'
import { PIPButton } from './controls/PIPButton'
import { SettingsButton } from './controls/SettingsButton'
import { LoadingSpinner } from './overlays/LoadingSpinner'
import { CenterPlayButton } from './controls/CenterPlayButton'
import { useKeyboardShortcuts } from '../hooks/useKeyboardShortcuts'
import { useTouchGestures } from '../hooks/useTouchGestures'
import type { SubtitleTrack, AudioTrack, VideoQuality } from '../types'
import './ControlsLayer.css'

const SettingsMenu = lazy(() => import('./menus/SettingsMenu').then(module => ({ default: module.SettingsMenu })))

interface ControlsLayerProps {
  keyboardShortcuts?: boolean
  pictureInPicture?: boolean
  subtitles?: SubtitleTrack[]
  audioTracks?: AudioTrack[]
  qualities?: VideoQuality[]
}

export const ControlsLayer: React.FC<ControlsLayerProps> = ({
  keyboardShortcuts = true,
  pictureInPicture = true,
  subtitles = [],
  audioTracks = [],
  qualities = [],
}) => {
  const { videoState, uiState, togglePlay, toggleFullscreen, showControls, hideControls } =
    usePlayerContext()
  const [isPointerOver, setIsPointerOver] = useState(false)
  const [lastInteraction, setLastInteraction] = useState<number>(0)
  const hideTimeoutRef = useRef<number | undefined>(undefined)
  const containerRef = useRef<HTMLDivElement | null>(null)
  const lastClickTimeRef = useRef<number>(0)
  const isMenuOpen =
    uiState.settingsOpen ||
    uiState.volumeControlOpen ||
    uiState.qualityMenuOpen ||
    uiState.subtitleMenuOpen
  const autoHideEnabled = videoState.fullscreen && videoState.playing && !isMenuOpen

  const clearHideTimeout = useCallback(() => {
    if (hideTimeoutRef.current) {
      window.clearTimeout(hideTimeoutRef.current)
      hideTimeoutRef.current = undefined
    }
  }, [])

  const scheduleHide = useCallback(() => {
    if (!autoHideEnabled) {
      clearHideTimeout()
      return
    }

    clearHideTimeout()
    hideTimeoutRef.current = window.setTimeout(() => {
      hideControls()
    }, 3000)
  }, [autoHideEnabled, clearHideTimeout, hideControls])

  // Keep controls visible when not playing or when any menu is open
  useEffect(() => {
    if (!videoState.playing || isMenuOpen) {
      clearHideTimeout()
      showControls()
    }
  }, [videoState.playing, isMenuOpen, showControls, clearHideTimeout])

  // Manage controls visibility when leaving fullscreen
  useEffect(() => {
    if (!videoState.fullscreen) {
      clearHideTimeout()
      if (!videoState.playing || isPointerOver) {
        showControls()
      }
    }
  }, [videoState.fullscreen, videoState.playing, isPointerOver, showControls, clearHideTimeout])

  // Re-schedule auto hide when interaction changes
  useEffect(() => {
    if (autoHideEnabled && lastInteraction > 0) {
      scheduleHide()
    }

    return () => {
      if (autoHideEnabled) {
        clearHideTimeout()
      }
    }
  }, [autoHideEnabled, lastInteraction, scheduleHide, clearHideTimeout])

  const handleMouseEnter = useCallback(() => {
    setIsPointerOver(true)
    showControls()
    if (autoHideEnabled) {
      setLastInteraction(Date.now())
    }
  }, [autoHideEnabled, showControls])

  // Handle mouse movement
  const handleMouseMove = useCallback(() => {
    setIsPointerOver(true)
    showControls()
    if (autoHideEnabled) {
      setLastInteraction(Date.now())
    }
  }, [autoHideEnabled, showControls])

  const handleMouseLeave = useCallback(() => {
    setIsPointerOver(false)
    clearHideTimeout()
    if (videoState.fullscreen) {
      if (videoState.playing) {
        hideControls()
      } else {
        showControls()
      }
    } else if (videoState.playing) {
      hideControls()
    }
  }, [clearHideTimeout, videoState.fullscreen, videoState.playing, hideControls, showControls])

  useEffect(() => {
    return () => {
      clearHideTimeout()
    }
  }, [clearHideTimeout])

  const previousAutoHide = useRef(autoHideEnabled)
  useEffect(() => {
    if (autoHideEnabled && !previousAutoHide.current) {
      showControls()
      setLastInteraction(Date.now())
    }

    previousAutoHide.current = autoHideEnabled
  }, [autoHideEnabled, showControls])

  // Keyboard shortcuts
  useKeyboardShortcuts(keyboardShortcuts)

  // Touch gestures
  useTouchGestures(containerRef)

  // Handle click for play/pause and double-click for fullscreen
  const handleClick = useCallback(
    (e: React.MouseEvent) => {
      // Get the actual element that was clicked
      const target = e.target as HTMLElement
      const currentTarget = e.currentTarget as HTMLElement

      // Allow clicks on:
      // 1. The controls layer itself (when controls are hidden, pointer-events: none makes it work)
      // 2. The center play overlay
      // Don't handle clicks on control buttons or other interactive elements
      const isClickableArea =
        target === currentTarget ||
        target.classList.contains('center-play-overlay') ||
        target.classList.contains('controls-layer')

      if (!isClickableArea) {
        return
      }

      const now = Date.now()
      const timeSinceLastClick = now - lastClickTimeRef.current

      if (timeSinceLastClick < 300) {
        // Double click - toggle fullscreen
        e.preventDefault() // Prevent text selection on double click
        toggleFullscreen()
        lastClickTimeRef.current = 0
      } else {
        // Single click - toggle play/pause (with delay to detect double click)
        setTimeout(() => {
          if (Date.now() - lastClickTimeRef.current >= 300) {
            togglePlay()
          }
        }, 300)
        lastClickTimeRef.current = now
      }
    },
    [togglePlay, toggleFullscreen]
  )

  const controlsClassName = `controls-layer ${uiState.controlsVisible ? 'visible' : 'hidden'} ${
    videoState.playing ? 'playing' : 'paused'
  } ${videoState.fullscreen ? 'fullscreen' : 'windowed'}`

  return (
    <div
      ref={containerRef}
      className={controlsClassName}
      onMouseEnter={handleMouseEnter}
      onMouseMove={handleMouseMove}
      onMouseLeave={handleMouseLeave}
      onClick={handleClick}
    >
      {/* Loading spinner */}
      {videoState.loading && <LoadingSpinner />}

      {/* Center play button (only when paused) */}
      {!videoState.playing && !videoState.loading && <CenterPlayButton />}

      {/* Bottom controls bar */}
      <div className="controls-bar">
        {/* Progress bar (full width on top) */}
        <div className="progress-container">
          <ProgressBar />
        </div>

        {/* Control buttons */}
        <div className="controls-row">
          <div className="controls-left">
            <PlayPauseButton />
            <VolumeControl />
            <TimeDisplay />
          </div>

          <div className="controls-right">
            <div style={{ position: 'relative' }}>
              <SettingsButton />
              <Suspense fallback={null}>
                <SettingsMenu subtitles={subtitles} audioTracks={audioTracks} qualities={qualities} />
              </Suspense>
            </div>
            {pictureInPicture && <PIPButton />}
            <FullscreenButton />
          </div>
        </div>
      </div>
    </div>
  )
}
