import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
import { AssetTabs } from './AssetTabs';
import { buildAssetTabs } from './assetTabUtils';
import { NotesSidebar } from './NotesSidebar';
import { SyncedCaptionList } from './SyncedCaptionList';
import { VTTParser, type VTTCue } from '../../lib/vtt';
import { useReviewNotes, useCreateReviewNote, useUpdateReviewNote, useDeleteReviewNote } from '../../hooks/useReviewNotes';
import { useJobVttContent } from '../../hooks/useJob';
import { useAuthStore } from '../../lib/auth';
import type { Job, JobDownloadsResponse } from '../../types/api';

interface VideoReviewPlayerProps {
  job: Job;
  downloads: JobDownloadsResponse | undefined;
}

export function VideoReviewPlayer({ job, downloads }: VideoReviewPlayerProps) {
  const videoRef = useRef<HTMLVideoElement>(null);
  const [currentTime, setCurrentTime] = useState(0);
  const [isPaused, setIsPaused] = useState(true);
  const [showCaptions, setShowCaptions] = useState(true);

  // Build asset tabs
  const assetTabs = useMemo(() => buildAssetTabs(job, downloads), [job, downloads]);
  const [activeTabKey, setActiveTabKey] = useState<string>(assetTabs[0]?.key || '');

  // Stabilize video URL to prevent resets when downloads are refetched
  // Only update when tab changes, not when the same URL is refreshed with new signed params
  const [stableVideoUrls, setStableVideoUrls] = useState<Record<string, string>>({});

  // Update stable URLs only for tabs we haven't seen before
  useEffect(() => {
    setStableVideoUrls(prev => {
      const updated = { ...prev };
      let hasChanges = false;

      for (const tab of assetTabs) {
        // Only set if we don't have a URL for this tab yet
        if (!updated[tab.key] && tab.videoUrl) {
          updated[tab.key] = tab.videoUrl;
          hasChanges = true;
        }
      }

      return hasChanges ? updated : prev;
    });
  }, [assetTabs]);

  // Update active tab when tabs change
  useEffect(() => {
    if (assetTabs.length > 0 && !assetTabs.find((t) => t.key === activeTabKey)) {
      setActiveTabKey(assetTabs[0].key);
    }
  }, [assetTabs, activeTabKey]);

  // Disable browser-native text tracks so they don't compete with our React overlay
  useEffect(() => {
    const video = videoRef.current;
    if (!video) return;
    const disableTracks = () => {
      for (let i = 0; i < video.textTracks.length; i++) {
        video.textTracks[i].mode = 'disabled';
      }
    };
    disableTracks();
    video.addEventListener('loadedmetadata', disableTracks);
    return () => video.removeEventListener('loadedmetadata', disableTracks);
  }, [videoRef.current]);

  // Get current tab
  const activeTab = assetTabs.find((t) => t.key === activeTabKey);

  // Get current user
  const { user } = useAuthStore();
  const currentUserId = user?.id || '';

  // Fetch notes for current asset
  const { data: notesData, isLoading: notesLoading } = useReviewNotes(job.id, activeTabKey);
  const notes = useMemo(() => notesData?.notes || [], [notesData?.notes]);

  // Note mutations
  const createNoteMutation = useCreateReviewNote();
  const updateNoteMutation = useUpdateReviewNote();
  const deleteNoteMutation = useDeleteReviewNote();

  // Fetch VTT content for current language
  const { data: vttContent } = useJobVttContent(job.id, activeTab?.language);

  // Parse captions
  const captions = useMemo<VTTCue[]>(() => {
    // Debug logging for caption issues
    console.log('[VideoReviewPlayer] Caption Debug:', {
      hasVttContent: !!vttContent,
      vttContentKeys: vttContent ? Object.keys(vttContent) : [],
      hasCaptionsVtt: !!vttContent?.captions_vtt,
      hasRetimedCaptionsVtt: !!vttContent?.retimed_captions_vtt,
      captionsVttLength: vttContent?.captions_vtt?.length,
      retimedCaptionsVttLength: vttContent?.retimed_captions_vtt?.length,
      activeTabKey: activeTab?.key,
      activeTabLanguage: activeTab?.language,
      isAccessible: activeTab?.isAccessible,
    });

    if (!vttContent) {
      console.log('[VideoReviewPlayer] No vttContent - returning empty captions');
      return [];
    }

    // For accessible videos, use retimed captions if available, fall back to regular captions
    const vttSource = activeTab?.isAccessible
      ? (vttContent.retimed_captions_vtt || vttContent.captions_vtt)
      : vttContent.captions_vtt;

    console.log('[VideoReviewPlayer] VTT source selection:', {
      isAccessible: activeTab?.isAccessible,
      usingRetimedCaptions: activeTab?.isAccessible && !!vttContent.retimed_captions_vtt,
      vttSourceLength: vttSource?.length,
      vttSourcePreview: vttSource?.substring(0, 200),
    });

    if (!vttSource) {
      console.log('[VideoReviewPlayer] No vttSource - returning empty captions');
      return [];
    }

    try {
      const parsed = VTTParser.parse(vttSource);
      console.log('[VideoReviewPlayer] Parsed captions:', {
        count: parsed.length,
        firstCue: parsed[0],
        lastCue: parsed[parsed.length - 1],
      });
      return parsed;
    } catch (error) {
      console.error('[VideoReviewPlayer] Failed to parse captions VTT:', error);
      return [];
    }
  }, [vttContent, activeTab]);

  // Find current caption
  const currentCaption = useMemo(() => {
    const found = captions.find((cue) => currentTime >= cue.startTime && currentTime <= cue.endTime);
    // Only log when caption changes to reduce noise
    return found;
  }, [captions, currentTime]);

  // Debug: Log when currentCaption changes
  useEffect(() => {
    console.log('[VideoReviewPlayer] Current caption update:', {
      currentTime: currentTime.toFixed(2),
      hasCurrentCaption: !!currentCaption,
      currentCaptionText: currentCaption?.text?.substring(0, 50),
      showCaptions,
      totalCaptions: captions.length,
    });
  }, [currentCaption, currentTime, showCaptions, captions.length]);

  // Note highlighting state
  const [highlightedNoteIds, setHighlightedNoteIds] = useState<Set<string>>(new Set());
  const highlightTimersRef = useRef<Map<string, NodeJS.Timeout>>(new Map());

  // Note highlighting effect
  useEffect(() => {
    // Find notes within 0.5 seconds of current time
    const notesToHighlight = notes.filter(
      (note) => Math.abs(note.timestamp_seconds - currentTime) < 0.5
    );

    for (const note of notesToHighlight) {
      if (!highlightedNoteIds.has(note.id)) {
        // Start highlight
        setHighlightedNoteIds((prev) => new Set([...prev, note.id]));

        // Clear after 5 seconds
        const timer = setTimeout(() => {
          setHighlightedNoteIds((prev) => {
            const next = new Set(prev);
            next.delete(note.id);
            return next;
          });
          highlightTimersRef.current.delete(note.id);
        }, 5000);

        highlightTimersRef.current.set(note.id, timer);
      }
    }
  }, [currentTime, notes, highlightedNoteIds]);

  // Cleanup highlight timers on unmount
  useEffect(() => {
    const timers = highlightTimersRef.current;
    return () => {
      timers.forEach((timer) => clearTimeout(timer));
    };
  }, []);

  // Get stable video URL for current tab
  const currentVideoUrl = stableVideoUrls[activeTabKey] || activeTab?.videoUrl;

  // Video time update handler - stable event listeners
  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
    };

    const handlePlay = () => setIsPaused(false);
    const handlePause = () => setIsPaused(true);

    video.addEventListener('timeupdate', handleTimeUpdate);
    video.addEventListener('play', handlePlay);
    video.addEventListener('pause', handlePause);

    return () => {
      video.removeEventListener('timeupdate', handleTimeUpdate);
      video.removeEventListener('play', handlePlay);
      video.removeEventListener('pause', handlePause);
      clearTimeout(timeoutId);
    };
  }, [currentVideoUrl]); // Re-run when video URL changes to ensure listeners are attached

  // Reset video when tab changes
  useEffect(() => {
    const video = videoRef.current;
    if (video) {
      video.currentTime = 0;
      setCurrentTime(0);
    }
  }, [activeTabKey]);

  // Seek to timestamp
  const handleSeek = useCallback((timestamp: number) => {
    const video = videoRef.current;
    if (video) {
      video.currentTime = timestamp;
      setCurrentTime(timestamp);
    }
  }, []);

  // Add note handler
  const handleAddNote = useCallback(
    (content: string, timestamp: number) => {
      createNoteMutation.mutate({
        jobId: job.id,
        data: {
          asset_key: activeTabKey,
          timestamp_seconds: timestamp,
          content,
        },
      });
    },
    [createNoteMutation, job.id, activeTabKey]
  );

  // Edit note handler
  const handleEditNote = useCallback(
    (noteId: string, content: string) => {
      updateNoteMutation.mutate({
        jobId: job.id,
        noteId,
        data: { content },
      });
    },
    [updateNoteMutation, job.id]
  );

  // Delete note handler
  const handleDeleteNote = useCallback(
    (noteId: string) => {
      deleteNoteMutation.mutate({
        jobId: job.id,
        noteId,
      });
    },
    [deleteNoteMutation, job.id]
  );

  if (assetTabs.length === 0) {
    return (
      <div className="bg-white border border-gray-200 rounded-lg p-8 text-center">
        <p className="text-gray-500">No video assets available for review</p>
      </div>
    );
  }

  return (
    <div className="bg-white border border-gray-200 rounded-lg overflow-hidden">
      {/* Asset Tabs */}
      <AssetTabs
        tabs={assetTabs}
        activeTab={activeTabKey}
        onTabChange={setActiveTabKey}
      />

      {/* Main Content */}
      <div className="flex">
        {/* Video and Captions Area */}
        <div className="flex-1 p-4">
          {/* Video Player */}
          <div className="relative bg-black rounded-lg overflow-hidden">
            {currentVideoUrl ? (
              <video
                ref={videoRef}
                src={currentVideoUrl}
                controls
                className="w-full h-auto"
              >
                Your browser does not support the video tag.
              </video>
            ) : (
              <div className="aspect-video flex items-center justify-center bg-gray-900">
                <p className="text-gray-400">Video not available</p>
              </div>
            )}

            {/* Caption Overlay — position at top when cue has line:0% setting */}
            {showCaptions && currentCaption && (
              <div className={`absolute ${currentCaption.positionTop ? 'top-4' : 'bottom-14'} 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>

          {/* Video Controls */}
          <div className="flex items-center justify-between mt-3">
            <label className="flex items-center text-sm">
              <input
                type="checkbox"
                checked={showCaptions}
                onChange={(e) => setShowCaptions(e.target.checked)}
                className="mr-2 h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded"
              />
              Show Captions
            </label>

            <div className="text-sm text-gray-500 font-mono">
              {formatTime(currentTime)}
            </div>
          </div>

          {/* Caption Timeline */}
          <div className="mt-4">
            <SyncedCaptionList
              cues={captions}
              currentTime={currentTime}
              onSeek={handleSeek}
            />
          </div>
        </div>

        {/* Notes Sidebar */}
        <div className="w-80 flex-shrink-0">
          <NotesSidebar
            notes={notes}
            currentUserId={currentUserId}
            currentTimestamp={currentTime}
            isPaused={isPaused}
            highlightedNoteIds={highlightedNoteIds}
            isLoading={notesLoading}
            isSubmitting={createNoteMutation.isPending}
            onSeek={handleSeek}
            onAddNote={handleAddNote}
            onEditNote={handleEditNote}
            onDeleteNote={handleDeleteNote}
          />
        </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')}`;
}
