'use client'

import { useEffect, useRef, useState, useCallback } from 'react'
import { useUserSettings } from '@/hooks/useUserSettings'

export interface DoomScrollItem {
  url: string
  name: string
  mediaType: 'video' | 'image'
  itemKey?: string
}

interface Props {
  items: DoomScrollItem[]
  videoContext?: 'mixed' | 'movies' | 'tv'
  onClose: () => void
  onViewInLibrary?: (item: DoomScrollItem) => void
}

const HISTORY_CAP = 100

function pickRandom(items: DoomScrollItem[], excludeRecent: DoomScrollItem[]): DoomScrollItem {
  const excludeCount = Math.min(excludeRecent.length, items.length - 1)
  const recentUrls = new Set(excludeRecent.slice(-excludeCount).map((i) => i.url))
  const candidates = items.filter((i) => !recentUrls.has(i.url))
  const pool = candidates.length > 0 ? candidates : items
  return pool[Math.floor(Math.random() * pool.length)]
}

export default function DoomScrollView({ items, videoContext = 'mixed', onClose, onViewInLibrary }: Props) {
  const settings = useUserSettings()
  const settingsMuted = videoContext === 'mixed' ? settings.mixedMuted : videoContext === 'movies' ? settings.moviesMuted : settings.tvMuted

  const [history, setHistory] = useState<DoomScrollItem[]>(() => {
    if (items.length === 0) return []
    return [pickRandom(items, [])]
  })
  const [historyIndex, setHistoryIndex] = useState(0)
  const [localMuted, setLocalMuted] = useState(settingsMuted)
  const [isPaused, setIsPaused] = useState(false)
  const [autoPlayEnabled, setAutoPlayEnabled] = useState(false)
  const [autoPlaySeconds, setAutoPlaySeconds] = useState(5)

  // Tools overlay visibility
  const [showToolsOverlay, setShowToolsOverlay] = useState(false)

  // Rating state
  const [userRating, setUserRatingState] = useState<number | null>(null)
  const [ratingHover, setRatingHover] = useState<number | null>(null)
  const [savingRating, setSavingRating] = useState(false)

  // Text overlay state
  const [extractedText, setExtractedText] = useState<string | null>(null)
  const [editedExtractedText, setEditedExtractedText] = useState<string>('')
  const [savingText, setSavingText] = useState(false)
  const [translatedText, setTranslatedText] = useState<string | null>(null)
  const [showTextOverlay, setShowTextOverlay] = useState(false)
  const [showOriginal, setShowOriginal] = useState(false)
  const [extracting, setExtracting] = useState(false)
  const [extractError, setExtractError] = useState<string | null>(null)
  const [extractPending, setExtractPending] = useState(false)
  const [retranslating, setRetranslating] = useState(false)
  const [translatePending, setTranslatePending] = useState(false)
  const [ocrLanguageInput, setOcrLanguageInput] = useState('')
  const [defaultOcrLanguages, setDefaultOcrLanguages] = useState('eng')
  const [sourceLanguage, setSourceLanguage] = useState('')

  const videoRef = useRef<HTMLVideoElement>(null)
  const extractPollRef = useRef<ReturnType<typeof setInterval> | null>(null)
  const cooldownRef = useRef(false)
  const touchStartY = useRef<number | null>(null)

  const current = history[historyIndex] ?? null
  const isVideo = current?.mediaType === 'video'
  const backCount = history.length - 1 - historyIndex

  // Derived: what text to display in the overlay
  const displayText = (translatedText && !showOriginal) ? translatedText : extractedText

  const goNext = useCallback(() => {
    if (items.length === 0) return
    setHistoryIndex((idx) => {
      if (idx < history.length - 1) {
        return idx + 1
      }
      const next = pickRandom(items, history)
      setHistory((h) => {
        const updated = [...h, next]
        return updated.length > HISTORY_CAP ? updated.slice(-HISTORY_CAP) : updated
      })
      return Math.min(idx + 1, HISTORY_CAP - 1)
    })
  }, [items, history])

  const goPrev = useCallback(() => {
    setHistoryIndex((idx) => Math.max(0, idx - 1))
  }, [])

  const navigate = useCallback((dir: 'next' | 'prev') => {
    if (cooldownRef.current) return
    cooldownRef.current = true
    if (dir === 'next') goNext()
    else goPrev()
    setTimeout(() => { cooldownRef.current = false }, 300)
  }, [goNext, goPrev])

  // On navigation to a new item: reset pause state and start playing.
  // Merging the reset + play() into one effect prevents the old isPaused=true
  // value from calling pause() on the freshly-mounted video element before the
  // reset fires. If autoplay is blocked by browser policy (common when unmuted),
  // fall back to muted and retry — the user can unmute manually afterward.
  useEffect(() => {
    setIsPaused(false)
    if (!videoRef.current) return
    videoRef.current.play().catch(() => {
      if (!videoRef.current) return
      videoRef.current.muted = true
      setLocalMuted(true)
      videoRef.current.play().catch(() => {})
    })
  }, [current?.url])

  // Sync muted imperatively — React's muted prop is not reliable
  useEffect(() => {
    if (videoRef.current) videoRef.current.muted = localMuted
  }, [localMuted, current?.url])

  // Sync play/pause imperatively for user-initiated pause/unpause only.
  // current?.url is intentionally excluded: navigation is handled above.
  useEffect(() => {
    if (!videoRef.current) return
    if (isPaused) {
      videoRef.current.pause()
    } else {
      videoRef.current.play().catch(() => {})
    }
  }, [isPaused])

  // Auto-play timer — resets on each new item, pause, enable/disable, or interval change
  useEffect(() => {
    if (!autoPlayEnabled || isPaused) return
    const id = setTimeout(() => goNext(), autoPlaySeconds * 1000)
    return () => clearTimeout(id)
  }, [autoPlayEnabled, isPaused, autoPlaySeconds, current?.url, goNext])

  // Fetch OCR settings once on mount
  useEffect(() => {
    fetch('/api/ai-settings/ocr')
      .then((r) => r.json())
      .then((d: { ocrMode: string; ocrLanguages: string }) => {
        setDefaultOcrLanguages(d.ocrLanguages)
      })
      .catch(() => {})
  }, [])

  // Fetch extracted text + rating for current item; clear any in-flight poll on item change
  useEffect(() => {
    if (extractPollRef.current) {
      clearInterval(extractPollRef.current)
      extractPollRef.current = null
    }
    setExtractedText(null)
    setEditedExtractedText('')
    setTranslatedText(null)
    setShowTextOverlay(false)
    setShowOriginal(false)
    setExtracting(false)
    setExtractError(null)
    setExtractPending(false)
    setRetranslating(false)
    setTranslatePending(false)
    setUserRatingState(null)
    setRatingHover(null)
    if (!current?.itemKey) return
    const key = current.itemKey
    fetch(`/api/ai-tagging/fields?itemKey=${encodeURIComponent(key)}`)
      .then((r) => r.json())
      .then((data: { extractedText: string | null; extractedTextTranslated: string | null }) => {
        setExtractedText(data.extractedText)
        setEditedExtractedText(data.extractedText ?? '')
        setTranslatedText(data.extractedTextTranslated)
      })
      .catch(() => {})
    fetch(`/api/ratings?itemKey=${encodeURIComponent(key)}`)
      .then((r) => r.json())
      .then((data: { userRating: number | null }) => {
        setUserRatingState(data.userRating)
      })
      .catch(() => {})
  }, [current?.itemKey])

  // Clean up poll on unmount
  useEffect(() => {
    return () => {
      if (extractPollRef.current) clearInterval(extractPollRef.current)
    }
  }, [])

  useEffect(() => {
    const handleKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') { onClose(); return }
      if (e.key === 'ArrowDown' || e.key === ' ' || e.key === 'PageDown') { e.preventDefault(); navigate('next') }
      if (e.key === 'ArrowUp' || e.key === 'PageUp') { e.preventDefault(); navigate('prev') }
      if (e.key === 't' || e.key === 'T') {
        if (extractedText) setShowTextOverlay((v) => !v)
      }
    }
    const handleWheel = (e: WheelEvent) => {
      e.preventDefault()
      navigate(e.deltaY > 0 ? 'next' : 'prev')
    }
    const handleTouchStart = (e: TouchEvent) => {
      touchStartY.current = e.touches[0].clientY
    }
    const handleTouchEnd = (e: TouchEvent) => {
      if (touchStartY.current === null) return
      const delta = touchStartY.current - e.changedTouches[0].clientY
      if (Math.abs(delta) > 50) navigate(delta > 0 ? 'next' : 'prev')
      touchStartY.current = null
    }

    document.addEventListener('keydown', handleKey)
    document.addEventListener('wheel', handleWheel, { passive: false })
    document.addEventListener('touchstart', handleTouchStart, { passive: true })
    document.addEventListener('touchend', handleTouchEnd, { passive: true })
    document.body.style.overflow = 'hidden'

    return () => {
      document.removeEventListener('keydown', handleKey)
      document.removeEventListener('wheel', handleWheel)
      document.removeEventListener('touchstart', handleTouchStart)
      document.removeEventListener('touchend', handleTouchEnd)
      document.body.style.overflow = ''
    }
  }, [navigate, onClose, extractedText])

  // ── Polling helper ──────────────────────────────────────────────────────────
  const startPolling = useCallback((snapshotText: string | null, snapshotTranslated: string | null) => {
    if (!current?.itemKey) return
    const itemKey = current.itemKey
    if (extractPollRef.current) clearInterval(extractPollRef.current)
    const deadline = Date.now() + 5 * 60 * 1000
    extractPollRef.current = setInterval(async () => {
      if (Date.now() > deadline) {
        clearInterval(extractPollRef.current!)
        extractPollRef.current = null
        setExtractPending(false)
        setTranslatePending(false)
        return
      }
      try {
        const r = await fetch(`/api/ai-tagging/fields?itemKey=${encodeURIComponent(itemKey)}`)
        const data: { extractedText: string | null; extractedTextTranslated: string | null } = await r.json()
        const textChanged = data.extractedText !== snapshotText
        const translationChanged = data.extractedTextTranslated !== snapshotTranslated
        if (textChanged || translationChanged) {
          clearInterval(extractPollRef.current!)
          extractPollRef.current = null
          setExtractedText(data.extractedText)
          setEditedExtractedText(data.extractedText ?? '')
          setTranslatedText(data.extractedTextTranslated)
          setExtractPending(false)
          setTranslatePending(false)
          if (data.extractedText) setShowTextOverlay(true)
        }
      } catch { /* ignore */ }
    }, 2000)
  }, [current?.itemKey])

  // ── Rating actions ───────────────────────────────────────────────────────────
  const handleSetRating = useCallback(async (star: number) => {
    if (!current?.itemKey) return
    const next = userRating === star ? null : star
    setSavingRating(true)
    try {
      const res = await fetch('/api/ratings', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ itemKey: current.itemKey, userRating: next }),
      })
      if (res.ok) setUserRatingState(next)
    } finally {
      setSavingRating(false)
    }
  }, [current?.itemKey, userRating])

  // ── Text extraction ──────────────────────────────────────────────────────────
  const callExtract = useCallback(async (modeOverride: string) => {
    if (!current?.itemKey) return
    const itemKey = current.itemKey
    setExtracting(true)
    setExtractError(null)
    setExtractPending(false)
    try {
      const res = await fetch('/api/ai-tagging/extract-text', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          itemKey,
          ocrMode: modeOverride,
          ...(modeOverride !== 'llm' && ocrLanguageInput.trim() && { ocrLanguages: ocrLanguageInput.trim() }),
        }),
      })
      if (res.status === 202) {
        setExtractPending(true)
        startPolling(extractedText, translatedText)
        return
      }
      if (!res.ok) {
        const data = await res.json().catch(() => ({}))
        throw new Error((data as { error?: string }).error ?? 'Extraction failed')
      }
      const result = await res.json()
      const newText: string | null = result.extractedText || null
      const newTranslated: string | null = result.translatedText || null
      setExtractedText(newText)
      setEditedExtractedText(newText ?? '')
      setTranslatedText(newTranslated)
      if (newText) setShowTextOverlay(true)
    } catch (err) {
      setExtractError(err instanceof Error ? err.message : 'Extraction failed')
      setTimeout(() => setExtractError(null), 4000)
    } finally {
      setExtracting(false)
    }
  }, [current?.itemKey, ocrLanguageInput, extractedText, translatedText, startPolling])

  // ── Save edited extracted text ───────────────────────────────────────────────
  const handleSaveExtractedText = useCallback(async () => {
    if (!current?.itemKey) return
    setSavingText(true)
    try {
      await fetch('/api/ai-tagging/fields', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ itemKey: current.itemKey, extractedText: editedExtractedText }),
      })
      setExtractedText(editedExtractedText)
    } finally {
      setSavingText(false)
    }
  }, [current?.itemKey, editedExtractedText])

  // ── Translation ──────────────────────────────────────────────────────────────
  const handleTranslate = useCallback(async () => {
    if (!current?.itemKey) return
    setRetranslating(true)
    setTranslatePending(false)
    try {
      const res = await fetch('/api/ai-tagging/translate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          itemKey: current.itemKey,
          ...(sourceLanguage.trim() && { sourceLanguage: sourceLanguage.trim() }),
        }),
      })
      if (res.status === 202) {
        setTranslatePending(true)
        startPolling(extractedText, translatedText)
        return
      }
      if (!res.ok) {
        const data = await res.json().catch(() => ({}))
        throw new Error((data as { error?: string }).error ?? 'Translation failed')
      }
      const result = await res.json()
      setTranslatedText(result.translatedText || null)
    } catch {
      // ignore
    } finally {
      setRetranslating(false)
    }
  }, [current?.itemKey, sourceLanguage, extractedText, translatedText, startPolling])

  return (
    <div className="fixed inset-0 z-50 flex flex-col" style={{ backgroundColor: '#000' }}>
      {/* Keyframe for auto-play progress bar */}
      <style>{`@keyframes doom-progress { from { width: 0% } to { width: 100% } }`}</style>

      {/* Top bar */}
      <div className="absolute top-0 left-0 right-0 flex items-center gap-2 p-3 z-10">
        <span className="text-xs px-2 py-1 rounded flex-shrink-0" style={{ color: 'rgba(255,255,255,0.5)', backgroundColor: 'rgba(0,0,0,0.4)' }}>
          {backCount > 0 ? `← ${backCount}` : 'Doom Scroll'}
        </span>

        {/* Auto-play controls */}
        <div className="flex-1 flex items-center justify-center gap-2">
          <button
            onClick={() => setAutoPlayEnabled((v) => !v)}
            className="px-3 py-1 rounded-full text-xs font-medium transition-colors flex-shrink-0"
            style={{
              backgroundColor: autoPlayEnabled ? 'var(--accent)' : 'rgba(0,0,0,0.5)',
              color: '#fff',
            }}
            aria-label={autoPlayEnabled ? 'Disable auto-play' : 'Enable auto-play'}
          >
            Auto
          </button>
          {autoPlayEnabled && (
            <div className="flex items-center gap-1">
              <button
                onClick={() => setAutoPlaySeconds((s) => Math.max(1, s - 1))}
                className="w-6 h-6 rounded-full flex items-center justify-center text-sm flex-shrink-0"
                style={{ backgroundColor: 'rgba(0,0,0,0.5)', color: '#fff' }}
                aria-label="Decrease interval"
              >
                −
              </button>
              <span className="text-xs text-center flex-shrink-0" style={{ color: 'rgba(255,255,255,0.8)', minWidth: '2.25rem' }}>
                {autoPlaySeconds}s
              </span>
              <button
                onClick={() => setAutoPlaySeconds((s) => Math.min(60, s + 1))}
                className="w-6 h-6 rounded-full flex items-center justify-center text-sm flex-shrink-0"
                style={{ backgroundColor: 'rgba(0,0,0,0.5)', color: '#fff' }}
                aria-label="Increase interval"
              >
                +
              </button>
            </div>
          )}
        </div>

        <button
          onClick={onClose}
          className="w-9 h-9 rounded-full flex items-center justify-center text-sm flex-shrink-0 transition-opacity hover:opacity-100 opacity-80"
          style={{ backgroundColor: 'rgba(0,0,0,0.5)', color: '#fff' }}
          aria-label="Close doom scroll"
        >
          ✕
        </button>
      </div>

      {/* Media */}
      <div className="flex-1 flex items-center justify-center overflow-hidden">
        {isVideo && current ? (
          <video
            ref={videoRef}
            key={current.url}
            src={current.url}
            autoPlay
            loop={!autoPlayEnabled}
            muted={localMuted}
            playsInline
            className="max-w-full max-h-full object-contain cursor-pointer"
            style={{ backgroundColor: '#000' }}
            onClick={() => setIsPaused((v) => !v)}
          />
        ) : current?.mediaType === 'image' ? (
          // eslint-disable-next-line @next/next/no-img-element
          <img
            key={current.url}
            src={current.url}
            alt={current.name}
            className="max-w-full max-h-full object-contain"
          />
        ) : null}
      </div>

      {/* Tools overlay — anchored lower-left, above the bottom bar */}
      {showToolsOverlay && current?.itemKey && (
        <div
          className="absolute bottom-16 left-4 z-20 rounded-xl p-4 flex flex-col gap-3 overflow-y-auto"
          style={{
            backgroundColor: 'rgba(10,10,10,0.92)',
            border: '1px solid rgba(255,255,255,0.12)',
            width: 'min(320px, calc(100vw - 2rem))',
            maxHeight: 'calc(100vh - 8rem)',
          }}
          onClick={(e) => e.stopPropagation()}
        >
          {/* ── Rating ──────────────────────────────────────────── */}
          <div>
            <p className="text-xs font-semibold uppercase tracking-wider mb-2" style={{ color: 'rgba(255,255,255,0.45)' }}>
              Rating
            </p>
            <div className="flex items-center gap-1" onMouseLeave={() => setRatingHover(null)}>
              {[1, 2, 3, 4, 5].map((star) => {
                const filled = (ratingHover ?? userRating ?? 0) >= star
                return (
                  <button
                    key={star}
                    onClick={() => handleSetRating(star)}
                    onMouseEnter={() => setRatingHover(star)}
                    disabled={savingRating}
                    aria-label={`Rate ${star} star${star > 1 ? 's' : ''}`}
                    style={{
                      fontSize: '1.4rem',
                      color: filled ? '#f59e0b' : 'rgba(255,255,255,0.2)',
                      background: 'none',
                      border: 'none',
                      padding: '0 2px',
                      cursor: savingRating ? 'wait' : 'pointer',
                      transition: 'color 0.1s',
                      lineHeight: 1,
                    }}
                  >
                    ★
                  </button>
                )
              })}
            </div>
          </div>

          {/* ── Text Extraction (images only) ───────────────────── */}
          {current.mediaType === 'image' && (
            <div style={{ borderTop: '1px solid rgba(255,255,255,0.1)', paddingTop: '0.75rem' }}>
              <div className="flex items-center justify-between mb-2">
                <p className="text-xs font-semibold uppercase tracking-wider" style={{ color: 'rgba(255,255,255,0.45)' }}>
                  Text Extraction
                </p>
                <button
                  onClick={() => callExtract('llm')}
                  disabled={extracting || extractPending}
                  className="w-7 h-7 rounded-full flex items-center justify-center transition-opacity disabled:opacity-40"
                  style={{
                    backgroundColor: extractPending ? 'var(--accent)' : 'rgba(255,255,255,0.12)',
                    color: extractPending ? '#fff' : 'rgba(255,255,255,0.7)',
                    fontSize: '0.95rem',
                  }}
                  aria-label="Extract with AI"
                  title="Extract with AI (skips OCR)"
                >
                  {extracting || extractPending ? <span className="animate-spin" style={{ display: 'inline-block' }}>⟳</span> : '✨'}
                </button>
              </div>

              <div className="flex items-center gap-2 flex-wrap">
                <button
                  onClick={() => callExtract('tesseract')}
                  disabled={extracting || extractPending}
                  className="text-xs px-2 py-1 rounded-lg transition-colors disabled:opacity-40 flex-shrink-0"
                  style={{ backgroundColor: 'rgba(255,255,255,0.1)', color: 'rgba(255,255,255,0.7)' }}
                >
                  {extracting ? '⟳ Scanning…' : extractedText ? '🔍 Re-scan with OCR' : '🔍 Scan with OCR'}
                </button>
                <input
                  type="text"
                  value={ocrLanguageInput}
                  onChange={(e) => setOcrLanguageInput(e.target.value)}
                  placeholder={defaultOcrLanguages}
                  className="text-xs px-2 py-0.5 rounded-full outline-none"
                  style={{
                    backgroundColor: 'rgba(255,255,255,0.07)',
                    border: '1px solid rgba(255,255,255,0.15)',
                    color: 'rgba(255,255,255,0.85)',
                    width: 120,
                  }}
                  title="Tesseract language(s) for this extraction (e.g. jpn+jpn_vert). Leave blank to use the configured default."
                />
              </div>

              {extractError && (
                <p className="text-xs mt-1" style={{ color: '#f87171' }}>{extractError}</p>
              )}

              {/* Extracted text editor */}
              {extractedText !== null && (
                <div className="flex flex-col gap-1 mt-2">
                  <p className="text-xs font-medium" style={{ color: 'rgba(255,255,255,0.45)' }}>Extracted Text</p>
                  <textarea
                    value={editedExtractedText}
                    onChange={(e) => setEditedExtractedText(e.target.value)}
                    className="text-xs rounded-lg p-2 w-full resize-y outline-none"
                    style={{
                      backgroundColor: 'rgba(255,255,255,0.07)',
                      border: '1px solid rgba(255,255,255,0.15)',
                      color: 'rgba(255,255,255,0.9)',
                      minHeight: '3.5rem',
                      maxHeight: '8rem',
                      fontFamily: 'inherit',
                    }}
                  />
                  {editedExtractedText !== extractedText && (
                    <button
                      onClick={handleSaveExtractedText}
                      disabled={savingText}
                      className="self-start text-xs px-2 py-0.5 rounded-full transition-opacity disabled:opacity-50"
                      style={{ backgroundColor: 'var(--accent)', color: '#fff' }}
                    >
                      {savingText ? '⟳ Saving…' : 'Save'}
                    </button>
                  )}

                  {/* Translation display */}
                  {translatedText && (
                    <div className="mt-1">
                      <p className="text-xs font-medium mb-1" style={{ color: 'rgba(255,255,255,0.45)' }}>Translation</p>
                      <pre
                        className="text-xs whitespace-pre-wrap rounded-lg p-2 max-h-32 overflow-y-auto"
                        style={{
                          backgroundColor: 'rgba(255,255,255,0.07)',
                          border: '1px solid rgba(255,255,255,0.15)',
                          color: 'rgba(255,255,255,0.9)',
                        }}
                      >
                        {translatedText}
                      </pre>
                    </div>
                  )}

                  {/* Original / translation toggle */}
                  {extractedText && translatedText && (
                    <button
                      onClick={() => setShowOriginal((v) => !v)}
                      className="self-start text-xs px-2 py-0.5 rounded-full mt-1"
                      style={{ backgroundColor: 'rgba(255,255,255,0.12)', color: 'rgba(255,255,255,0.7)' }}
                    >
                      {showOriginal ? 'Show Translation in popover' : 'Show Original in popover'}
                    </button>
                  )}

                  {/* Translate / re-translate */}
                  <div className="flex items-center gap-1.5 flex-wrap mt-1">
                    <input
                      type="text"
                      value={sourceLanguage}
                      onChange={(e) => setSourceLanguage(e.target.value)}
                      placeholder="Source lang…"
                      className="text-xs px-2 py-0.5 rounded-full outline-none"
                      style={{
                        backgroundColor: 'rgba(255,255,255,0.07)',
                        border: '1px solid rgba(255,255,255,0.15)',
                        color: 'rgba(255,255,255,0.85)',
                        width: 100,
                      }}
                    />
                    <button
                      onClick={handleTranslate}
                      disabled={retranslating || translatePending}
                      className="text-xs px-2 py-0.5 rounded-full transition-colors disabled:opacity-40"
                      style={{
                        backgroundColor: translatePending ? 'var(--accent)' : 'rgba(255,255,255,0.12)',
                        color: translatePending ? '#fff' : 'rgba(255,255,255,0.7)',
                      }}
                    >
                      {retranslating ? '⟳ Translating…' : translatePending ? '⟳ Queued…' : translatedText ? '🌐 Re-translate' : '🌐 Translate'}
                    </button>
                  </div>
                </div>
              )}
            </div>
          )}
        </div>
      )}

      {/* Text overlay */}
      {showTextOverlay && displayText && (
        <div
          className="absolute bottom-4 left-4 right-4 z-20 rounded-xl p-4 max-w-fit"
          style={{ backgroundColor: 'rgba(0,0,0,0.75)' }}
          onClick={(e) => e.stopPropagation()}
        >
          {extractedText && translatedText && (
            <div className="flex justify-end mb-2">
              <button
                onClick={() => setShowOriginal((v) => !v)}
                className="text-xs px-2 py-0.5 rounded-full"
                style={{ backgroundColor: 'rgba(255,255,255,0.15)', color: 'rgba(255,255,255,0.7)' }}
              >
                {showOriginal ? 'Show Translation' : 'Show Original'}
              </button>
            </div>
          )}
          <p className="text-sm whitespace-pre-wrap" style={{ color: 'rgba(255,255,255,0.9)' }}>
            {displayText}
          </p>
        </div>
      )}

      {/* Bottom bar: [mute + tools] | filename | action buttons */}
      <div className="absolute bottom-0 left-0 right-0 flex items-center gap-3 px-4 pb-3 pt-2 z-10">
        <div className="flex items-center gap-1 flex-shrink-0">
          {isVideo && (
            <button
              onClick={() => setLocalMuted((v) => !v)}
              className="w-9 h-9 rounded-full flex items-center justify-center transition-opacity hover:opacity-100 opacity-70"
              style={{ backgroundColor: 'rgba(0,0,0,0.5)', color: '#fff' }}
              aria-label={localMuted ? 'Unmute' : 'Mute'}
            >
              {localMuted ? (
                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/>
                  <line x1="23" y1="9" x2="17" y2="15"/>
                  <line x1="17" y1="9" x2="23" y2="15"/>
                </svg>
              ) : (
                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/>
                  <path d="M19.07 4.93a10 10 0 0 1 0 14.14"/>
                  <path d="M15.54 8.46a5 5 0 0 1 0 7.07"/>
                </svg>
              )}
            </button>
          )}
          {current?.itemKey && (
            <button
              onClick={() => setShowToolsOverlay((v) => !v)}
              className="w-9 h-9 rounded-full flex items-center justify-center transition-opacity hover:opacity-100 opacity-70"
              style={{
                backgroundColor: showToolsOverlay ? 'rgba(255,255,255,0.2)' : 'rgba(0,0,0,0.5)',
                color: '#fff',
              }}
              aria-label={showToolsOverlay ? 'Close tools' : 'Open tools'}
              title="Rating &amp; text tools"
            >
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <circle cx="12" cy="12" r="3"/>
                <path d="M19.07 4.93a10 10 0 0 1 0 14.14M4.93 4.93a10 10 0 0 0 0 14.14"/>
                <line x1="12" y1="2" x2="12" y2="5"/>
                <line x1="12" y1="19" x2="12" y2="22"/>
                <line x1="2" y1="12" x2="5" y2="12"/>
                <line x1="19" y1="12" x2="22" y2="12"/>
              </svg>
            </button>
          )}
        </div>
        <span className="flex-1 text-xs truncate text-center" style={{ color: 'rgba(255,255,255,0.4)' }}>
          {current?.name}
        </span>
        <div className="flex-shrink-0 flex items-center gap-1">
          {extractedText ? (
            <button
              onClick={() => setShowTextOverlay((v) => !v)}
              className="w-9 h-9 rounded-full flex items-center justify-center transition-opacity hover:opacity-100 opacity-70"
              style={{
                backgroundColor: showTextOverlay ? 'rgba(255,255,255,0.2)' : 'rgba(0,0,0,0.5)',
                color: '#fff',
              }}
              aria-label={showTextOverlay ? 'Hide text' : 'Show text'}
            >
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <line x1="3" y1="6" x2="21" y2="6"/>
                <line x1="3" y1="12" x2="15" y2="12"/>
                <line x1="3" y1="18" x2="18" y2="18"/>
              </svg>
            </button>
          ) : current?.itemKey && current?.mediaType === 'image' ? (
            <button
              onClick={() => callExtract('tesseract')}
              disabled={extracting || extractPending}
              className="w-9 h-9 rounded-full flex items-center justify-center transition-opacity hover:opacity-100 opacity-70 disabled:opacity-40"
              style={{
                backgroundColor: extractPending
                  ? 'var(--accent)'
                  : extractError
                    ? 'rgba(127,29,29,0.8)'
                    : 'rgba(0,0,0,0.5)',
                color: extractError ? '#fca5a5' : '#fff',
              }}
              aria-label={extractPending ? 'Extracting text…' : 'Extract text'}
              title={extractPending ? 'Queued — extracting text…' : extractError ?? 'Extract text'}
            >
              {extracting || extractPending ? (
                <span className="animate-spin" style={{ display: 'inline-block', fontSize: '0.75rem' }}>⟳</span>
              ) : (
                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
                  <polyline points="14 2 14 8 20 8"/>
                  <line x1="16" y1="13" x2="8" y2="13"/>
                  <line x1="16" y1="17" x2="8" y2="17"/>
                  <polyline points="10 9 9 9 8 9"/>
                </svg>
              )}
            </button>
          ) : null}
          {onViewInLibrary && current?.itemKey && (
            <button
              onClick={(e) => { e.stopPropagation(); onViewInLibrary(current) }}
              className="w-9 h-9 rounded-full flex items-center justify-center transition-opacity hover:opacity-100 opacity-70"
              style={{ backgroundColor: 'rgba(0,0,0,0.5)', color: '#fff' }}
              aria-label="View in library"
            >
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
                <polyline points="9 22 9 12 15 12 15 22"/>
              </svg>
            </button>
          )}
        </div>
      </div>

      {/* Auto-play progress bar — key on current URL restarts animation on each new item */}
      {autoPlayEnabled && !isPaused && (
        <div
          key={current?.url}
          className="absolute bottom-0 left-0 h-0.5 z-20"
          style={{
            backgroundColor: 'var(--accent)',
            animationName: 'doom-progress',
            animationDuration: `${autoPlaySeconds}s`,
            animationTimingFunction: 'linear',
            animationFillMode: 'forwards',
          }}
        />
      )}

      {/* Prev / Next hint arrows */}
      {historyIndex > 0 && (
        <button
          onClick={() => navigate('prev')}
          className="absolute left-1/2 top-16 -translate-x-1/2 w-10 h-10 rounded-full flex items-center justify-center text-xl transition-opacity hover:opacity-100 opacity-50 z-10"
          style={{ backgroundColor: 'rgba(0,0,0,0.4)', color: '#fff' }}
          aria-label="Previous"
        >
          ↑
        </button>
      )}
      <button
        onClick={() => navigate('next')}
        className="absolute left-1/2 bottom-14 -translate-x-1/2 w-10 h-10 rounded-full flex items-center justify-center text-xl transition-opacity hover:opacity-100 opacity-50 z-10"
        style={{ backgroundColor: 'rgba(0,0,0,0.4)', color: '#fff' }}
        aria-label="Next"
      >
        ↓
      </button>
    </div>
  )
}
