
import React, { useState, useEffect, useRef } from 'react';
import { SceneData, SceneStatus, StyleOption, ModelSettings, CharacterData, LocationData, ReferenceImage, CameraAngle, ShotSize } from '../types';
import { generateImageService, generateVideoService, refineActionToPrompt, constructSpatialPrompt } from '../services/geminiService';
import { CAMERA_ANGLE_LABELS, SHOT_SIZE_LABELS } from '../constants';
import { Image, Video, RefreshCw, Sparkles, Settings, X, Camera, Film, Eye, Wand2, ChevronDown, CheckCircle, Move, Download, Scan, Trash2, MapPin, User, Package, Upload } from 'lucide-react';

interface SceneEditorProps {
  scene: SceneData;
  characters: CharacterData[];
  locations: LocationData[];
  styleOption: StyleOption;
  onUpdate: (updatedScene: SceneData) => void;
  onDelete: (sceneId: string) => void;
  modelSettings: ModelSettings;
}

const SceneEditor: React.FC<SceneEditorProps> = ({ scene, characters, locations, styleOption, onUpdate, onDelete, modelSettings }) => {
  const [isLoading, setIsLoading] = useState(false);
  const [isRefining, setIsRefining] = useState(false);
  
  const [actionInput, setActionInput] = useState(scene.characterPrompt || scene.description);
  const [videoPromptInput, setVideoPromptInput] = useState(scene.videoPrompt || "");
  
  const [cameraAngle, setCameraAngle] = useState<CameraAngle>(scene.cameraAngle || CameraAngle.EYE_LEVEL);
  const [shotSize, setShotSize] = useState<ShotSize>(scene.shotSize || ShotSize.MEDIUM);
  
  const [showRawPromptModal, setShowRawPromptModal] = useState(false);
  const [rawPrompt, setRawPrompt] = useState("");

  const canvasRef = useRef<HTMLDivElement>(null);
  const propInputRef = useRef<HTMLInputElement>(null);
  
  const [charPositions, setCharPositions] = useState<Record<string, {x: number, y: number}>>({});
  const [propPositions, setPropPositions] = useState<Record<string, {x: number, y: number}>>({});
  
  const [draggedId, setDraggedId] = useState<string | null>(null);
  const [dragType, setDragType] = useState<'char' | 'prop' | null>(null);

  const currentLocation = locations.find(l => l.id === scene.locationId);
  const activeCharacters = characters.filter(c => scene.characterIds && scene.characterIds.includes(c.id));
  const activeProps = scene.props || [];

  const hasLocationMaster = !!currentLocation?.masterImage;
  const currentImage = scene.videoUrl || scene.compositeImage || scene.backgroundImage || currentLocation?.masterImage;

  useEffect(() => {
    // Initialize character positions
    const initialCharPos: Record<string, {x: number, y: number}> = {};
    activeCharacters.forEach((char, index) => {
        if (!charPositions[char.id]) {
            initialCharPos[char.id] = { x: 20 + (index * 30), y: 60 };
        }
    });
    setCharPositions(prev => ({...prev, ...initialCharPos}));

    // Initialize prop positions
    const initialPropPos: Record<string, {x: number, y: number}> = {};
    activeProps.forEach((prop, index) => {
        if (!propPositions[prop.id]) {
            initialPropPos[prop.id] = { x: 50 + (index * 10), y: 50 };
        }
    });
    setPropPositions(prev => ({...prev, ...initialPropPos}));

  }, [scene.characterIds, scene.props]);

  useEffect(() => {
    if (scene.characterPrompt) setActionInput(scene.characterPrompt);
    if (scene.videoPrompt) {
        setVideoPromptInput(scene.videoPrompt);
    } else {
        const defaultVideoJson = { 
            prompt: "Cinematic motion, character moving naturally",
            camera_movement: "pan_right",
            motion_strength: 5 
        };
        setVideoPromptInput(JSON.stringify(defaultVideoJson, null, 2));
    }
    if (scene.cameraAngle) setCameraAngle(scene.cameraAngle);
    if (scene.shotSize) setShotSize(scene.shotSize);
  }, [scene.characterPrompt, scene.videoPrompt, scene.description, scene.cameraAngle, scene.shotSize]);

  const getSemanticPosition = (x: number, y: number): string => {
      let h = "center";
      if (x < 33) h = "left"; else if (x > 66) h = "right";
      let v = "center";
      if (y < 33) v = "top"; else if (y > 66) v = "bottom";
      if (h === "center" && v === "center") return "center of the frame";
      return `${v} ${h} of the frame`;
  };

  const constructFullPrompt = (overrideAction?: string) => {
    const refs: ReferenceImage[] = [];
    activeCharacters.forEach(c => {
         const pos = charPositions[c.id] || {x: 50, y: 50};
         
         // DETERMINE VARIANT IMAGE
         const variantId = scene.characterVariantMap?.[c.id];
         const variant = c.variants?.find(v => v.id === variantId);
         const imageUrl = variant ? variant.imageUrl : c.masterImage;

         if (imageUrl) {
            refs.push({ id: c.id, url: imageUrl, x: pos.x, y: pos.y, width: 0, zIndex: 0, usage: 'face', semanticPosition: getSemanticPosition(pos.x, pos.y) });
         }
    });
    activeProps.forEach(p => {
         const pos = propPositions[p.id] || {x: 50, y: 50};
         refs.push({ ...p, semanticPosition: getSemanticPosition(pos.x, pos.y) });
    });

    const actionWithCamera = `[Camera: ${cameraAngle}, Shot: ${shotSize}] ${overrideAction || actionInput}`;

    return constructSpatialPrompt(
        actionWithCamera,
        styleOption,
        refs,
        'scene',
        true,
        modelSettings.googleApiKey
    );
  };

  const openRawPromptModal = () => { setRawPrompt(constructFullPrompt()); setShowRawPromptModal(true); };

  const handleRefineAction = async () => {
      if (!actionInput) return;
      if (!modelSettings.googleApiKey) {
          alert("請先輸入 Google API Key");
          return;
      }
      setIsRefining(true);
      try {
          const refined = await refineActionToPrompt(actionInput, styleOption.promptModifier, modelSettings.textModel, modelSettings.googleApiKey);
          setActionInput(refined); 
      } catch (e) { console.error(e); } finally { setIsRefining(false); }
  };

  const handleMouseMove = (e: React.MouseEvent) => {
      if (!draggedId || !canvasRef.current || !dragType) return;
      const rect = canvasRef.current.getBoundingClientRect();
      const x = Math.max(0, Math.min(100, ((e.clientX - rect.left) / rect.width) * 100));
      const y = Math.max(0, Math.min(100, ((e.clientY - rect.top) / rect.height) * 100));
      
      if (dragType === 'char') {
          setCharPositions(prev => ({ ...prev, [draggedId]: { x, y } }));
      } else {
          setPropPositions(prev => ({ ...prev, [draggedId]: { x, y } }));
      }
  };

  const handlePropUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
      const file = e.target.files?.[0];
      if (!file) return;
      const reader = new FileReader();
      reader.onload = (event) => {
          if (event.target?.result) {
              const newProp: ReferenceImage = {
                  id: `prop-${Date.now()}`,
                  url: event.target.result as string,
                  x: 50, y: 50, width: 80, zIndex: 10,
                  usage: 'prop'
              };
              const newProps = [...(scene.props || []), newProp];
              onUpdate({ ...scene, props: newProps });
          }
      };
      reader.readAsDataURL(file);
      e.target.value = '';
  };

  const removeProp = (propId: string) => {
      onUpdate({ ...scene, props: (scene.props || []).filter(p => p.id !== propId) });
  };
  
  const handleVariantChange = (charId: string, variantId: string) => {
      const newMap = { ...(scene.characterVariantMap || {}), [charId]: variantId };
      onUpdate({ ...scene, characterVariantMap: newMap });
  };

  const handleDirectSynthesis = async () => {
     if (!hasLocationMaster) {
         alert("請先選擇一個已生成定裝照的場景 (Location)。");
         return;
     }
     if (!modelSettings.googleApiKey) {
         alert("請先輸入 Google API Key");
         return;
     }
     setIsLoading(true);
     onUpdate({ ...scene, status: SceneStatus.GENERATING_CHAR });
     try {
        const refs: ReferenceImage[] = [];
        
        // Add Character Refs (Variant Aware)
        activeCharacters.forEach(c => {
            const variantId = scene.characterVariantMap?.[c.id];
            const variant = c.variants?.find(v => v.id === variantId);
            const imageUrl = variant ? variant.imageUrl : c.masterImage;

            if (imageUrl) {
                const pos = charPositions[c.id] || {x: 50, y: 50};
                refs.push({ 
                    id: `char-master-${c.id}`, 
                    url: imageUrl, 
                    x: pos.x, 
                    y: pos.y, 
                    width: 0, 
                    zIndex: 0, 
                    usage: 'face', 
                    semanticPosition: getSemanticPosition(pos.x, pos.y) 
                });
            }
        });

        // Add Prop Refs
        activeProps.forEach(p => {
             const pos = propPositions[p.id] || {x: 50, y: 50};
             refs.push({
                 ...p,
                 semanticPosition: getSemanticPosition(pos.x, pos.y)
             });
        });

        const actionWithCamera = `[Camera: ${cameraAngle}, Shot: ${shotSize}] ${actionInput}`;
        const finalPrompt = constructSpatialPrompt(
            actionWithCamera,
            styleOption,
            refs,
            'scene',
            true,
            modelSettings.googleApiKey
        );

        const imageUrl = await generateImageService(
            finalPrompt, 
            styleOption, 
            modelSettings.imageModel, 
            'scene', 
            currentLocation!.masterImage, 
            refs,
            modelSettings.googleApiKey,
            modelSettings.devMode || false
        );
        onUpdate({ 
            ...scene, 
            backgroundImage: currentLocation!.masterImage, 
            compositeImage: imageUrl, 
            characterPrompt: actionInput, 
            cameraAngle: cameraAngle, 
            shotSize: shotSize, 
            status: SceneStatus.CHAR_READY 
        });
     } catch (error: any) { 
         onUpdate({ ...scene, status: SceneStatus.ERROR }); 
         alert(error.message);
     } finally { setIsLoading(false); setShowRawPromptModal(false); }
  };

  const handleGenerateVideo = async () => {
    if (!scene.compositeImage) return;
    setIsLoading(true);
    onUpdate({ ...scene, status: SceneStatus.GENERATING_VIDEO });
    try {
      const videoUrl = await generateVideoService(videoPromptInput, scene.compositeImage);
      onUpdate({ ...scene, videoUrl: videoUrl, videoPrompt: videoPromptInput, status: SceneStatus.VIDEO_READY });
    } catch (error) { onUpdate({ ...scene, status: SceneStatus.ERROR }); } finally { setIsLoading(false); }
  };

  const handleDownloadImage = (url: string, filename: string) => {
      const link = document.createElement('a');
      link.href = url;
      link.download = filename;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
  };
  
  const toggleCharacter = (charId: string) => {
      const currentIds = scene.characterIds || [];
      const newIds = currentIds.includes(charId) 
          ? currentIds.filter(id => id !== charId) 
          : [...currentIds, charId];
      onUpdate({ ...scene, characterIds: newIds });
  };

  return (
    <div className="glass-card rounded-3xl overflow-hidden flex flex-col md:flex-row shadow-2xl min-h-[550px] transition-all hover:border-white/20">
      
      {/* Visual Area */}
      <div 
        ref={canvasRef}
        onMouseMove={handleMouseMove}
        onMouseUp={() => { setDraggedId(null); setDragType(null); }}
        onMouseLeave={() => { setDraggedId(null); setDragType(null); }}
        className="relative w-full md:w-7/12 bg-black/40 group overflow-hidden flex items-center justify-center backdrop-blur-sm select-none"
      >
        <div className="absolute top-4 left-4 z-30 flex gap-2">
            <button onClick={() => propInputRef.current?.click()} className="p-2 bg-black/50 hover:bg-black/80 text-emerald-400 rounded-lg backdrop-blur-md transition-all flex items-center gap-2 text-xs font-bold border border-emerald-500/30">
                <Upload className="w-3 h-3" /> 上傳道具
            </button>
            <input type="file" ref={propInputRef} className="hidden" accept="image/*" onChange={handlePropUpload} />
        </div>

        {currentImage ? (
          scene.videoUrl ? (
            <video src={currentImage} controls autoPlay loop className="w-full h-full object-contain" />
          ) : (
            <div className="relative w-full h-full">
                <img src={currentImage} className="w-full h-full object-contain pointer-events-none" />
                {scene.compositeImage && (
                    <button 
                        onClick={() => handleDownloadImage(scene.compositeImage!, `lumina-scene-${scene.sceneNumber}.png`)}
                        className="absolute bottom-4 right-4 bg-black/60 hover:bg-black/90 text-white p-3 rounded-full backdrop-blur-md transition-all z-40 border border-white/20 shadow-lg"
                        title="下載合成圖片"
                    >
                        <Download className="w-5 h-5" />
                    </button>
                )}
            </div>
          )
        ) : (
          <div className="text-center p-8"><Image className="w-16 h-16 mb-4 text-zinc-700 mx-auto" /><p className="text-zinc-600 font-medium">準備合成</p></div>
        )}

        {!scene.videoUrl && !isLoading && !scene.compositeImage && activeCharacters.map(char => {
            const variantId = scene.characterVariantMap?.[char.id];
            const variant = char.variants?.find(v => v.id === variantId);
            const img = variant ? variant.imageUrl : char.masterImage;
            
            if (!img) return null;
            const pos = charPositions[char.id] || {x: 50, y: 50};
            return (
                <div 
                    key={char.id}
                    onMouseDown={(e) => { e.preventDefault(); setDraggedId(char.id); setDragType('char'); }}
                    className={`absolute w-20 h-20 rounded-full border-2 border-white/50 shadow-2xl overflow-hidden cursor-move z-10 ${draggedId === char.id ? 'scale-110 border-indigo-400' : ''}`}
                    style={{ 
                        left: `${pos.x}%`, 
                        top: `${pos.y}%`, 
                        transform: 'translate(-50%, -50%)',
                        backgroundImage: `url(${img})`,
                        backgroundSize: 'cover'
                    }}
                    title={`${char.name} (${variant ? variant.name : 'Default'})`}
                />
            );
        })}

        {!scene.videoUrl && !isLoading && !scene.compositeImage && activeProps.map(prop => {
            const pos = propPositions[prop.id] || {x: 50, y: 50};
            return (
                <div 
                    key={prop.id}
                    onMouseDown={(e) => { e.preventDefault(); setDraggedId(prop.id); setDragType('prop'); }}
                    className={`absolute w-20 h-20 border border-emerald-400/50 shadow-xl cursor-move z-20 group/prop ${draggedId === prop.id ? 'scale-110 border-emerald-400' : ''}`}
                    style={{ 
                        left: `${pos.x}%`, 
                        top: `${pos.y}%`, 
                        transform: 'translate(-50%, -50%)'
                    }}
                >
                    <img src={prop.url} className="w-full h-full object-contain pointer-events-none" />
                    <button onClick={() => removeProp(prop.id)} className="absolute -top-2 -right-2 bg-red-500 text-white rounded-full p-0.5 opacity-0 group-hover/prop:opacity-100 transition-opacity"><X className="w-3 h-3" /></button>
                </div>
            );
        })}

        {isLoading && <div className="absolute inset-0 bg-black/80 flex flex-col items-center justify-center z-20"><RefreshCw className="w-10 h-10 text-indigo-500 animate-spin mb-4" /><span className="text-xs text-indigo-400 font-bold tracking-[0.2em] animate-pulse">RENDERING...</span></div>}
      </div>

      {/* Control Area */}
      <div className="w-full md:w-5/12 p-8 flex flex-col bg-zinc-900/10 backdrop-blur-md border-l border-white/5">
        <div className="mb-4 pb-4 border-b border-white/5 flex justify-between items-start">
             <div className="flex-1">
                 <div className="flex items-center gap-2 mb-1">
                     <span className="text-xs text-zinc-500">場次</span>
                     <input
                         type="number"
                         value={scene.sceneNumber}
                         onChange={(e) => onUpdate({ ...scene, sceneNumber: parseInt(e.target.value) || 1 })}
                         className="text-2xl font-bold text-white tracking-tight bg-transparent border-none outline-none focus:outline-none focus:ring-0 p-0 w-20"
                         style={{ borderBottom: '1px solid transparent' }}
                         onFocus={(e) => e.target.style.borderBottomColor = 'rgba(99, 102, 241, 0.5)'}
                         onBlur={(e) => e.target.style.borderBottomColor = 'transparent'}
                         min="1"
                     />
                 </div>
                 <p className="text-xs text-zinc-500">Scene Control</p>
             </div>
             <button onClick={() => onDelete(scene.id)} className="text-zinc-600 hover:text-red-400 p-2 rounded-lg hover:bg-white/5 transition-colors">
                 <Trash2 className="w-4 h-4" />
             </button>
        </div>

        <div className="space-y-6 flex-1 overflow-y-auto pr-2">
            
            <div className="bg-white/5 rounded-xl p-4 space-y-4">
                <h4 className="text-xs font-bold text-zinc-400 uppercase tracking-wider flex items-center gap-2"><Settings className="w-3 h-3" /> 場景調度 (Setup)</h4>
                
                <div>
                    <label className="text-[10px] text-zinc-500 uppercase font-bold mb-1 block flex items-center gap-1"><MapPin className="w-3 h-3" /> 地點 (Location)</label>
                    <select 
                        value={scene.locationId || ''} 
                        onChange={(e) => onUpdate({ ...scene, locationId: e.target.value })}
                        className="glass-input w-full rounded-lg p-2 text-xs"
                    >
                        <option value="">選擇地點...</option>
                        {locations.map(l => <option key={l.id} value={l.id}>{l.name} {l.masterImage ? '✓' : ''}</option>)}
                    </select>
                </div>

                <div>
                    <label className="text-[10px] text-zinc-500 uppercase font-bold mb-2 block flex items-center gap-1"><User className="w-3 h-3" /> 演員 (Cast)</label>
                    <div className="flex flex-col gap-2">
                        {characters.map(c => {
                            const isSelected = scene.characterIds?.includes(c.id);
                            const variants = c.variants || [];
                            return (
                                <div key={c.id} className="flex items-center gap-2">
                                    <button 
                                        onClick={() => toggleCharacter(c.id)}
                                        className={`px-2 py-1.5 rounded text-xs border transition-all flex-1 text-left ${isSelected ? 'bg-indigo-500/30 border-indigo-500 text-white' : 'border-zinc-700 text-zinc-500 hover:border-zinc-500'}`}
                                    >
                                        {c.name} {c.masterImage ? '✓' : ''}
                                    </button>
                                    
                                    {/* Variant Selector */}
                                    {isSelected && variants.length > 0 && (
                                        <select
                                            value={scene.characterVariantMap?.[c.id] || ''}
                                            onChange={(e) => handleVariantChange(c.id, e.target.value)}
                                            className="glass-input rounded-lg p-1 text-[10px] w-24 bg-black"
                                        >
                                            <option value="">預設造型</option>
                                            {variants.map(v => <option key={v.id} value={v.id}>{v.name}</option>)}
                                        </select>
                                    )}
                                </div>
                            )
                        })}
                    </div>
                </div>
            </div>

            <div className="grid grid-cols-2 gap-3">
              <div>
                <label className="text-[10px] text-zinc-500 uppercase font-bold tracking-wider mb-1 block">
                    <Move className="w-3 h-3 inline mr-1" /> 運鏡視角 (Angle)
                </label>
                <select
                    value={cameraAngle}
                    onChange={(e) => setCameraAngle(e.target.value as CameraAngle)}
                    className="glass-input w-full rounded-xl p-2 text-xs appearance-none bg-zinc-900"
                >
                    {Object.entries(CAMERA_ANGLE_LABELS).map(([key, label]) => (
                        <option key={key} value={key} className="bg-zinc-900">{label}</option>
                    ))}
                </select>
              </div>
              <div>
                <label className="text-[10px] text-zinc-500 uppercase font-bold tracking-wider mb-1 block">
                    <Scan className="w-3 h-3 inline mr-1" /> 鏡頭景別 (Shot)
                </label>
                <select
                    value={shotSize}
                    onChange={(e) => setShotSize(e.target.value as ShotSize)}
                    className="glass-input w-full rounded-xl p-2 text-xs appearance-none bg-zinc-900"
                >
                    {Object.entries(SHOT_SIZE_LABELS).map(([key, label]) => (
                        <option key={key} value={key} className="bg-zinc-900">{label}</option>
                    ))}
                </select>
              </div>
            </div>

            <div className="space-y-2">
                <div className="flex justify-between items-center">
                    <label className="text-[10px] text-zinc-500 uppercase font-bold tracking-wider">動作/劇情 (Action)</label>
                    <button onClick={openRawPromptModal} className="text-[10px] text-indigo-400 flex items-center gap-1"><Settings className="w-3 h-3" /> 原始指令</button>
                </div>
                <div className="relative">
                    <textarea 
                        value={actionInput} 
                        onChange={(e) => setActionInput(e.target.value)} 
                        className="glass-input w-full rounded-xl p-3 text-sm focus:outline-none resize-none min-h-[80px]" 
                        placeholder="請描述動作..."
                    />
                    <button onClick={handleRefineAction} disabled={isRefining} className="absolute right-2 bottom-2 text-indigo-500 hover:text-white bg-indigo-500/10 p-1.5 rounded-lg"><Wand2 className={`w-4 h-4 ${isRefining ? 'animate-spin' : ''}`} /></button>
                </div>
            </div>
            
            {hasLocationMaster ? (
                 <button onClick={handleDirectSynthesis} disabled={isLoading} className="glass-btn w-full bg-indigo-600/30 border-indigo-500/50 hover:bg-indigo-600/50 text-white py-3 rounded-xl font-bold flex items-center justify-center gap-2">
                    <Sparkles className="w-4 h-4" /> {scene.compositeImage ? '重新合成 (Re-Synthesize)' : '合成場景 (Synthesize)'}
                </button>
            ) : (
                <div className="p-3 bg-red-500/10 border border-red-500/30 rounded-xl text-red-300 text-xs text-center">
                    請先選擇一個有效的地點 (Location)
                </div>
            )}

            {scene.compositeImage && (
                <div className="border-t border-white/5 pt-4 mt-2 space-y-3">
                    <label className="text-[10px] text-zinc-500 uppercase font-bold tracking-wider flex items-center gap-1"><Film className="w-3 h-3" /> 影片控制 (Veo JSON)</label>
                    <textarea 
                        value={videoPromptInput} 
                        onChange={(e) => setVideoPromptInput(e.target.value)} 
                        className="glass-input w-full rounded-xl p-3 text-xs font-mono text-emerald-300 focus:outline-none resize-none h-24" 
                        placeholder='{"prompt": "...", "camera_movement": "pan_right"}'
                    />
                    <button onClick={handleGenerateVideo} disabled={isLoading} className="glass-btn w-full hover:bg-white/10 text-white py-3 rounded-xl font-bold flex items-center justify-center gap-2">
                        <Video className="w-4 h-4 text-purple-400" /> 生成影片 (Generate Video)
                    </button>
                </div>
            )}
        </div>
      </div>
      
       {showRawPromptModal && (
          <div className="fixed inset-0 bg-black/80 backdrop-blur-md z-50 flex items-center justify-center p-4">
              <div className="glass-card rounded-2xl w-full max-w-2xl flex flex-col max-h-[90vh]">
                  <div className="p-4 border-b border-white/5 flex justify-between items-center">
                      <h3 className="font-bold text-white">指令預覽 (Prompt Preview)</h3>
                      <button onClick={() => setShowRawPromptModal(false)}><X className="w-5 h-5 text-zinc-500" /></button>
                  </div>
                  <div className="p-6 flex-1 overflow-y-auto">
                      <pre className="text-xs text-emerald-400 font-mono whitespace-pre-wrap">{rawPrompt}</pre>
                  </div>
                  <div className="p-4 border-t border-white/5 text-right">
                      <button onClick={() => setShowRawPromptModal(false)} className="glass-btn px-6 py-2 rounded-lg text-white font-bold">關閉</button>
                  </div>
              </div>
          </div>
      )}
    </div>
  );
};

export default SceneEditor;
