import React, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
import axios from 'axios';
import { ChevronLeft, Play, Pause, Volume2, Settings, Download, Save, LayoutTemplate, Type, Image as ImageIcon, Music, Scissors, Plus, Trash2, Maximize2, Loader2 } from 'lucide-react';
import VoiceMarketModal from './VoiceMarketModal';
import ExportModal from './ExportModal';
import { LlmProvider, PipelineQuality, Subtitle, TextStyles } from '../types';
import { generateSubtitlePipeline } from '../services/subtitleService';
import { generateTTS } from '../services/ttsService';
import { MINIMAX_VOICES } from '../voices';
import { apiUrl } from '../lib/apiBasePath';

export default function EditorScreen({ videoFile, targetLanguage, trimRange, onBack }: { videoFile: File | null; targetLanguage: string; trimRange?: {start: number, end: number} | null; onBack: () => void }) {
  const [subtitles, setSubtitles] = useState<Subtitle[]>([]);
  const [activeSubtitleId, setActiveSubtitleId] = useState<string>('');
  const [showVoiceMarket, setShowVoiceMarket] = useState(false);
  const [voiceMarketTargetId, setVoiceMarketTargetId] = useState<string | null>(null);
  const [showExportModal, setShowExportModal] = useState(false);
  const [isGenerating, setIsGenerating] = useState(false);
  const [isDubbingGenerating, setIsDubbingGenerating] = useState(false);
  const [generatingAudioIds, setGeneratingAudioIds] = useState<Set<string>>(new Set());
  const [generationError, setGenerationError] = useState<string | null>(null);
  const [subtitleQuality, setSubtitleQuality] = useState<PipelineQuality>('fallback');
  const [llmProvider, setLlmProvider] = useState<LlmProvider>('doubao');
  
  // Video Player State
  const videoRef = useRef<HTMLVideoElement>(null);
  const audioRef = useRef<HTMLAudioElement | null>(null);
  const bgmRef = useRef<HTMLAudioElement | null>(null);
  const audioContextRef = useRef<AudioContext | null>(null);
  const lastPlayedSubId = useRef<string | null>(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [bgmUrl, setBgmUrl] = useState<string | null>(null);
  const [bgmBase64, setBgmBase64] = useState<string | null>(null);
  const [isSeparating, setIsSeparating] = useState(false);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(30); // Default 30s, updated on load

  const [videoUrl, setVideoUrl] = useState<string>('');
  const [videoAspectRatio, setVideoAspectRatio] = useState<number>(16/9);
  const containerRef = useRef<HTMLDivElement>(null);
  const [renderedVideoWidth, setRenderedVideoWidth] = useState<number | '100%'>('100%');
  const autoGenerationKeyRef = useRef<string | null>(null);
  
  // Timeline Dragging State
  const [draggingId, setDraggingId] = useState<string | null>(null);
  const [dragType, setDragType] = useState<'move' | 'resize-left' | 'resize-right' | null>(null);
  const [dragStartX, setDragStartX] = useState(0);
  const [initialSubTimes, setInitialSubTimes] = useState<{startTime: number, endTime: number} | null>(null);
  const [isDraggingPlayhead, setIsDraggingPlayhead] = useState(false);
  const timelineTrackRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!containerRef.current) return;
    const observer = new ResizeObserver((entries) => {
      for (let entry of entries) {
        const { width, height } = entry.contentRect;
        const containerAspect = width / height;
        if (containerAspect > videoAspectRatio) {
          // Container is wider than video. Video height is 100%, width is scaled.
          setRenderedVideoWidth(height * videoAspectRatio);
        } else {
          // Container is taller than video. Video width is 100%.
          setRenderedVideoWidth(width);
        }
      }
    });
    observer.observe(containerRef.current);
    return () => observer.disconnect();
  }, [videoAspectRatio]);

  useEffect(() => {
    if (!videoFile) {
      setVideoUrl('');
      return;
    }
    const url = URL.createObjectURL(videoFile);
    setVideoUrl(url);
    return () => {
      URL.revokeObjectURL(url);
    };
  }, [videoFile]);

  const fetchSubtitles = useCallback(async () => {
    if (!videoFile) return;
    setIsGenerating(true);
    setGenerationError(null);
    try {
      const pipelineResult = await generateSubtitlePipeline(
        videoFile,
        targetLanguage,
        llmProvider,
        trimRange,
      );
      const generatedSubs = pipelineResult.subtitles;
      setSubtitleQuality(pipelineResult.quality);
      
      let adjustedSubs = generatedSubs;
      if (trimRange) {
        adjustedSubs = generatedSubs
          .filter(sub => sub.endTime > trimRange.start && sub.startTime < trimRange.end)
          .map(sub => ({
            ...sub,
            startTime: Math.max(0, sub.startTime - trimRange.start),
            endTime: Math.min(trimRange.end - trimRange.start, sub.endTime - trimRange.start)
          }));
      }

      setSubtitles(adjustedSubs);
      if (adjustedSubs.length > 0) {
        setActiveSubtitleId(adjustedSubs[0].id);
      }
    } catch (err: any) {
      console.error("Failed to generate subtitles:", err);
      setSubtitleQuality('fallback');
      
      let errorMessage = "Failed to generate subtitles. Please try again or check your API key.";
      const errString = err instanceof Error ? err.message : JSON.stringify(err);
      
      if (
        errString.includes("429") || 
        errString.includes("quota") || 
        errString.includes("RESOURCE_EXHAUSTED") ||
        err?.status === 429 ||
        err?.error?.code === 429
      ) {
        errorMessage = "You have exceeded your Volcengine API quota. Please check your plan and billing details.";
      } else if (err instanceof Error) {
        errorMessage = err.message;
      }

      setGenerationError(errorMessage);
      setSubtitles([]);
      setActiveSubtitleId('');
    } finally {
      setIsGenerating(false);
    }
  }, [videoFile, targetLanguage, trimRange, llmProvider]);

  // Generate subtitles on mount
  useEffect(() => {
    const autoGenerationKey = JSON.stringify({
      fileName: videoFile?.name || '',
      fileSize: videoFile?.size || 0,
      targetLanguage,
      trimRange,
      llmProvider,
    });

    if (autoGenerationKeyRef.current === autoGenerationKey) {
      return;
    }

    autoGenerationKeyRef.current = autoGenerationKey;
    fetchSubtitles();
  }, [fetchSubtitles, videoFile, targetLanguage, trimRange, llmProvider]);

  const [textStyles, setTextStyles] = useState<TextStyles>({
    fontFamily: 'MiSans-Late',
    fontSize: 24,
    color: '#FFFFFF',
    backgroundColor: 'transparent',
    alignment: 'center',
    isBold: false,
    isItalic: false,
    isUnderline: false,
  });

  const togglePlay = async () => {
    if (videoRef.current) {
      if (isPlaying) {
        videoRef.current.pause();
        if (bgmRef.current) bgmRef.current.pause();
        if (audioRef.current) audioRef.current.pause();
      } else {
        if (trimRange && (videoRef.current.currentTime < trimRange.start || videoRef.current.currentTime >= trimRange.end)) {
          videoRef.current.currentTime = trimRange.start;
        }
        
        videoRef.current.play();
        if (bgmRef.current) {
          bgmRef.current.currentTime = videoRef.current.currentTime;
          bgmRef.current.play();
        }
      }
      setIsPlaying(!isPlaying);
    }
  };

  const handleGenerateDubbing = async () => {
    if (subtitles.length === 0) return;
    setIsDubbingGenerating(true);
    
    // Step 1: Vocal Separation (Scheme A: Server-side AI-like separation)
    if (!bgmUrl && videoFile) {
      setIsSeparating(true);
      try {
        const formData = new FormData();
        formData.append('video', videoFile);

        const response = await axios.post(apiUrl('/separate-vocal'), formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        });
        const { instrumental } = response.data;
        
        const blob = await (await fetch(`data:audio/mp3;base64,${instrumental}`)).blob();
        const url = URL.createObjectURL(blob);
        setBgmUrl(url);
        setBgmBase64(instrumental);
        console.log("Vocal separation completed (Instrumental extracted via Scheme A)");
      } catch (err) {
        console.error("Vocal separation failed:", err);
      } finally {
        setIsSeparating(false);
      }
    }

    // Step 2: TTS Generation
    const toGenerate = subtitles.filter(s => !s.audioUrl).map(s => s.id);
    setGeneratingAudioIds(new Set(toGenerate));

    try {
      const updatedSubtitles = [...subtitles];
      
      for (let i = 0; i < updatedSubtitles.length; i++) {
        const sub = updatedSubtitles[i];
        if (sub.audioUrl) continue;
        
        try {
          const textToSpeak = sub.translatedText || sub.text;
          const audioUrl = await generateTTS(textToSpeak, sub.voiceId);
          updatedSubtitles[i] = { ...sub, audioUrl };
          // Update state incrementally so user sees progress
          setSubtitles([...updatedSubtitles]);
        } catch (err) {
          console.error(`Failed to generate TTS for subtitle ${sub.id}:`, err);
        } finally {
          setGeneratingAudioIds(prev => {
            const next = new Set(prev);
            next.delete(sub.id);
            return next;
          });
        }
      }
    } catch (err) {
      console.error("Failed to generate dubbing:", err);
    } finally {
      setIsDubbingGenerating(false);
      setGeneratingAudioIds(new Set());
      if (subtitles.some(s => s.audioUrl)) {
        console.log("Dubbing generation completed.");
      }
    }
  };

  const handleTimeUpdate = () => {
    if (videoRef.current) {
      let time = videoRef.current.currentTime;
      
      if (trimRange) {
        if (time < trimRange.start) {
          videoRef.current.currentTime = trimRange.start;
          time = trimRange.start;
        } else if (time >= trimRange.end) {
          videoRef.current.pause();
          if (bgmRef.current) bgmRef.current.pause();
          if (audioRef.current) audioRef.current.pause();
          setIsPlaying(false);
          videoRef.current.currentTime = trimRange.start;
          time = trimRange.start;
        }
      }

      setCurrentTime(time);
      
      const displayTime = trimRange ? time - trimRange.start : time;

      // Auto-select active subtitle based on time
      const activeSub = subtitles.find(s => displayTime >= s.startTime && displayTime <= s.endTime);
      
      // Sync BGM with video
      if (bgmRef.current && videoRef.current && isPlaying) {
        if (Math.abs(bgmRef.current.currentTime - videoRef.current.currentTime) > 0.3) {
          bgmRef.current.currentTime = videoRef.current.currentTime;
        }
      }

      if (activeSub) {
        if (activeSub.id !== activeSubtitleId) {
          setActiveSubtitleId(activeSub.id);
        }
        
        // Play dubbing if available and not already playing for this sub
        if (activeSub.audioUrl && lastPlayedSubId.current !== activeSub.id && isPlaying) {
          if (audioRef.current) {
            audioRef.current.pause();
          }
          
          const audio = new Audio(activeSub.audioUrl);
          audio.volume = activeSub.volume !== undefined ? activeSub.volume : 1.0;
          audioRef.current = audio;
          
          audio.play().catch(e => console.error("Audio playback failed:", e));
          lastPlayedSubId.current = activeSub.id;
        }
      } else {
        lastPlayedSubId.current = null;
      }
    }
  };

  useEffect(() => {
    if (videoRef.current) {
      videoRef.current.volume = bgmUrl ? 0 : 0.3;
    }
  }, [bgmUrl]);

  const handleLoadedMetadata = () => {
    if (videoRef.current) {
      setDuration(videoRef.current.duration);
      videoRef.current.volume = bgmUrl ? 0 : 0.3; // Mute if BGM (instrumental) is present
      if (bgmRef.current) {
        bgmRef.current.volume = 0.5; // BGM volume
      }
      if (videoRef.current.videoHeight > 0) {
        setVideoAspectRatio(videoRef.current.videoWidth / videoRef.current.videoHeight);
      }
      if (trimRange) {
        videoRef.current.currentTime = trimRange.start;
        setCurrentTime(trimRange.start);
      }
    }
  };

  const handleTimelineMouseDown = (e: React.MouseEvent, subId: string, type: 'move' | 'resize-left' | 'resize-right') => {
    e.stopPropagation();
    const sub = subtitles.find(s => s.id === subId);
    if (!sub) return;

    setDraggingId(subId);
    setDragType(type);
    setDragStartX(e.clientX);
    setInitialSubTimes({ startTime: sub.startTime, endTime: sub.endTime });
    setActiveSubtitleId(subId);
  };

  const handleTimelineMouseMove = useCallback((e: MouseEvent) => {
    if (!timelineTrackRef.current) return;
    const rect = timelineTrackRef.current.getBoundingClientRect();
    const timelineWidth = rect.width - 32; // Subtract padding (1rem each side)
    const displayDuration = trimRange ? trimRange.end - trimRange.start : duration;

    if (isDraggingPlayhead) {
      const deltaX = e.clientX - rect.left - 16; // 1rem padding
      const percent = Math.max(0, Math.min(1, deltaX / timelineWidth));
      const newTime = percent * displayDuration;
      if (videoRef.current) {
        videoRef.current.currentTime = newTime + (trimRange?.start || 0);
      }
      return;
    }

    if (!draggingId || !initialSubTimes) return;

    const deltaX = e.clientX - dragStartX;
    const deltaSeconds = (deltaX / timelineWidth) * displayDuration;

    setSubtitles(prev => prev.map(sub => {
      if (sub.id !== draggingId) return sub;

      let newStart = sub.startTime;
      let newEnd = sub.endTime;

      if (dragType === 'move') {
        newStart = Math.max(0, Math.min(displayDuration - (initialSubTimes.endTime - initialSubTimes.startTime), initialSubTimes.startTime + deltaSeconds));
        newEnd = newStart + (initialSubTimes.endTime - initialSubTimes.startTime);
      } else if (dragType === 'resize-left') {
        newStart = Math.max(0, Math.min(initialSubTimes.endTime - 0.2, initialSubTimes.startTime + deltaSeconds));
      } else if (dragType === 'resize-right') {
        newEnd = Math.max(initialSubTimes.startTime + 0.2, Math.min(displayDuration, initialSubTimes.endTime + deltaSeconds));
      }

      return { ...sub, startTime: newStart, endTime: newEnd };
    }));
  }, [draggingId, dragType, dragStartX, initialSubTimes, duration, trimRange, isDraggingPlayhead]);

  const handleTimelineMouseUp = useCallback(() => {
    setDraggingId(null);
    setDragType(null);
    setInitialSubTimes(null);
    setIsDraggingPlayhead(false);
  }, []);

  useEffect(() => {
    if (draggingId || isDraggingPlayhead) {
      window.addEventListener('mousemove', handleTimelineMouseMove);
      window.addEventListener('mouseup', handleTimelineMouseUp);
    } else {
      window.removeEventListener('mousemove', handleTimelineMouseMove);
      window.removeEventListener('mouseup', handleTimelineMouseUp);
    }
    return () => {
      window.removeEventListener('mousemove', handleTimelineMouseMove);
      window.removeEventListener('mouseup', handleTimelineMouseUp);
    };
  }, [draggingId, isDraggingPlayhead, handleTimelineMouseMove, handleTimelineMouseUp]);

  const formatTime = (seconds: number) => {
    if (isNaN(seconds) || seconds < 0) seconds = 0;
    const mins = Math.floor(seconds / 60);
    const secs = Math.floor(seconds % 60);
    return `00:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
  };

  const displayDuration = trimRange ? trimRange.end - trimRange.start : duration;
  const displayCurrentTime = trimRange ? Math.max(0, currentTime - trimRange.start) : currentTime;

  // Calculate playhead position percentage
  const playheadPercent = displayDuration > 0 ? (displayCurrentTime / displayDuration) * 100 : 0;

  // Get current subtitle text
  const currentSubtitleText = subtitles.find(s => displayCurrentTime >= s.startTime && displayCurrentTime <= s.endTime)?.translatedText || '';

  return (
    <div className="h-[100dvh] flex flex-col bg-white overflow-hidden">
      {/* Top Header */}
      <header className="h-14 border-b border-gray-200 flex items-center justify-between px-4 shrink-0">
        <div className="flex items-center gap-4">
          <button onClick={onBack} className="p-2 hover:bg-gray-100 rounded-md">
            <ChevronLeft className="w-5 h-5" />
          </button>
          <div className="flex items-center gap-2">
            <div className="w-6 h-6 bg-orange-500 rounded flex items-center justify-center text-white font-bold text-xs">M</div>
            <span className="font-medium text-sm">Translate 1.0</span>
          </div>
        </div>

        <div className="flex items-center gap-4">
          <button className="p-2 hover:bg-gray-100 rounded-md text-gray-600">
            <LayoutTemplate className="w-5 h-5" />
          </button>
          <button className="p-2 hover:bg-gray-100 rounded-md text-gray-600">
            <Type className="w-5 h-5" />
          </button>
          <div className="h-4 w-px bg-gray-300 mx-2"></div>
          <button 
            onClick={togglePlay}
            className="flex items-center gap-2 px-3 py-1.5 bg-red-50 text-red-600 rounded-md text-sm font-medium hover:bg-red-100"
          >
            <Play className="w-4 h-4 fill-current" />
            Watch Video
          </button>
          <button className="flex items-center gap-2 px-3 py-1.5 text-gray-600 hover:bg-gray-100 rounded-md text-sm font-medium">
            <Save className="w-4 h-4" />
            Save Editing
          </button>
          <button
            onClick={() => setShowExportModal(true)}
            className="flex items-center gap-2 px-4 py-1.5 bg-[#52c41a] text-white rounded-md text-sm font-medium hover:bg-[#46a616]"
          >
            <Download className="w-4 h-4" />
            Export
          </button>
        </div>
      </header>

      {/* Main Workspace */}
      <div className="flex-1 flex overflow-hidden min-h-0">
        {/* Left Sidebar - Subtitles */}
        <div className="w-80 border-r border-gray-200 flex flex-col bg-gray-50 shrink-0">
          <div className="p-4 border-b border-gray-200 bg-white shrink-0">
            <div className="flex bg-gray-100 p-1 rounded-md mb-4">
              <button className="flex-1 py-1.5 bg-white shadow-sm rounded text-sm font-medium">AI Dub</button>
              <button className="flex-1 py-1.5 text-gray-600 text-sm font-medium">Voice Clone</button>
            </div>
            <p className="text-xs text-gray-500 mb-4">
              Tip: After modifying the subtitle text, you need to regenerate the dubbing to take effect!
            </p>
            <div className="mb-4">
              <label htmlFor="llm-provider" className="block text-xs font-medium text-gray-500 mb-1">
                LLM
              </label>
              <select
                id="llm-provider"
                aria-label="LLM"
                value={llmProvider}
                onChange={(e) => setLlmProvider(e.target.value as LlmProvider)}
                className="w-full border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:border-blue-500 bg-white"
              >
                <option value="doubao">Doubao</option>
                <option value="gemini">Gemini</option>
              </select>
            </div>
            <button 
              onClick={handleGenerateDubbing}
              disabled={isDubbingGenerating || subtitles.length === 0}
              className="w-full py-2 bg-blue-500 hover:bg-blue-600 disabled:bg-blue-300 text-white rounded-md text-sm font-medium transition-colors flex items-center justify-center gap-2"
            >
              {isDubbingGenerating && <Loader2 className="w-4 h-4 animate-spin" />}
              {isSeparating ? 'Separating Vocals...' : isDubbingGenerating ? 'Generating TTS...' : 'Generate Dubbing'}
            </button>
          </div>

          <div className="flex-1 overflow-y-auto p-2 space-y-2 min-h-0">
            {isGenerating ? (
              <div className="flex flex-col items-center justify-center h-full text-gray-500 space-y-4">
                <Loader2 className="w-8 h-8 animate-spin text-blue-500" />
                <p className="text-sm font-medium">AI is analyzing and translating...</p>
                <p className="text-xs text-center px-4">This may take a minute depending on the video length.</p>
              </div>
            ) : (
              <>
                {generationError && (
                  <div className="p-3 mb-2 text-xs text-red-600 bg-red-50 border border-red-200 rounded-md flex flex-col gap-2">
                    <p>{generationError}</p>
                    <button 
                      onClick={() => fetchSubtitles()}
                      className="px-3 py-1.5 bg-red-100 hover:bg-red-200 text-red-700 rounded font-medium transition-colors self-start"
                    >
                      Retry Generation
                    </button>
                  </div>
                )}
                {!generationError && subtitleQuality === 'fallback' && (
                  <div className="p-3 mb-2 text-xs text-amber-700 bg-amber-50 border border-amber-200 rounded-md">
                    Low-precision subtitle timing is active for this generation. You can still edit subtitles before dubbing.
                  </div>
                )}
                {subtitles.map((sub, index) => (
                  <div
                    key={sub.id}
                    className={`p-3 rounded-lg border transition-all ${
                      activeSubtitleId === sub.id 
                        ? 'border-blue-500 bg-blue-50/50 shadow-sm' 
                        : sub.audioUrl 
                          ? 'border-green-200 bg-white' 
                          : 'border-gray-200 bg-white'
                    } cursor-pointer relative group`}
                    onClick={() => {
                      setActiveSubtitleId(sub.id);
                      if (videoRef.current) {
                        videoRef.current.currentTime = sub.startTime + (trimRange?.start || 0);
                      }
                    }}
                  >
                    {sub.audioUrl && (
                      <div className="absolute -right-1 -top-1 w-4 h-4 bg-green-500 rounded-full flex items-center justify-center text-white shadow-sm">
                        <Music className="w-2.5 h-2.5" />
                      </div>
                    )}
                    {generatingAudioIds.has(sub.id) && (
                      <div className="absolute right-2 top-2">
                        <Loader2 className="w-3 h-3 animate-spin text-blue-500" />
                      </div>
                    )}
                    <div className="flex items-center justify-between mb-2">
                      <span className="text-xs font-medium text-gray-500">
                        {index + 1}. {formatTime(sub.startTime)} - {formatTime(sub.endTime)}
                      </span>
                      <div className="flex items-center gap-2">
                        {sub.audioUrl && (
                          <div className="flex items-center gap-1 bg-gray-100 px-1.5 py-0.5 rounded">
                            <Volume2 className="w-3 h-3 text-gray-500" />
                            <input 
                              type="range" 
                              min="0" 
                              max="1" 
                              step="0.1" 
                              value={sub.volume ?? 1.0}
                              onChange={(e) => {
                                const newSubs = [...subtitles];
                                newSubs[index].volume = parseFloat(e.target.value);
                                setSubtitles(newSubs);
                              }}
                              className="w-12 h-1 bg-gray-300 rounded-lg appearance-none cursor-pointer accent-blue-500"
                              onClick={(e) => e.stopPropagation()}
                            />
                          </div>
                        )}
                        <button
                          className="flex items-center gap-1 text-xs text-blue-600 bg-blue-50 px-2 py-1 rounded"
                          onClick={(e) => { 
                            e.stopPropagation(); 
                            setVoiceMarketTargetId(sub.id);
                            setShowVoiceMarket(true); 
                          }}
                        >
                          <div className="w-4 h-4 rounded-full bg-orange-200 overflow-hidden">
                              <img src={`https://api.dicebear.com/7.x/avataaars/svg?seed=${sub.voiceId}`} alt="avatar" />
                          </div>
                          {MINIMAX_VOICES.find(v => v.id === sub.voiceId)?.name || 'Select Voice'}
                        </button>
                      </div>
                    </div>
                    <textarea
                      className="w-full text-sm bg-transparent border-none resize-none focus:ring-0 p-0 text-gray-500 mb-2"
                      rows={2}
                      value={sub.originalText}
                      readOnly
                    />
                    <textarea
                      className="w-full text-sm bg-transparent border-none resize-none focus:ring-0 p-0 text-gray-800 font-medium"
                      rows={2}
                      value={sub.translatedText}
                      onChange={(e) => {
                        const newSubs = [...subtitles];
                        newSubs[index].translatedText = e.target.value;
                        setSubtitles(newSubs);
                      }}
                    />
                  </div>
                ))}
              </>
            )}
          </div>
        </div>

        {/* Center - Video Player */}
        <div className="flex-1 flex flex-col bg-gray-100 relative min-w-0 min-h-0">
          <div className="flex-1 flex items-center justify-center p-8 relative min-h-0">
            {/* Video Container */}
            <div ref={containerRef} className="relative w-full h-full bg-black rounded-lg overflow-hidden shadow-lg flex items-center justify-center min-h-0">
               {videoUrl ? (
                 <video 
                   ref={videoRef}
                   src={videoUrl} 
                   className="w-full h-full object-contain"
                   onTimeUpdate={handleTimeUpdate}
                   onLoadedMetadata={handleLoadedMetadata}
                   onEnded={() => {
                     setIsPlaying(false);
                     if (bgmRef.current) bgmRef.current.pause();
                     if (audioRef.current) audioRef.current.pause();
                   }}
                   onClick={togglePlay}
                   playsInline
                   preload="metadata"
                 />
               ) : (
                 <div className="text-gray-500 flex flex-col items-center justify-center h-full w-full">
                   <ImageIcon className="w-12 h-12 mb-2 opacity-50" />
                   <p>No video loaded</p>
                 </div>
               )}
               
               {/* BGM Audio Element */}
               {bgmUrl && (
                 <audio 
                   ref={bgmRef}
                   src={bgmUrl}
                   className="hidden"
                   onEnded={() => {
                     if (videoRef.current) videoRef.current.pause();
                     setIsPlaying(false);
                   }}
                 />
               )}
               
               {/* Subtitle Overlay */}
               {currentSubtitleText && (
                 <div 
                   className="absolute bottom-[10%] left-1/2 -translate-x-1/2 flex justify-center pointer-events-none px-4"
                   style={{ width: renderedVideoWidth }}
                 >
                   <p 
                     className="text-white text-base md:text-lg font-bold drop-shadow-md break-words whitespace-pre-wrap text-center max-w-[90%]" 
                     style={{ 
                       fontFamily: textStyles.fontFamily,
                       color: textStyles.color,
                       textAlign: textStyles.alignment,
                       fontWeight: textStyles.isBold ? 'bold' : 'normal',
                       fontStyle: textStyles.isItalic ? 'italic' : 'normal',
                       textDecoration: textStyles.isUnderline ? 'underline' : 'none',
                     }}
                   >
                     {currentSubtitleText}
                   </p>
                 </div>
               )}
            </div>
          </div>

          {/* Player Controls */}
          <div className="h-12 bg-white border-t border-gray-200 flex items-center justify-between px-4 shrink-0">
            <div className="flex items-center gap-4">
              <button className="p-1.5 hover:bg-gray-100 rounded-full" onClick={togglePlay}>
                {isPlaying ? <Pause className="w-5 h-5" /> : <Play className="w-5 h-5" />}
              </button>
              <span className="text-sm font-medium font-mono">
                {formatTime(displayCurrentTime)} / {formatTime(displayDuration)}
              </span>
            </div>
            <div className="flex items-center gap-4">
              {bgmUrl && (
                <div className="flex items-center gap-2 bg-gray-100 px-2 py-1 rounded-md">
                  <Music className="w-4 h-4 text-green-600" />
                  <span className="text-xs font-medium text-gray-600">BGM</span>
                  <input 
                    type="range" 
                    min="0" 
                    max="1" 
                    step="0.1" 
                    defaultValue="0.5"
                    onChange={(e) => {
                      if (bgmRef.current) bgmRef.current.volume = parseFloat(e.target.value);
                    }}
                    className="w-16 h-1 bg-gray-300 rounded-lg appearance-none cursor-pointer accent-green-500"
                  />
                </div>
              )}
              <Maximize2 className="w-4 h-4 text-gray-500" />
            </div>
          </div>
        </div>

        {/* Right Sidebar - Properties */}
        <div className="w-72 border-l border-gray-200 bg-white flex flex-col shrink-0 overflow-y-auto">
          <div className="p-4 border-b border-gray-200">
            <label className="flex items-center gap-2 text-sm text-gray-700 cursor-pointer">
              <input type="checkbox" className="rounded text-blue-600 focus:ring-blue-500" defaultChecked />
              Apply to all subtitles
            </label>
          </div>

          <div className="p-4 border-b border-gray-200">
            <div className="flex items-center gap-2 mb-3">
              <div className="w-6 h-6 rounded-full bg-green-100 flex items-center justify-center text-green-600 text-xs font-bold">
                W
              </div>
              <span className="text-sm font-medium text-gray-700">Wife</span>
            </div>
            <input
              type="text"
              value="Husband"
              className="w-full border border-gray-300 rounded-md px-3 py-1.5 text-sm focus:outline-none focus:border-blue-500"
              readOnly
            />
          </div>

          <div className="p-4">
            <h3 className="text-sm font-medium text-gray-700 mb-3">Text Styles</h3>
            
            {/* Style Presets Grid */}
            <div className="grid grid-cols-4 gap-2 mb-6">
              {['T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'T'].map((item, i) => (
                <button key={i} className={`aspect-square rounded border flex items-center justify-center text-lg font-bold ${i === 8 ? 'border-blue-500 bg-blue-50 text-blue-600' : 'border-gray-200 bg-gray-50 text-gray-700 hover:bg-gray-100'}`}>
                  {item}
                </button>
              ))}
            </div>

            {/* Font Family */}
            <div className="mb-4">
              <select 
                className="w-full border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:border-blue-500"
                value={textStyles.fontFamily}
                onChange={(e) => setTextStyles({...textStyles, fontFamily: e.target.value})}
              >
                <option value="MiSans-Late">MiSans-Late</option>
                <option value="Arial">Arial</option>
                <option value="Roboto">Roboto</option>
                <option value="serif">Serif</option>
              </select>
            </div>

            {/* Font Size & Alignment */}
            <div className="flex gap-2 mb-4">
              <select className="flex-1 border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:border-blue-500">
                <option>Normal</option>
                <option>Large</option>
                <option>Small</option>
              </select>
              <div className="flex border border-gray-300 rounded-md overflow-hidden">
                <button 
                  className={`px-3 py-2 border-r border-gray-300 font-bold ${textStyles.isBold ? 'bg-gray-200' : 'bg-gray-50 hover:bg-gray-100'}`}
                  onClick={() => setTextStyles({...textStyles, isBold: !textStyles.isBold})}
                >B</button>
                <button 
                  className={`px-3 py-2 border-r border-gray-300 italic ${textStyles.isItalic ? 'bg-gray-200' : 'bg-gray-50 hover:bg-gray-100'}`}
                  onClick={() => setTextStyles({...textStyles, isItalic: !textStyles.isItalic})}
                >I</button>
                <button 
                  className={`px-3 py-2 underline ${textStyles.isUnderline ? 'bg-gray-200' : 'bg-gray-50 hover:bg-gray-100'}`}
                  onClick={() => setTextStyles({...textStyles, isUnderline: !textStyles.isUnderline})}
                >U</button>
              </div>
            </div>

            {/* Colors */}
            <div className="space-y-3">
              <div className="flex items-center justify-between">
                <span className="text-sm text-gray-600">Color</span>
                <div className="flex items-center gap-2">
                  <input 
                    type="color" 
                    value={textStyles.color}
                    onChange={(e) => setTextStyles({...textStyles, color: e.target.value})}
                    className="w-6 h-6 rounded border border-gray-300 p-0 cursor-pointer" 
                  />
                  <span className="text-sm text-gray-500">100%</span>
                </div>
              </div>
              <div className="flex items-center justify-between">
                <span className="text-sm text-gray-600">Stroke</span>
                <div className="flex items-center gap-2">
                  <div className="w-6 h-6 rounded border border-gray-300 bg-black"></div>
                  <span className="text-sm text-gray-500">100%</span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* Bottom Timeline */}
      <div className="h-48 border-t border-gray-200 bg-white flex flex-col shrink-0">
        {/* Timeline Toolbar */}
        <div className="h-10 border-b border-gray-100 flex items-center px-4 gap-4">
          <button className="p-1.5 hover:bg-gray-100 rounded text-gray-600"><Scissors className="w-4 h-4" /></button>
          <button className="p-1.5 hover:bg-gray-100 rounded text-gray-600"><Plus className="w-4 h-4" /></button>
          <button className="p-1.5 hover:bg-gray-100 rounded text-gray-600"><Trash2 className="w-4 h-4" /></button>
          <div className="h-4 w-px bg-gray-300 mx-2"></div>
          <span className="text-xs text-orange-500 bg-orange-50 px-2 py-1 rounded border border-orange-200">
            Stretch the dubbing to control the speed
          </span>
          <div className="flex-1"></div>
          {/* Zoom slider placeholder */}
          <div className="w-32 h-1 bg-gray-200 rounded-full relative">
            <div className="absolute left-1/2 top-1/2 -translate-y-1/2 w-3 h-3 bg-white border border-gray-400 rounded-full"></div>
          </div>
        </div>

        {/* Timeline Tracks */}
        <div ref={timelineTrackRef} className="flex-1 overflow-x-auto overflow-y-hidden relative custom-scrollbar bg-gray-50">
           {/* Time Ruler */}
           <div className="h-6 border-b border-gray-200 flex items-end px-4 relative min-w-[1000px] bg-white">
              {[0, 20, 40, 60, 80, 100].map(percent => (
                <span key={percent} className="absolute text-[10px] text-gray-400" style={{ left: `${percent}%` }}>
                  {formatTime((displayDuration * percent) / 100)}
                </span>
              ))}
           </div>

           {/* Video Track */}
           <div className="h-12 border-b border-gray-200 flex items-center px-4 min-w-[1000px] relative">
              <div className="absolute left-4 right-4 h-10 bg-blue-50 rounded overflow-hidden flex border border-blue-100 items-center justify-center text-xs text-blue-400">
                 Video Track
              </div>
           </div>

            {/* Subtitle Track */}
           <div className="h-12 border-b border-gray-200 flex items-center px-4 min-w-[1000px] relative">
              {subtitles.map((sub) => {
                const leftPercent = (sub.startTime / displayDuration) * 100;
                const widthPercent = ((sub.endTime - sub.startTime) / displayDuration) * 100;
                return (
                  <div 
                    key={sub.id}
                    className={`absolute h-10 rounded flex flex-col justify-start px-2 cursor-pointer border transition-colors select-none overflow-hidden ${
                      activeSubtitleId === sub.id ? 'bg-[#e6f4ff] border-[#1677ff] z-10' : 'bg-white border-gray-200 hover:border-blue-300'
                    }`}
                    style={{ left: `calc(1rem + ${leftPercent}%)`, width: `${widthPercent}%` }}
                    onClick={() => {
                      setActiveSubtitleId(sub.id);
                      if (videoRef.current) videoRef.current.currentTime = sub.startTime + (trimRange?.start || 0);
                    }}
                    onMouseDown={(e) => handleTimelineMouseDown(e, sub.id, 'move')}
                  >
                     <div 
                       className="absolute left-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-blue-400/50 z-20"
                       onMouseDown={(e) => handleTimelineMouseDown(e, sub.id, 'resize-left')}
                     />
                     <div 
                       className="absolute right-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-blue-400/50 z-20"
                       onMouseDown={(e) => handleTimelineMouseDown(e, sub.id, 'resize-right')}
                     />
                     <span className="text-[9px] font-bold text-blue-800 truncate pointer-events-none mt-0.5">T {sub.speaker}</span>
                     <span className="text-[9px] text-blue-600 truncate pointer-events-none leading-tight">{sub.translatedText}</span>
                  </div>
                );
              })}
           </div>

            {/* Audio Track */}
           <div className="h-12 flex items-center px-4 min-w-[1000px] relative">
              {subtitles.map((sub) => {
                if (!sub.audioUrl && !generatingAudioIds.has(sub.id)) return null;
                
                const leftPercent = (sub.startTime / displayDuration) * 100;
                const widthPercent = ((sub.endTime - sub.startTime) / displayDuration) * 100;
                return (
                  <div 
                    key={`audio-${sub.id}`}
                    className={`absolute h-8 border rounded flex items-center justify-center overflow-hidden transition-all ${
                      generatingAudioIds.has(sub.id) 
                        ? 'bg-blue-50 border-blue-200 animate-pulse' 
                        : 'bg-white border-green-200'
                    }`}
                    style={{ left: `calc(1rem + ${leftPercent}%)`, width: `${widthPercent}%` }}
                  >
                     {generatingAudioIds.has(sub.id) ? (
                       <Loader2 className="w-3 h-3 animate-spin text-blue-400" />
                     ) : (
                       <svg width="100%" height="100%" preserveAspectRatio="none" viewBox="0 0 100 100">
                          <path d="M0,50 Q10,20 20,50 T40,50 T60,50 T80,50 T100,50" stroke="#52c41a" strokeWidth="1" fill="none" />
                          <path d="M0,50 Q10,80 20,50 T40,50 T60,50 T80,50 T100,50" stroke="#52c41a" strokeWidth="1" fill="none" />
                       </svg>
                     )}
                  </div>
                );
              })}
           </div>

           {/* Playhead */}
           <div 
             className="absolute top-0 bottom-0 w-px bg-red-500 z-30 cursor-ew-resize group"
             style={{ left: `calc(1rem + ${playheadPercent}%)` }}
             onMouseDown={(e) => {
               e.stopPropagation();
               setIsDraggingPlayhead(true);
             }}
           >
              <div className="absolute -top-1 -translate-x-1/2 w-3 h-3 bg-red-500 rotate-45 shadow-sm"></div>
              <div className="absolute top-0 bottom-0 -left-1 -right-1 cursor-ew-resize"></div>
           </div>
        </div>
      </div>

      {/* Modals */}
      {showVoiceMarket && (
        <VoiceMarketModal 
          onClose={() => setShowVoiceMarket(false)} 
          onSelect={(voiceId) => {
            if (voiceMarketTargetId) {
              const newSubs = subtitles.map(s => s.id === voiceMarketTargetId ? { ...s, voiceId, audioUrl: undefined } : s);
              setSubtitles(newSubs);
              setShowVoiceMarket(false);
            }
          }}
          onSelectAll={(voiceId) => {
            const newSubs = subtitles.map(s => ({ ...s, voiceId, audioUrl: undefined }));
            setSubtitles(newSubs);
            setShowVoiceMarket(false);
          }}
        />
      )}
      {showExportModal && (
        <ExportModal 
          onClose={() => setShowExportModal(false)} 
          videoFile={videoFile}
          subtitles={subtitles}
          bgmUrl={bgmUrl}
          bgmBase64={bgmBase64}
          textStyles={textStyles}
          trimRange={trimRange}
        />
      )}
    </div>
  );
}
