import * as React from 'react';
import { Avatar, Voice, VideoScene, VideoProject, AIGCVideo, AIGCSettings, MediaSource, ScriptContent, ScriptVersion } from '../types';
import { Icon } from './ui/Icon';
import { Tabs } from './ui/Tabs';
import { polishScript } from '../services/geminiService';

// --- MOCK DATA ---
const mockAvatars: Avatar[] = [
    { id: 'av1', name: 'Robotix', imageUrl: 'https://api.dicebear.com/8.x/bottts-neutral/svg?seed=robotix' },
    { id: 'av2', name: 'Cyber', imageUrl: 'https://api.dicebear.com/8.x/bottts-neutral/svg?seed=cyber' },
    { id: 'av3', name: 'Gizmo', imageUrl: 'https://api.dicebear.com/8.x/bottts-neutral/svg?seed=gizmo' },
];

const mockVoices: Voice[] = [ { id: 'vo1', name: 'Alloy', accent: 'Neutral' }, { id: 'vo2', name: 'Echo', accent: 'Warm' }, { id: 'vo3', name: 'Fable', accent: 'Professional' }];
const mockBackgrounds = { 
    colors: ['#111827', '#1f2937', '#374151', '#4b5563', '#6b7280', '#9ca3af', '#d1d5db', '#f3f4f6'], 
    images: [
        { type: 'url', value: 'https://picsum.photos/seed/bg1/800/450' }, 
        { type: 'url', value: 'https://picsum.photos/seed/bg2/800/450' }, 
        { type: 'url', value: 'https://picsum.photos/seed/bg3/800/450' }, 
        { type: 'url', value: 'https://picsum.photos/seed/bg4/800/450' }
    ] as MediaSource[]
};
const initialScriptVersionId = `v-init-${Date.now()}`;
const initialProject: VideoProject = { 
    id: `proj-${Date.now()}`, 
    name: 'My First Video', 
    aspectRatio: '16:9',
    scenes: [{ 
        id: `scene-${Date.now()}`, 
        script: {
            versions: [{ id: initialScriptVersionId, text: 'Welcome to our presentation!' }],
            selectedVersionId: initialScriptVersionId
        }, 
        avatarId: 'av1', 
        voiceId: 'vo1', 
        background: { type: 'color', value: '#1f2937' }, 
        avatarPosition: { x: 50, y: 10 },
        avatarScale: 1,
    }]
};

// --- Child Components ---
const GenerationProgress: React.FC<{ progress: number; totalVideos: number; currentVideo: number }> = ({ progress, totalVideos, currentVideo }) => (
    <div className="fixed inset-0 bg-black/80 flex flex-col items-center justify-center z-50">
        <div className="bg-gray-800 p-8 rounded-lg text-center w-full max-w-md">
            <h3 className="text-xl font-bold text-white mb-4">Generating Videos...</h3>
            <p className="text-gray-400 mb-4">{`Processing video ${currentVideo} of ${totalVideos}. This may take a moment.`}</p>
            <div className="w-full bg-gray-700 rounded-full h-4">
                <div className="bg-brand-primary h-4 rounded-full transition-all duration-500" style={{ width: `${progress}%` }} />
            </div>
        </div>
    </div>
);

const VideoCanvas: React.FC<{
    scene: VideoScene;
    aspectRatio: '16:9' | '9:16';
    onAvatarMove: (pos: { x: number, y: number }) => void;
    onAvatarScale: (newScale: number) => void;
}> = ({ scene, aspectRatio, onAvatarMove, onAvatarScale }) => {
    const canvasRef = React.useRef<HTMLDivElement>(null);
    const avatarRef = React.useRef<HTMLImageElement>(null);

    // Interaction state
    const [isSelected, setIsSelected] = React.useState(false);
    const [interactionState, setInteractionState] = React.useState<'idle' | 'dragging' | 'resizing'>('idle');

    // Refs to store start positions for calculations
    const interactionStartRef = React.useRef({
        dragOffsetX: 0,
        dragOffsetY: 0,
        resizeStartX: 0,
        resizeStartWidth: 0,
        resizeStartScale: 1,
    });

    const activeAvatar = mockAvatars.find(a => a.id === scene.avatarId);

    // Mouse Down on Avatar -> start dragging
    const handleAvatarMouseDown = (e: React.MouseEvent<HTMLImageElement>) => {
        e.preventDefault();
        e.stopPropagation();
        
        if (!avatarRef.current || !canvasRef.current) return;
        
        setIsSelected(true);
        setInteractionState('dragging');

        const avatarRect = avatarRef.current.getBoundingClientRect();
        interactionStartRef.current = {
            ...interactionStartRef.current,
            dragOffsetX: e.clientX - avatarRect.left,
            dragOffsetY: e.clientY - avatarRect.top,
        };
    };

    // Mouse Down on Resize Handle -> start resizing
    const handleResizeMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
        e.preventDefault();
        e.stopPropagation();

        if (!avatarRef.current) return;
        
        setInteractionState('resizing');
        interactionStartRef.current = {
            ...interactionStartRef.current,
            resizeStartX: e.clientX,
            resizeStartWidth: avatarRef.current.clientWidth,
            resizeStartScale: scene.avatarScale,
        };
    };

    // Effect for global mouse move and mouse up events
    React.useEffect(() => {
        const handleMouseMove = (e: MouseEvent) => {
            if (interactionState === 'idle' || !canvasRef.current) return;
            
            e.preventDefault();

            if (interactionState === 'dragging') {
                if (!avatarRef.current) return;
                const canvasRect = canvasRef.current.getBoundingClientRect();
                
                const newAvatarLeft = e.clientX - canvasRect.left - interactionStartRef.current.dragOffsetX;
                const newAvatarTop = e.clientY - canvasRect.top - interactionStartRef.current.dragOffsetY;
                
                const avatarWidth = avatarRef.current.offsetWidth;
                const avatarHeight = avatarRef.current.offsetHeight;

                const newXPercent = ((newAvatarLeft + avatarWidth / 2) / canvasRect.width) * 100;
                const newYFromBottom = canvasRect.height - newAvatarTop - avatarHeight;
                const newYPercent = (newYFromBottom / canvasRect.height) * 100;
                
                const clampedX = Math.max((avatarWidth / 2 / canvasRect.width) * 100, Math.min(100 - (avatarWidth / 2 / canvasRect.width) * 100, newXPercent));
                const clampedY = Math.max(0, Math.min(100 - (avatarHeight / canvasRect.height) * 100, newYPercent));

                onAvatarMove({ x: clampedX, y: clampedY });
            }

            if (interactionState === 'resizing') {
                 const deltaX = e.clientX - interactionStartRef.current.resizeStartX;
                 const newWidth = interactionStartRef.current.resizeStartWidth + deltaX;
                 const baseWidth = interactionStartRef.current.resizeStartWidth / interactionStartRef.current.resizeStartScale;
                 if (baseWidth === 0) return;
                 const newScale = newWidth / baseWidth;
                 onAvatarScale(Math.max(0.2, Math.min(3.0, newScale)));
            }
        };

        const handleMouseUp = () => {
            setInteractionState('idle');
        };

        window.addEventListener('mousemove', handleMouseMove);
        window.addEventListener('mouseup', handleMouseUp);
        
        return () => {
            window.removeEventListener('mousemove', handleMouseMove);
            window.removeEventListener('mouseup', handleMouseUp);
        };
    }, [interactionState, onAvatarMove, onAvatarScale]);
    
    // Deselect avatar when clicking on canvas background
    const handleCanvasMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
        if (e.target === e.currentTarget) {
            setIsSelected(false);
        }
    };

    const isVideoBg = scene.background.type === 'video';
    const backgroundStyle = scene.background.type !== 'video' ? {
        background: scene.background.type === 'color' ? scene.background.value : `url(${scene.background.value}) center/cover`
    } : {};
    
    return (
        <div ref={canvasRef} onMouseDown={handleCanvasMouseDown}
            className={`bg-black rounded-lg relative overflow-hidden shadow-2xl transition-all duration-300 max-w-full max-h-full ${aspectRatio === '16:9' ? 'aspect-video w-full' : 'aspect-[9/16] h-full'}`}
            style={backgroundStyle}>
            {isVideoBg && (
                <video key={scene.background.value} src={scene.background.value} autoPlay loop muted className="absolute top-0 left-0 w-full h-full object-cover" />
            )}
            {activeAvatar && 
                <div
                    className="absolute"
                    style={{
                        left: `${scene.avatarPosition.x}%`, 
                        bottom: `${scene.avatarPosition.y}%`, 
                        height: '80%',
                        transform: `translateX(-50%)`,
                        cursor: interactionState === 'dragging' ? 'grabbing' : 'grab',
                    }}
                >
                    <div className="relative w-auto h-full" style={{ transform: `scale(${scene.avatarScale})`, transformOrigin: 'bottom center' }}>
                        <img 
                            ref={avatarRef} 
                            src={activeAvatar.imageUrl} 
                            alt={activeAvatar.name} 
                            onMouseDown={handleAvatarMouseDown}
                            className="h-full object-contain select-none pointer-events-auto"
                        />
                        {isSelected && (
                            <>
                                <div className="absolute inset-0 border-2 border-dashed border-brand-primary pointer-events-none" />
                                <div 
                                    onMouseDown={handleResizeMouseDown}
                                    className="absolute -bottom-1 -right-1 w-4 h-4 bg-brand-primary border-2 border-white dark:border-gray-800 rounded-full cursor-se-resize pointer-events-auto"
                                />
                            </>
                        )}
                    </div>
                </div>
            }
        </div>
    );
};


// --- Main Component ---
interface VideoCreatorProps {
    aigcSettings: AIGCSettings;
    onUpdateAIGCSettings: (newSettings: AIGCSettings) => void;
    onVideosGenerated: (videos: AIGCVideo[]) => void;
}
const VideoCreator: React.FC<VideoCreatorProps> = ({ aigcSettings, onUpdateAIGCSettings, onVideosGenerated }) => {
    const [projects, setProjects] = React.useState<VideoProject[]>([initialProject]);
    const [activeProjectId, setActiveProjectId] = React.useState<string>(projects[0].id);
    const [activeSceneId, setActiveSceneId] = React.useState<string | null>(projects[0].scenes[0]?.id || null);
    const [selectedProjects, setSelectedProjects] = React.useState<string[]>([]);
    const [isGenerating, setIsGenerating] = React.useState(false);
    const [generationState, setGenerationState] = React.useState({ progress: 0, current: 0, total: 0 });
    const [editorTab, setEditorTab] = React.useState<'avatar' | 'voice' | 'script' | 'background'>('script');
    const [backgroundTab, setBackgroundTab] = React.useState<'color' | 'media'>('color');
    const [isPolishing, setIsPolishing] = React.useState(false);
    const [editingProjectId, setEditingProjectId] = React.useState<string | null>(null);
    const [editingProjectName, setEditingProjectName] = React.useState<string>('');

    const activeProject = React.useMemo(() => projects.find(p => p.id === activeProjectId), [projects, activeProjectId]);
    const activeScene = React.useMemo(() => activeProject?.scenes.find(s => s.id === activeSceneId), [activeProject, activeSceneId]);

    React.useEffect(() => {
        if (activeProject && (!activeSceneId || !activeProject.scenes.some(s => s.id === activeSceneId))) {
            setActiveSceneId(activeProject.scenes[0]?.id || null);
        }
    }, [activeProjectId, activeProject, activeSceneId]);

    const updateProject = (updatedProject: VideoProject) => {
        setProjects(prev => prev.map(p => p.id === updatedProject.id ? updatedProject : p));
    };

    const handleStartEditingProjectName = (project: VideoProject) => {
        setEditingProjectId(project.id);
        setEditingProjectName(project.name);
    };

    const handleCancelEditingProjectName = () => {
        setEditingProjectId(null);
        setEditingProjectName('');
    };

    const handleSaveProjectName = () => {
        if (!editingProjectId || !editingProjectName.trim()) {
            handleCancelEditingProjectName();
            return;
        }
        setProjects(prev => prev.map(p =>
            p.id === editingProjectId ? { ...p, name: editingProjectName.trim() } : p
        ));
        handleCancelEditingProjectName();
    };
    
    const addProject = () => {
        const newSceneId = `scene-${Date.now()}`;
        const newScriptVersionId = `v-new-${Date.now()}`;
        const newProject: VideoProject = { 
            id: `proj-${Date.now()}`, 
            name: `Untitled Video ${projects.length + 1}`, 
            aspectRatio: '16:9',
            scenes: [{ 
                id: newSceneId, 
                script: {
                    versions: [{ id: newScriptVersionId, text: 'New video script.' }],
                    selectedVersionId: newScriptVersionId,
                },
                avatarId: 'av1', 
                voiceId: 'vo1', 
                background: { type: 'image', value: (mockBackgrounds.images[0] as { type: 'url', value: string }).value }, 
                avatarPosition: { x: 50, y: 10 },
                avatarScale: 1
            }]
        };
        setProjects(prev => [...prev, newProject]);
        setActiveProjectId(newProject.id);
    };
    
    const deleteProject = (id: string) => {
        const newProjects = projects.filter(p => p.id !== id);
        if (newProjects.length === 0) return;
        setProjects(newProjects);
        if (activeProjectId === id) setActiveProjectId(newProjects[0].id);
    };

    const updateScene = (updatedScene: VideoScene) => {
        if (!activeProject) return;
        const updatedScenes = activeProject.scenes.map(s => s.id === updatedScene.id ? updatedScene : s);
        updateProject({ ...activeProject, scenes: updatedScenes });
    };

    const handleAddScene = () => {
        if (!activeProject) return;
        const newScriptVersionId = `v-new-${Date.now()}`;
        const newScene: VideoScene = { 
            id: `scene-${Date.now()}`, 
            script: {
                versions: [{ id: newScriptVersionId, text: 'New scene script.' }],
                selectedVersionId: newScriptVersionId,
            },
            avatarId: 'av2', 
            voiceId: 'vo2', 
            background: {type: 'color', value: '#111827'}, 
            avatarPosition: { x: 50, y: 10 },
            avatarScale: 1
        };
        const updatedScenes = [...activeProject.scenes, newScene];
        updateProject({ ...activeProject, scenes: updatedScenes });
        setActiveSceneId(newScene.id);
    };

    const handleDeleteScene = (sceneId: string) => {
        if (!activeProject || activeProject.scenes.length <= 1) {
            alert("A project must have at least one scene.");
            return;
        }
        const updatedScenes = activeProject.scenes.filter(s => s.id !== sceneId);
        updateProject({ ...activeProject, scenes: updatedScenes });
        if (activeSceneId === sceneId) {
            setActiveSceneId(updatedScenes[0]?.id || null);
        }
    };

    const handleGenerate = () => {
        const projectsToGenerate = projects.filter(p => selectedProjects.includes(p.id));
        if (projectsToGenerate.length === 0) return;
        setIsGenerating(true);
        setGenerationState({ progress: 0, current: 1, total: projectsToGenerate.length });
    };

    React.useEffect(() => {
        if (isGenerating) {
            const interval = setInterval(() => {
                setGenerationState(prev => {
                    const newProgress = prev.progress + 2;
                    if (newProgress >= 100) {
                        if (prev.current >= prev.total) {
                            clearInterval(interval);
                            const projectsToGenerate = projects.filter(p => selectedProjects.includes(p.id));
                            const newVideos: AIGCVideo[] = projectsToGenerate.map(p => ({ id: `vid-gen-${p.id}`, title: p.name, thumbnailUrl: `https://picsum.photos/seed/gen${p.id}/200/120`, videoUrl: 'https://storage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4' }));
                            onVideosGenerated(newVideos);
                            setIsGenerating(false);
                            setSelectedProjects([]);
                            return prev;
                        }
                        return { ...prev, progress: 0, current: prev.current + 1 };
                    }
                    return { ...prev, progress: newProgress };
                });
            }, 50);
            return () => clearInterval(interval);
        }
    }, [isGenerating, projects, selectedProjects, onVideosGenerated]);

    const handleUploadMedia = (type: 'image' | 'video') => {
        const isVideo = type === 'video';
        const newMedia: MediaSource = {
            type: 'file', // Simulating a file upload
            value: {
                name: isVideo ? `user_video_${Date.now()}.mp4` : `user_image_${Date.now()}.jpg`,
                size: 1234567,
                previewUrl: isVideo 
                    ? 'https://storage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4'
                    : `https://picsum.photos/seed/user-img-${Date.now()}/800/450`
            }
        };
        onUpdateAIGCSettings({
            ...aigcSettings,
            userMedia: [...(aigcSettings.userMedia || []), newMedia]
        });
    };

    const handleSelectMedia = (source: MediaSource) => {
        if (!activeScene) return;
        // FIX: Add explicit checks to ensure type-safe access to properties of the MediaSource union type.
        let url: string | undefined;
        let isVideo = false;

        if (source.type === 'file') {
            url = source.value.previewUrl;
            isVideo = ['.mp4', '.webm', '.ogg'].some(ext => source.value.name.endsWith(ext));
        } else if (source.type === 'url') {
            url = source.value;
            isVideo = ['.mp4', '.webm', '.ogg'].some(ext => url.endsWith(ext));
        }

        if (url) {
            updateScene({ ...activeScene, background: { type: isVideo ? 'video' : 'image', value: url } });
        }
    };
    
    if (!activeProject || !activeScene) return <div className="p-8 text-center text-gray-500 dark:text-gray-400">Loading editor...</div>

    const mediaGallery = [...mockBackgrounds.images, ...(aigcSettings.userMedia || [])];

    const renderEditorContent = () => {
        switch (editorTab) {
            case 'avatar': return <div><h4 className="font-semibold text-gray-900 dark:text-white mb-3">Avatar</h4><div className="grid grid-cols-3 gap-2">{mockAvatars.map(avatar => <div key={avatar.id} onClick={() => updateScene({ ...activeScene, avatarId: avatar.id })} className={`rounded-lg overflow-hidden cursor-pointer border-2 ${activeScene.avatarId === avatar.id ? 'border-brand-primary ring-2 ring-brand-primary/50' : 'border-gray-200 dark:border-gray-700'}`}><img src={avatar.imageUrl} alt={avatar.name} className="w-full h-auto bg-gray-100 dark:bg-gray-700" /><p className="text-xs text-center bg-gray-200/50 dark:bg-gray-900/50 py-1 text-gray-900 dark:text-white">{avatar.name}</p></div>)}</div></div>
            case 'voice': return <div> <h4 className="font-semibold text-gray-900 dark:text-white mb-3">Voice</h4> <select value={activeScene.voiceId} onChange={e => updateScene({ ...activeScene, voiceId: e.target.value })} className="w-full bg-gray-100 dark:bg-gray-700 p-2 rounded-md border border-gray-300 dark:border-gray-600"> {mockVoices.map(voice => <option key={voice.id} value={voice.id}>{`${voice.name} (${voice.accent})`}</option>)}</select></div>
            case 'script': {
                const scriptContent = activeScene.script;
                
                const handleScriptTextChange = (versionId: string, newText: string) => {
                    const newVersions = scriptContent.versions.map(v => 
                        v.id === versionId ? { ...v, text: newText } : v
                    );
                    updateScene({
                        ...activeScene,
                        script: { ...scriptContent, versions: newVersions },
                    });
                };

                const handleSelectVersion = (versionId: string) => {
                    updateScene({
                        ...activeScene,
                        script: { ...scriptContent, selectedVersionId: versionId },
                    });
                };
                
                const handleAIPolish = async () => {
                    if (!activeScene || isPolishing) return;
                    const currentVersion = activeScene.script.versions.find(v => v.id === activeScene.script.selectedVersionId);
                    if (!currentVersion || !currentVersion.text.trim()) {
                        alert("Please write a script first.");
                        return;
                    }
                    
                    setIsPolishing(true);
                    try {
                        const polishedVariations = await polishScript(currentVersion.text);

                        const newVersions = polishedVariations.map((text, i) => ({
                            id: `v-polished-${Date.now()}-${i}`,
                            text,
                        }));
                        
                        updateScene({
                            ...activeScene,
                            script: {
                                ...activeScene.script,
                                versions: [...activeScene.script.versions, ...newVersions],
                            },
                        });
                    } catch (error) {
                        console.error("Failed to polish script:", error);
                        alert("Sorry, we couldn't polish the script at this time.");
                    } finally {
                        setIsPolishing(false);
                    }
                };

                return (
                    <div>
                        <div className="flex justify-between items-center mb-3">
                            <h4 className="font-semibold text-gray-900 dark:text-white">Script</h4>
                            <button 
                                onClick={handleAIPolish}
                                disabled={isPolishing}
                                className="flex items-center gap-2 text-sm font-semibold bg-gray-200 dark:bg-gray-700 px-3 py-1.5 rounded-md hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors disabled:opacity-50"
                            >
                                <Icon className="h-4 w-4 text-brand-primary"><path strokeLinecap="round" strokeLinejoin="round" d="M9.75 3.104v5.714a2.25 2.25 0 01-.659 1.591L5 14.5M9.75 3.104c.251.023.501.05.75.082a9.75 9.75 0 016 6.062c.313.958.5 1.965.5 3.004v.75a2.25 2.25 0 01-2.25 2.25H3.75a2.25 2.25 0 01-2.25-2.25v-.75c0-1.04.187-2.046.5-3.004a9.75 9.75 0 016-6.062 12.312 12.312 0 01.75-.082zM9.75 18.75c-2.482 0-4.72-1.22-6.16-3.223" /></Icon>
                                {isPolishing ? 'Polishing...' : 'AI Polish'}
                            </button>
                        </div>
                        <div className="space-y-4 max-h-[60vh] overflow-y-auto pr-2 -mr-4">
                            {scriptContent.versions.map((version, index) => (
                                <div key={version.id} className="flex items-start gap-3">
                                    <input
                                        type="radio"
                                        name={`script-version-${activeScene.id}`}
                                        id={`version-${version.id}`}
                                        checked={scriptContent.selectedVersionId === version.id}
                                        onChange={() => handleSelectVersion(version.id)}
                                        className="mt-3 h-4 w-4 bg-gray-100 dark:bg-gray-900 border-gray-300 dark:border-gray-600 text-brand-primary focus:ring-brand-secondary"
                                    />
                                    <div className="flex-1">
                                        <label htmlFor={`version-text-${version.id}`} className="sr-only">{`Script Version ${index + 1}`}</label>
                                        <textarea
                                            id={`version-text-${version.id}`}
                                            rows={4}
                                            value={version.text}
                                            onChange={e => handleScriptTextChange(version.id, e.target.value)}
                                            className="w-full bg-gray-100 dark:bg-gray-700 p-2 rounded-md border border-gray-300 dark:border-gray-600 focus:ring-1 focus:ring-brand-primary focus:border-brand-primary"
                                        />
                                    </div>
                                </div>
                            ))}
                        </div>
                    </div>
                );
            }
            case 'background': return (
                <div className="flex flex-col h-full">
                    <div className="flex-shrink-0">
                        <h4 className="font-semibold text-gray-900 dark:text-white mb-3">Background</h4>
                        <div className="flex gap-1 mb-3 p-1 bg-gray-200 dark:bg-gray-900 rounded-lg">
                            <button onClick={() => { setBackgroundTab('color'); updateScene({ ...activeScene, background: { type: 'color', value: mockBackgrounds.colors[0] } })}} className={`flex-1 py-1 text-xs rounded-md ${backgroundTab === 'color' ? 'bg-brand-primary text-white shadow' : 'hover:bg-gray-300 dark:hover:bg-gray-700'}`}>Color</button>
                            <button onClick={() => { setBackgroundTab('media'); if(mediaGallery.length > 0) handleSelectMedia(mediaGallery[0]); }} className={`flex-1 py-1 text-xs rounded-md ${backgroundTab === 'media' ? 'bg-brand-primary text-white shadow' : 'hover:bg-gray-300 dark:hover:bg-gray-700'}`}>Media</button>
                        </div>
                    </div>

                    {backgroundTab === 'color' && (
                        <div className="grid grid-cols-4 gap-2 flex-shrink-0">
                            {mockBackgrounds.colors.map(color => (
                                <button key={color} onClick={() => updateScene({ ...activeScene, background: { type: 'color', value: color } })} className={`h-12 rounded-md ${activeScene.background.value === color && activeScene.background.type === 'color' ? 'ring-2 ring-brand-primary ring-offset-2 ring-offset-gray-800' : ''}`} style={{ backgroundColor: color }} />
                            ))}
                        </div>
                    )}

                    {backgroundTab === 'media' && (
                        <div className="flex flex-col flex-1 min-h-0">
                             <div className="grid grid-cols-2 gap-2 mb-3 flex-shrink-0">
                                <button onClick={() => handleUploadMedia('image')} className="w-full text-xs p-2 bg-gray-200 dark:bg-gray-700 rounded-md hover:bg-gray-300 dark:hover:bg-gray-600">Upload Image</button>
                                <button onClick={() => handleUploadMedia('video')} className="w-full text-xs p-2 bg-gray-200 dark:bg-gray-700 rounded-md hover:bg-gray-300 dark:hover:bg-gray-600">Upload Video</button>
                            </div>
                            <div className="flex-1 overflow-y-auto pr-2 -mr-4">
                                <div className="grid grid-cols-2 gap-3">
                                    {mediaGallery.map((media, index) => {
                                        let url: string | undefined;
                                        let isVideo = false;
                                        // FIX: Use explicit checks to ensure type-safe access to properties of the MediaSource union type.
                                        if (media.type === 'file') {
                                            url = media.value.previewUrl;
                                            isVideo = ['.mp4', '.webm', '.ogg'].some(ext => media.value.name.endsWith(ext));
                                        } else if (media.type === 'url') {
                                            url = media.value;
                                            isVideo = ['.mp4', '.webm', '.ogg'].some(ext => url.endsWith(ext));
                                        }

                                        if (!url) return null;

                                        const thumbnailUrl = isVideo ? `https://picsum.photos/seed/vid-thumb-${index}/200` : url;

                                        return (
                                            <button key={`${url}-${index}`} onClick={() => handleSelectMedia(media)} className={`relative aspect-[16/9] rounded-lg bg-cover bg-center group ${activeScene.background.value === url ? 'ring-2 ring-brand-primary ring-offset-2 ring-offset-gray-800' : ''}`}>
                                                <img src={thumbnailUrl} className="w-full h-full object-cover rounded-md" alt="Media thumbnail"/>
                                                {isVideo && <div className="absolute inset-0 bg-black/50 flex items-center justify-center"><Icon className="h-6 w-6 text-white"><path strokeLinecap="round" strokeLinejoin="round" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" /><path strokeLinecap="round" strokeLinejoin="round" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></Icon></div>}
                                            </button>
                                        )
                                    })}
                                </div>
                            </div>
                        </div>
                    )}
                </div>
            );
        }
    }

    return (
        <>
            {isGenerating && <GenerationProgress progress={generationState.progress} totalVideos={generationState.total} currentVideo={generationState.current} />}
            <div className="flex flex-col h-full bg-gray-100 dark:bg-gray-900">
                 <div className="flex items-center gap-2 p-2 bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 overflow-x-auto flex-shrink-0">
                    {projects.map(p => (
                        <div key={p.id} className={`flex items-center gap-2 p-2 rounded-md text-sm cursor-pointer border ${activeProjectId === p.id ? 'bg-brand-primary/10 border-brand-primary text-brand-primary' : 'border-transparent hover:bg-gray-200/50 dark:hover:bg-gray-700'}`}>
                            <input type="checkbox" checked={selectedProjects.includes(p.id)} onChange={() => {setSelectedProjects(prev => prev.includes(p.id) ? prev.filter(id => id !== p.id) : [...prev, p.id]);}} className="h-4 w-4 rounded bg-gray-100 dark:bg-gray-900 border-gray-300 dark:border-gray-600 text-brand-primary focus:ring-brand-secondary"/>
                            {editingProjectId === p.id ? (
                                <input
                                    type="text"
                                    value={editingProjectName}
                                    onChange={e => setEditingProjectName(e.target.value)}
                                    onBlur={handleSaveProjectName}
                                    onKeyDown={e => {
                                        if (e.key === 'Enter') handleSaveProjectName();
                                        if (e.key === 'Escape') handleCancelEditingProjectName();
                                    }}
                                    autoFocus
                                    className="bg-white dark:bg-gray-700 text-sm p-1 rounded-sm border border-brand-primary focus:outline-none"
                                />
                            ) : (
                                <span onDoubleClick={() => handleStartEditingProjectName(p)} onClick={() => setActiveProjectId(p.id)} title="Double-click to rename">
                                    {p.name}
                                </span>
                            )}
                            <button onClick={() => deleteProject(p.id)} className="text-gray-400 dark:text-gray-500 hover:text-red-500">×</button>
                        </div>
                    ))}
                    <button onClick={addProject} className="p-2 rounded-full h-8 w-8 flex items-center justify-center hover:bg-gray-200 dark:hover:bg-gray-700 text-gray-500 dark:text-gray-400 text-lg flex-shrink-0">+</button>
                </div>

                <div className="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 p-3 flex items-center gap-3 overflow-x-auto flex-shrink-0">
                    {activeProject.scenes.map((scene, index) => (
                        <div key={scene.id} onClick={() => setActiveSceneId(scene.id)} className={`group relative p-2 rounded-lg cursor-pointer border-2 flex flex-col gap-2 items-center justify-center h-24 aspect-video flex-shrink-0 ${activeSceneId === scene.id ? 'border-brand-primary bg-gray-100 dark:bg-gray-700/50' : 'border-transparent bg-gray-50 dark:bg-gray-900/50 hover:bg-gray-100 dark:hover:bg-gray-700'}`}>
                             <div className="w-full h-full bg-cover bg-center rounded" style={{background: scene.background.type === 'color' ? scene.background.value : `url(${scene.background.value}) center/cover`}}/>
                             <p className="text-xs font-semibold text-gray-700 dark:text-gray-300">{`Scene ${index + 1}`}</p>
                             <button onClick={e => { e.stopPropagation(); handleDeleteScene(scene.id);}} className="absolute -top-1 -right-1 h-5 w-5 bg-red-500 text-white rounded-full flex items-center justify-center text-xs opacity-0 group-hover:opacity-100 transition-opacity">×</button>
                         </div>
                     ))}
                     <button onClick={handleAddScene} className="h-24 aspect-video flex-shrink-0 flex flex-col items-center justify-center bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-lg text-gray-500 dark:text-gray-400">
                        <Icon className="h-8 w-8"><path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" /></Icon>
                        <span className="text-xs mt-1">Add Scene</span>
                    </button>
                </div>
                
                <div className="flex flex-1 overflow-hidden">
                    <aside className="w-96 bg-white dark:bg-gray-800 p-4 flex flex-col border-r border-gray-200 dark:border-gray-700">
                        <Tabs tabs={['avatar', 'voice', 'script', 'background']} activeTab={editorTab} onTabClick={(t) => setEditorTab(t as any)} />
                        <div className="flex-1 overflow-y-auto pt-6 pr-2 -mr-4">{renderEditorContent()}</div>
                         <div className="mt-4 flex-shrink-0"><button onClick={handleGenerate} disabled={selectedProjects.length === 0} className="w-full bg-brand-primary text-white font-bold py-3 px-4 rounded-md hover:bg-brand-secondary transition-colors disabled:bg-gray-500 disabled:cursor-not-allowed">{`Generate ${selectedProjects.length} Video${selectedProjects.length !== 1 ? 's' : ''}`}</button></div>
                    </aside>
                    
                    <main className="flex-1 flex flex-col items-center justify-center p-8 bg-gray-100 dark:bg-gray-900 overflow-hidden space-y-4">
                         <div className="flex items-center gap-1 bg-gray-200 dark:bg-gray-800 p-1 rounded-lg">
                            <button onClick={() => updateProject({...activeProject, aspectRatio: '16:9'})} className={`px-3 py-1 text-sm rounded-md flex items-center gap-2 ${activeProject.aspectRatio === '16:9' ? 'bg-brand-primary text-white' : 'hover:bg-gray-300 dark:hover:bg-gray-700'}`}>16:9</button>
                            <button onClick={() => updateProject({...activeProject, aspectRatio: '9:16'})} className={`px-3 py-1 text-sm rounded-md flex items-center gap-2 ${activeProject.aspectRatio === '9:16' ? 'bg-brand-primary text-white' : 'hover:bg-gray-300 dark:hover:bg-gray-700'}`}>9:16</button>
                        </div>
                        <div className="w-full flex-1 flex items-center justify-center overflow-hidden">
                            <VideoCanvas scene={activeScene} aspectRatio={activeProject.aspectRatio} onAvatarMove={pos => updateScene({ ...activeScene, avatarPosition: pos })} onAvatarScale={scale => updateScene({ ...activeScene, avatarScale: scale })}/>
                        </div>
                    </main>
                </div>

            </div>
        </>
    );
};

export default VideoCreator;