import { useRef, useEffect, useState, useMemo } from 'react';
import { VTTParser, type VTTCue } from '../lib/vtt';
import { getLanguageLabel } from '../utils/language';

interface LanguageTrack {
  language: string;
  label: string;
  captionsVtt?: string;
  audioDescriptionVtt?: string;
  audioDescriptionUrl?: string;
}

interface VideoWithCaptionsProps {
  videoUrl: string;
  tracks?: LanguageTrack[];
  // Legacy single-language props (still supported)
  captionsVtt?: string;
  audioDescriptionVtt?: string;
  audioDescriptionUrl?: string;
  sourceLanguage?: string; // Language code for legacy props (e.g., 'en', 'de', 'es')
  className?: string;
}

export function VideoWithCaptions({
  videoUrl,
  tracks = [],
  // Legacy props
  captionsVtt,
  audioDescriptionVtt,
  audioDescriptionUrl,
  sourceLanguage = 'en',
  className = ''
}: VideoWithCaptionsProps) {
  const videoRef = useRef<HTMLVideoElement>(null);
  const timelineRef = useRef<HTMLDivElement>(null);
  const [currentTime, setCurrentTime] = useState(0);
  const [showCaptions, setShowCaptions] = useState(true);
  const [showAudioDescription, setShowAudioDescription] = useState(false);
  const [selectedLanguage, setSelectedLanguage] = useState('');
  const [languageCues, setLanguageCues] = useState<Record<string, { captions: VTTCue[]; ad: VTTCue[] }>>({});

  // Combine legacy props with tracks (use useMemo to prevent recreation)
  const allTracks = useMemo(() => {
    const combined = [...tracks];
    if (captionsVtt || audioDescriptionVtt) {
      combined.unshift({
        language: sourceLanguage,
        label: getLanguageLabel(sourceLanguage),
        captionsVtt,
        audioDescriptionVtt,
        audioDescriptionUrl
      });
    }
    return combined;
  }, [tracks, captionsVtt, audioDescriptionVtt, audioDescriptionUrl, sourceLanguage]);

  // Set initial language selection
  useEffect(() => {
    if (allTracks.length > 0 && !selectedLanguage) {
      setSelectedLanguage(allTracks[0].language);
    }
  }, [allTracks]);

  // Parse VTT content for all tracks
  useEffect(() => {
    if (allTracks.length === 0) return;
    
    const newLanguageCues: Record<string, { captions: VTTCue[]; ad: VTTCue[] }> = {};
    
    for (const track of allTracks) {
      const captions: VTTCue[] = [];
      const ad: VTTCue[] = [];
      
      if (track.captionsVtt) {
        try {
          console.log(`Raw VTT content for ${track.language}:`, track.captionsVtt.substring(0, 500));
          const parsedCues = VTTParser.parse(track.captionsVtt);
          console.log(`Parsed ${parsedCues.length} cues for ${track.language}:`, parsedCues.slice(0, 3));
          captions.push(...parsedCues);
        } catch (error) {
          console.error(`Failed to parse captions VTT for ${track.language}:`, error);
        }
      }
      
      if (track.audioDescriptionVtt) {
        try {
          ad.push(...VTTParser.parse(track.audioDescriptionVtt));
        } catch (error) {
          console.error(`Failed to parse audio description VTT for ${track.language}:`, error);
        }
      }
      
      newLanguageCues[track.language] = { captions, ad };
    }
    
    // Only update if the content has actually changed
    setLanguageCues(prevCues => {
      const hasChanged = JSON.stringify(prevCues) !== JSON.stringify(newLanguageCues);
      return hasChanged ? newLanguageCues : prevCues;
    });
  }, [allTracks]);

  // Update current time
  useEffect(() => {
    const video = videoRef.current;
    if (!video) return;

    let timeoutId: ReturnType<typeof setTimeout>;
    const handleTimeUpdate = () => {
      clearTimeout(timeoutId);
      timeoutId = setTimeout(() => {
        setCurrentTime(video.currentTime);
      }, 100); // Throttle updates to every 100ms
    };

    video.addEventListener('timeupdate', handleTimeUpdate);
    return () => {
      video.removeEventListener('timeupdate', handleTimeUpdate);
      clearTimeout(timeoutId);
    };
  }, []);

  // Get current track data (memoized)
  const currentTrack = useMemo(() => 
    allTracks.find(track => track.language === selectedLanguage),
    [allTracks, selectedLanguage]
  );
  
  const currentCues = useMemo(() => 
    languageCues[selectedLanguage] || { captions: [], ad: [] },
    [languageCues, selectedLanguage]
  );

  // Find current caption and audio description (memoized)
  const currentCaption = useMemo(() =>
    currentCues.captions.find(
      cue => currentTime >= cue.startTime && currentTime <= cue.endTime
    ),
    [currentCues.captions, currentTime]
  );

  const currentAD = useMemo(() =>
    currentCues.ad.find(
      cue => currentTime >= cue.startTime && currentTime <= cue.endTime
    ),
    [currentCues.ad, currentTime]
  );

  // Auto-scroll to current caption
  useEffect(() => {
    if (currentCaption && timelineRef.current) {
      const timelineContainer = timelineRef.current;
      const currentCaptionIndex = currentCues.captions.findIndex(
        cue => cue === currentCaption
      );
      
      if (currentCaptionIndex !== -1) {
        const captionElements = timelineContainer.children;
        const currentElement = captionElements[currentCaptionIndex] as HTMLElement;
        
        if (currentElement) {
          // Get actual rendered positions
          const elementRect = currentElement.getBoundingClientRect();
          const containerRect = timelineContainer.getBoundingClientRect();
          
          // Calculate element position relative to container
          const elementTopInContainer = elementRect.top - containerRect.top + timelineContainer.scrollTop;
          const elementBottomInContainer = elementTopInContainer + elementRect.height;
          
          const containerHeight = timelineContainer.clientHeight;
          const currentScrollTop = timelineContainer.scrollTop;
          const visibleTop = currentScrollTop;
          const visibleBottom = currentScrollTop + containerHeight;
          
          // Check if element is outside visible area
          const isAbove = elementTopInContainer < visibleTop;
          const isBelow = elementBottomInContainer > visibleBottom;
          
          if (isAbove || isBelow) {
            // Calculate scroll position to center the element
            const targetScrollTop = elementTopInContainer - (containerHeight / 2) + (elementRect.height / 2);
            
            timelineContainer.scrollTo({
              top: Math.max(0, targetScrollTop),
              behavior: 'smooth'
            });
          }
        }
      }
    }
  }, [currentCaption, currentCues.captions]);

  const jumpToTime = (time: number) => {
    const video = videoRef.current;
    if (video && !video.ended) {
      video.currentTime = time;
      // Don't auto-play, let user manually play if they want
    }
  };

  return (
    <div className={`space-y-4 ${className}`}>
      {/* Video Player */}
      <div className="relative bg-black rounded-lg overflow-hidden">
        <video
          ref={videoRef}
          src={videoUrl}
          controls
          className="w-full h-auto"
        >
          Your browser does not support the video tag.
        </video>
        
        {/* Caption Overlay */}
        {showCaptions && currentCaption && (
          <div className="absolute bottom-16 left-1/2 transform -translate-x-1/2 bg-black bg-opacity-80 text-white px-4 py-2 rounded max-w-[90%]">
            <div className="text-center whitespace-pre-wrap">
              {currentCaption.text}
            </div>
          </div>
        )}
      </div>

      {/* Controls */}
      <div className="flex flex-wrap gap-4 items-center">
        {allTracks.length > 1 && (
          <div className="flex items-center">
            <label htmlFor="language-select" className="text-sm mr-2">Language:</label>
            <select
              id="language-select"
              value={selectedLanguage}
              onChange={(e) => setSelectedLanguage(e.target.value)}
              className="text-sm border border-gray-300 rounded px-2 py-1"
            >
              {allTracks.map((track) => (
                <option key={track.language} value={track.language}>
                  {track.label}
                </option>
              ))}
            </select>
          </div>
        )}
        
        <label className="flex items-center">
          <input
            type="checkbox"
            checked={showCaptions}
            onChange={(e) => setShowCaptions(e.target.checked)}
            className="mr-2"
          />
          <span className="text-sm">Show Captions</span>
        </label>
        
        {currentTrack?.audioDescriptionUrl && (
          <label className="flex items-center">
            <input
              type="checkbox"
              checked={showAudioDescription}
              onChange={(e) => setShowAudioDescription(e.target.checked)}
              className="mr-2"
            />
            <span className="text-sm">Play Audio Description</span>
          </label>
        )}
        
        <div className="text-sm text-gray-500">
          Time: {formatTime(currentTime)}
        </div>
      </div>

      {/* Audio Description Player */}
      {showAudioDescription && currentTrack?.audioDescriptionUrl && (
        <div className="bg-gray-50 p-4 rounded-lg">
          <h4 className="font-medium text-gray-900 mb-2">Audio Description ({currentTrack.label})</h4>
          <audio
            src={currentTrack.audioDescriptionUrl}
            controls
            className="w-full"
          />
          {currentAD && (
            <div className="mt-2 text-sm text-gray-700 italic">
              Current AD: "{currentAD.text}"
            </div>
          )}
        </div>
      )}

      {/* Caption Cues Timeline */}
      {currentCues.captions.length > 0 && (
        <div className="bg-white border border-gray-200 rounded-lg p-4">
          <h4 className="font-medium text-gray-900 mb-3">
            Caption Timeline ({currentTrack?.label || selectedLanguage})
          </h4>
          <div ref={timelineRef} className="max-h-48 overflow-y-auto space-y-2">
            {currentCues.captions.map((cue, index) => (
              <div
                key={index}
                className={`p-2 rounded cursor-pointer transition-colors ${
                  currentTime >= cue.startTime && currentTime <= cue.endTime
                    ? 'bg-blue-100 border border-blue-300'
                    : 'bg-gray-50 hover:bg-gray-100'
                }`}
                onClick={() => jumpToTime(cue.startTime)}
              >
                <div className="flex justify-between items-start">
                  <div className="text-sm font-mono text-gray-600">
                    {formatTime(cue.startTime)} → {formatTime(cue.endTime)}
                  </div>
                  <button
                    onClick={(e) => {
                      e.stopPropagation();
                      jumpToTime(cue.startTime);
                    }}
                    className="text-xs text-blue-600 hover:text-blue-800"
                  >
                    Jump
                  </button>
                </div>
                <div className="text-sm text-gray-900 mt-1">
                  {cue.text}
                </div>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

function formatTime(seconds: number): string {
  const hours = Math.floor(seconds / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);
  const secs = Math.floor(seconds % 60);
  
  if (hours > 0) {
    return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
  }
  return `${minutes}:${secs.toString().padStart(2, '0')}`;
}