'use client';

import '../utils/arabicFontFix.js';
import { useEffect } from 'react';

// ─── Constants ────────────────────────────────────────────────────────────────
const MAX_ELEMENT_RETRIES  = 3;
const PENDING_TIMEOUT_MS   = 20_000;
const FAST_POLL_MS         = 500;
const FAST_POLL_DURATION   = 15_000;
const SLOW_POLL_MS         = 3_000;
const SLOW_POLL_DURATION   = 45_000;
const INITIAL_SCAN_DELAYS  = [50, 250, 600, 1200, 2500, 4500];

export default function VttEngine({ articleRef, slug, htmlContent }) {
  useEffect(() => {
    if (!htmlContent) return;

    const articleEl = articleRef.current;
    if (!articleEl) return;

    // ── Lifecycle guard
    const abortController = new AbortController();
    let isActive = true;

    // ── Per-run state
    const inFlightElements  = new WeakSet();
    const processedSrcs     = new Set();
    const retryCounts       = new WeakMap();
    const pendingTimestamps = new WeakMap();

    // ── Cleanup registry
    const cleanupFns = [];
    const safeCleanup = () => cleanupFns.forEach(fn => { try { fn(); } catch (_) {} });
    cleanupFns.push(() => { isActive = false; abortController.abort(); });

    // ── Wipe stale flags from previous render
    const querySelectorStr = 'video, audio, iframe, .tuwa-subtitle-box';
    articleEl.querySelectorAll(querySelectorStr)
      .forEach(el => el.removeAttribute('data-vtt-processed'));
    articleEl.querySelectorAll('.tuwa-subtitle-overlay')
      .forEach(o => o.remove());

    // ── VTT parsing
    const parseVttTime = (timeStr) => {
      if (!timeStr) return 0;
      const clean = timeStr.trim().split(/\s+/)[0].replace(',', '.');
      const parts  = clean.split(':');
      let s = 0;
      if (parts.length === 3) s = +parts[0] * 3600 + +parts[1] * 60 + +parts[2];
      else if (parts.length === 2) s = +parts[0] * 60 + +parts[1];
      else s = +parts[0];
      return isNaN(s) ? 0 : s;
    };

    const parseVtt = (vttText) => {
      const cues  = [];
      const lines = vttText.replace(/\r\n/g, '\n').split('\n');
      let cur = null;

      for (let line of lines) {
        line = line.trim();
        if (!line) {
          if (cur?.textLines.length) {
            cues.push({ start: cur.start, end: cur.end, text: cur.textLines.join('<br>') });
          }
          cur = null;
          continue;
        }
        if (/^(WEBVTT|Kind:|Language:|NOTE)/.test(line)) continue;
        if (line.includes('-->')) {
          if (cur?.textLines.length) {
            cues.push({ start: cur.start, end: cur.end, text: cur.textLines.join('<br>') });
          }
          const [t0, t1] = line.split('-->');
          cur = { start: parseVttTime(t0), end: parseVttTime(t1), textLines: [] };
        } else if (cur) {
          if (!line.match(/^\d+$/) || cur.textLines.length > 0) {
            cur.textLines.push(line);
          }
        }
      }
      if (cur?.textLines.length) {
        cues.push({ start: cur.start, end: cur.end, text: cur.textLines.join('<br>') });
      }
      return cues;
    };

    // ── Overlay creation
    const createOverlay = (container, isStandaloneBox) => {
      let existing = null;
      try {
        existing = container.querySelector(':scope > .tuwa-subtitle-overlay');
      } catch (e) {
        existing = Array.from(container.children).find(c => c.classList.contains('tuwa-subtitle-overlay'));
      }
      if (existing) return existing;

      const overlay = document.createElement('div');
      overlay.className = 'tuwa-subtitle-overlay';
      overlay.style.zIndex      = '9999';
      overlay.style.padding     = '0 20px';
      overlay.style.boxSizing   = 'border-box';
      overlay.style.minHeight   = '44px';
      overlay.style.display     = 'block';
      overlay.style.width       = '100%';
      overlay.style.textAlign   = 'center';

      if (isStandaloneBox) {
        overlay.style.position   = 'relative';
        overlay.style.marginTop  = '10px';
      } else {
        if (window.getComputedStyle(container).position === 'static') {
          container.style.position = 'relative';
        }
        overlay.style.position      = 'absolute';
        overlay.style.bottom        = '8%';
        overlay.style.left          = '0';
        overlay.style.pointerEvents = 'none';
      }

      container.appendChild(overlay);
      return overlay;
    };

    // ── Subtitle updater
    const attachSubtitleUpdater = (overlay, cues, originalMediaEl) => {
      let lastCueText = null;
      let mediaEl = originalMediaEl;

      const updateSubtitle = (currentTime) => {
        if (!isActive) return;
        const activeCue = cues.find(c => currentTime >= c.start && currentTime <= c.end);
        const newText   = activeCue ? activeCue.text : null;
        if (newText === lastCueText) return;
        lastCueText = newText;
        overlay.innerHTML = newText
          ? `<span style="background:rgba(0,0,0,0.82);color:#fff;padding:5px 14px;border-radius:6px;font-size:1.05rem;line-height:1.6;display:inline-block;text-shadow:1px 1px 2px #000;font-family:sans-serif;">${newText}</span>`
          : '';
      };

      const tag = mediaEl.tagName.toLowerCase();

      // Native MP4 Video/Audio Fixes
      if (tag === 'video' || tag === 'audio') {
        updateSubtitle(mediaEl.currentTime || 0);
        
        const onTimeUpdate = () => updateSubtitle(mediaEl.currentTime);
        
        mediaEl.addEventListener('timeupdate', onTimeUpdate);
        mediaEl.addEventListener('play', onTimeUpdate);
        mediaEl.addEventListener('seeking', onTimeUpdate);
        mediaEl.addEventListener('seeked', onTimeUpdate);
        
        cleanupFns.push(() => {
          mediaEl.removeEventListener('timeupdate', onTimeUpdate);
          mediaEl.removeEventListener('play', onTimeUpdate);
          mediaEl.removeEventListener('seeking', onTimeUpdate);
          mediaEl.removeEventListener('seeked', onTimeUpdate);
        });

      } else if (tag === 'iframe') {
        let newSrc = mediaEl.src || '';
        const isYouTube = newSrc.includes('youtube.com') || newSrc.includes('youtu.be');
        
        // Guard: Do not touch non-YouTube iframes (e.g., MP4s embedded via third-party iframe)
        if (!isYouTube) return; 

        let needsReplace = false;
        
        try {
          const url = new URL(newSrc);
          if (!url.searchParams.has('enablejsapi') || !url.searchParams.has('origin')) {
            url.searchParams.set('enablejsapi', '1');
            url.searchParams.set('origin', window.location.origin);
            newSrc = url.toString();
            needsReplace = true;
          }
        } catch (_) {
          if (!newSrc.includes('enablejsapi=1')) {
            newSrc += (newSrc.includes('?') ? '&' : '?') + 'enablejsapi=1&origin=' + encodeURIComponent(window.location.origin);
            needsReplace = true;
          }
        }

        // SPA Fix: Clone and replace iframe to prevent YouTube connection handshake drops
        if (needsReplace) {
          const clone = mediaEl.cloneNode(true);
          if (!clone.id) clone.id = `yt-iframe-${Math.random().toString(36).substr(2, 9)}`;
          clone.src = newSrc;
          if (mediaEl.parentNode) {
            mediaEl.parentNode.replaceChild(clone, mediaEl);
          }
          mediaEl = clone;
        } else {
          if (!mediaEl.id) mediaEl.id = `yt-iframe-${Math.random().toString(36).substr(2, 9)}`;
        }

        let pollingStarted = false;
        let ytPlayerInstance = null;

        const startYTPolling = (ytPlayer) => {
          if (pollingStarted || !isActive) return;
          pollingStarted = true;
          const interval = setInterval(() => {
            if (!isActive) { clearInterval(interval); return; }
            try {
              if (typeof ytPlayer.getCurrentTime === 'function') {
                const time = ytPlayer.getCurrentTime();
                if (time !== undefined && time !== null) {
                  updateSubtitle(time);
                }
              }
            } catch (_) {}
          }, 100);
          cleanupFns.push(() => clearInterval(interval));
        };

        const setupYT = () => {
          if (!isActive) return;
          let isReady = false;
          
          const ytPlayer = new window.YT.Player(mediaEl, {
            events: {
              onReady: (e) => {
                isReady = true;
                if (!isActive) { try { e.target.destroy(); } catch (_) {} return; }
                ytPlayerInstance = e.target;
                startYTPolling(e.target);
              },
            },
          });

          // Fallback if YouTube API misses the onReady event due to network delay
          const fallbackTimer = setTimeout(() => {
            if (!isReady && isActive && ytPlayer && typeof ytPlayer.getCurrentTime === 'function') {
              ytPlayerInstance = ytPlayer;
              startYTPolling(ytPlayer);
            }
          }, 3000);

          cleanupFns.push(() => {
            clearTimeout(fallbackTimer);
            try { (ytPlayerInstance || ytPlayer).destroy(); ytPlayerInstance = null; } catch (_) {}
          });
        };

        if (window.YT?.Player) {
          setupYT();
        } else {
          window.ytQueue = window.ytQueue || [];
          window.ytQueue.push(setupYT);
        }
      }
    };

    // ── Fetch with retry
    const fetchVttWithRetry = async (url, signal, maxRetries = 3) => {
      let lastError;
      for (let attempt = 0; attempt < maxRetries; attempt++) {
        if (!isActive || signal.aborted) throw new DOMException('Aborted', 'AbortError');
        try {
          const res = await fetch(url, { signal });
          if (res.ok) return await res.text();
          const err = new Error(`HTTP ${res.status}`);
          if (res.status >= 400 && res.status < 500) throw err;
          throw err;
        } catch (err) {
          if (err.name === 'AbortError') throw err;
          lastError = err;
          if (attempt < maxRetries - 1) {
            await new Promise(r => setTimeout(r, 500 * (2 ** attempt)));
          }
        }
      }
      throw lastError;
    };

    // ── Core init for a single element
    const initSingleSubtitle = async (targetEl) => {
      if (!isActive) return;

      if (
        targetEl.tagName === 'IFRAME' &&
        !targetEl.dataset.vtt &&
        !targetEl.closest('.tuwa-subtitle-box')
      ) {
        targetEl.dataset.vttProcessed = 'ignored';
        return;
      }

      const currentState = targetEl.dataset.vttProcessed;

      if (currentState === 'pending') {
        const start = pendingTimestamps.get(targetEl);
        if (start && Date.now() - start > PENDING_TIMEOUT_MS) {
          targetEl.removeAttribute('data-vtt-processed');
          try { inFlightElements.delete(targetEl); } catch (_) {}
          pendingTimestamps.delete(targetEl);
        } else {
          return; 
        }
      }

      if (
        inFlightElements.has(targetEl)  ||
        currentState === 'true'         ||
        currentState === 'ignored'
      ) return;

      if (currentState === 'error') {
        const retries = retryCounts.get(targetEl) || 0;
        if (retries >= MAX_ELEMENT_RETRIES) return;
      }

      let mediaEl = null, container = null, vttUrl = null, isStandaloneBox = false;

      if (targetEl.classList.contains('tuwa-subtitle-box')) {
        isStandaloneBox = true;
        container       = targetEl;
        const mediaId   = targetEl.dataset.video || targetEl.dataset.youtube || null;
        vttUrl          = targetEl.dataset.vtt   || null;
        mediaEl         = targetEl.querySelector('video, audio, iframe');

        if (!mediaEl && mediaId) {
          mediaEl = articleEl?.querySelector(`#${CSS.escape(mediaId)}`)
                 || articleEl?.querySelector(`[data-media-id="${CSS.escape(mediaId)}"]`);
        }
      } else {
        mediaEl   = targetEl;
        vttUrl    = targetEl.dataset.vtt || null;
        container = targetEl.parentElement;

        if (!vttUrl) {
          const box = targetEl.closest('.tuwa-subtitle-box');
          if (box) {
            vttUrl          = box.dataset.vtt || null;
            container       = box;
            isStandaloneBox = true;
          }
        }
      }

      if (!vttUrl) { targetEl.dataset.vttProcessed = 'ignored'; return; }
      if (!mediaEl) return;
      if (!container) container = mediaEl.parentElement;

      // Extract raw source URL to prevent duplicate processing on rerenders
      let mediaSrc = mediaEl.src || mediaEl.currentSrc || '';
      if (!mediaSrc && mediaEl.tagName === 'VIDEO') {
        const source = mediaEl.querySelector('source');
        if (source) mediaSrc = source.src || '';
      }
      
      const mediaIdentifier = mediaSrc.split('?')[0] || mediaEl.id || Math.random().toString();
      const srcKey = `${vttUrl}||${mediaIdentifier}`;

      if (processedSrcs.has(srcKey)) {
        targetEl.dataset.vttProcessed = 'true';
        return;
      }

      inFlightElements.add(targetEl);
      targetEl.dataset.vttProcessed = 'pending';
      pendingTimestamps.set(targetEl, Date.now());

      try {
        const vttText = await fetchVttWithRetry(vttUrl, abortController.signal);
        if (!isActive) return;

        const cues = parseVtt(vttText);

        if (cues.length > 0) {
          const overlay = createOverlay(container, isStandaloneBox);
          attachSubtitleUpdater(overlay, cues, mediaEl);
          processedSrcs.add(srcKey);
          targetEl.dataset.vttProcessed = 'true';
          retryCounts.delete(targetEl);
        } else {
          targetEl.dataset.vttProcessed = 'error';
          retryCounts.set(targetEl, (retryCounts.get(targetEl) || 0) + 1);
        }

      } catch (err) {
        if (err.name === 'AbortError') return; 

        if (isActive) {
          targetEl.dataset.vttProcessed = 'error';
          retryCounts.set(targetEl, (retryCounts.get(targetEl) || 0) + 1);
          console.warn('[VttEngine] VTT fetch failed:', err.message, '→', vttUrl);
        }

      } finally {
        pendingTimestamps.delete(targetEl);
        try { inFlightElements.delete(targetEl); } catch (_) {}
      }
    };

    const scanAndInit = () => {
      if (!isActive || !articleEl?.isConnected) return;
      articleEl.querySelectorAll(querySelectorStr).forEach(el => initSingleSubtitle(el));
    };

    const onMediaPlay = (e) => {
      if (!isActive) return;
      const target = e.target;
      if (!target || !['VIDEO', 'AUDIO', 'IFRAME'].includes(target.tagName)) return;

      const state = target.dataset.vttProcessed;

      if (state !== 'true') {
        if (state === 'error' || state === 'ignored' || state === 'pending') {
          target.removeAttribute('data-vtt-processed');
          retryCounts.delete(target);
          try { inFlightElements.delete(target); } catch (_) {}
          pendingTimestamps.delete(target);
        }

        let box = target.closest('.tuwa-subtitle-box');
        
        // Native MP4 fix: Lookup sibling subtitle box by ID connection
        if (!box) {
          const mediaId = target.id || target.dataset.mediaId;
          if (mediaId) {
            try {
              box = articleEl.querySelector(`.tuwa-subtitle-box[data-video="${CSS.escape(mediaId)}"], .tuwa-subtitle-box[data-youtube="${CSS.escape(mediaId)}"]`);
            } catch (_) {}
          }
        }

        if (box && box.dataset.vttProcessed !== 'true') {
          box.removeAttribute('data-vtt-processed');
          retryCounts.delete(box);
          try { inFlightElements.delete(box); } catch (_) {}
          pendingTimestamps.delete(box);
        }

        setTimeout(() => {
          if (!isActive) return;
          initSingleSubtitle(target);
          if (box) initSingleSubtitle(box);
        }, 200);
      }
    };

    articleEl.addEventListener('play', onMediaPlay, true /* capture */);
    cleanupFns.push(() => articleEl.removeEventListener('play', onMediaPlay, true));

    const onVisibilityChange = () => {
      if (document.visibilityState === 'visible' && isActive) {
        setTimeout(scanAndInit, 300);
      }
    };
    document.addEventListener('visibilitychange', onVisibilityChange);
    cleanupFns.push(() => document.removeEventListener('visibilitychange', onVisibilityChange));

    const onOnline = () => { if (isActive) setTimeout(scanAndInit, 500); };
    window.addEventListener('online', onOnline);
    cleanupFns.push(() => window.removeEventListener('online', onOnline));

    requestAnimationFrame(() => {
      INITIAL_SCAN_DELAYS.forEach(delay => {
        const t = setTimeout(() => { if (isActive) scanAndInit(); }, delay);
        cleanupFns.push(() => clearTimeout(t));
      });
    });

    const fastPoll = setInterval(scanAndInit, FAST_POLL_MS);

    const slowPollTimer = setTimeout(() => {
      clearInterval(fastPoll);
      if (!isActive) return;

      const slowPoll    = setInterval(scanAndInit, SLOW_POLL_MS);
      const stopSlowPoll = setTimeout(() => clearInterval(slowPoll), SLOW_POLL_DURATION);

      cleanupFns.push(() => { clearInterval(slowPoll); clearTimeout(stopSlowPoll); });
    }, FAST_POLL_DURATION);

    cleanupFns.push(() => { clearInterval(fastPoll); clearTimeout(slowPollTimer); });

    if (!window.tuwaYTInitialized) {
      window.tuwaYTInitialized = true;
      const prev = window.onYouTubeIframeAPIReady;
      window.onYouTubeIframeAPIReady = () => {
        if (prev) prev();
        (window.ytQueue || []).forEach(fn => { try { fn(); } catch (_) {} });
        window.ytQueue = [];
      };
    }

    if (
      articleEl.querySelector('iframe') &&
      !document.querySelector('script[src="https://www.youtube.com/iframe_api"]')
    ) {
      const s   = document.createElement('script');
      s.src     = 'https://www.youtube.com/iframe_api';
      document.head.appendChild(s);
    }

    return () => {
      safeCleanup();
      try {
        articleEl.querySelectorAll(querySelectorStr)
          .forEach(el => el.removeAttribute('data-vtt-processed'));
        articleEl.querySelectorAll('.tuwa-subtitle-overlay')
          .forEach(o => { o.innerHTML = ''; o.remove(); });
      } catch (_) {}
    };

  }, [articleRef, slug, htmlContent]);

  return null;
}