import { useEffect, useState, useMemo, useCallback, useRef } from 'react';
import { useEditorStore } from './store/editorStore';
import VideoPlayer from './components/VideoPlayer';
import TranscriptEditor from './components/TranscriptEditor';
import WaveformTimeline from './components/WaveformTimeline';
import AIPanel from './components/AIPanel';
import ExportDialog from './components/ExportDialog';
import SettingsPanel from './components/SettingsPanel';
import DevPanel from './components/DevPanel';
import MarkersPanel from './components/MarkersPanel';
import SilenceTrimmerPanel from './components/SilenceTrimmerPanel';
import ZoneEditor from './components/ZoneEditor';
import BackgroundMusicPanel from './components/BackgroundMusicPanel';
import AppendClipPanel from './components/AppendClipPanel';
import LicenseDialog from './components/LicenseDialog';
import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';
import { useLicenseStore } from './store/licenseStore';
import {
  Film,
  FolderOpen,
  Settings,
  Sparkles,
  Download,
  FileInput,
  Save,
  Scissors,
  VolumeX,
  SlidersHorizontal,
  Gauge,
  FilePlus2,
  RefreshCw,
  Grid3x3,
  MapPin,
  Music,
  ListVideo,
  Clock,
  AlertTriangle,
} from 'lucide-react';

const LAST_MEDIA_PATH_KEY = 'talkedit:lastMediaPath';

type Panel = 'ai' | 'settings' | 'export' | 'silence' | 'zones' | 'markers' | 'music' | 'append' | null;

export default function App() {
  const {
    projectFilePath,
    videoPath,
    exportedAudioPath,
    words,
    segments,
    cutRanges,
    muteRanges,
    gainRanges,
    speedRanges,
    globalGainDb,
    silenceTrimGroups,
    transcriptionModel,
    language,
    isTranscribing,
    transcriptionStatus,
    markInTime,
    markOutTime,
    loadVideo,
    setProjectFilePath,
    setBackendUrl,
    clearMarkRange,
    setTranscription,
    setTranscriptionModel,
    setTranscribing,
    selectedWordIndices,
    addCutRange,
    addMuteRange,
    addGainRange,
    addSpeedRange,
  } = useEditorStore();

  const [activePanel, setActivePanel] = useState<Panel>(null);
  const [projectName, setProjectName] = useState<string | null>(null);
  const [splitRatio, setSplitRatio] = useState(() => {
    try { return Number(localStorage.getItem('talkedit:splitRatio')) || 0.5; } catch { return 0.5; }
  });
  const splitRef = useRef<HTMLDivElement>(null);
  const isDraggingSplit = useRef(false);

  const startSplitDrag = useCallback((e: React.MouseEvent) => {
    e.preventDefault();
    isDraggingSplit.current = true;
    const container = splitRef.current?.parentElement;
    if (!container) return;
    const rect = container.getBoundingClientRect();
    const onMove = (me: MouseEvent) => {
      if (!isDraggingSplit.current) return;
      const pct = (me.clientX - rect.left) / rect.width;
      const clamped = Math.max(0.15, Math.min(0.85, pct));
      setSplitRatio(clamped);
      localStorage.setItem('talkedit:splitRatio', String(clamped));
    };
    const onUp = () => { isDraggingSplit.current = false; window.removeEventListener('mousemove', onMove); window.removeEventListener('mouseup', onUp); };
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup', onUp);
  }, []);

  // Draggable right sidebar
  const [sidebarWidth, setSidebarWidth] = useState(() => {
    try { return Number(localStorage.getItem('talkedit:sidebarWidth')) || 320; } catch { return 320; }
  });
  const isDraggingSidebar = useRef(false);

  const startSidebarDrag = useCallback((e: React.MouseEvent) => {
    e.preventDefault();
    isDraggingSidebar.current = true;
    const container = document.querySelector('.main-content') as HTMLElement;
    if (!container) return;
    const rect = container.getBoundingClientRect();
    const onMove = (me: MouseEvent) => {
      if (!isDraggingSidebar.current) return;
      const w = rect.right - me.clientX;
      const clamped = Math.max(180, Math.min(600, w));
      setSidebarWidth(clamped);
      localStorage.setItem('talkedit:sidebarWidth', String(clamped));
    };
    const onUp = () => { isDraggingSidebar.current = false; window.removeEventListener('mousemove', onMove); window.removeEventListener('mouseup', onUp); };
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup', onUp);
  }, []);

  const [whisperModel, setWhisperModel] = useState('base');
  useEffect(() => { if (transcriptionModel) setWhisperModel(transcriptionModel); }, [transcriptionModel]);
  const [cutMode, setCutMode] = useState(false);
  const [muteMode, setMuteMode] = useState(false);
  const [gainMode, setGainMode] = useState(false);
  const [gainModeDb, setGainModeDb] = useState(3);
  const [speedMode, setSpeedMode] = useState(false);
  const [speedModeValue, setSpeedModeValue] = useState(1.25);
  const [showReprocessConfirm, setShowReprocessConfirm] = useState(false);
  const [showUnsavedPrompt, setShowUnsavedPrompt] = useState(false);
  const [pendingProceedAction, setPendingProceedAction] = useState<(() => Promise<void>) | null>(null);
  const [lastSavedSignature, setLastSavedSignature] = useState<string | null>(null);
  const [showFileMenu, setShowFileMenu] = useState(false);
  const canEdit = useLicenseStore((s) => s.canEdit);
  const licenseStatus = useLicenseStore((s) => s.status);
  const setShowLicenseDialog = useLicenseStore((s) => s.setShowDialog);

  const projectSignature = useMemo(() => {
    if (!videoPath) return null;
    return JSON.stringify({
      videoPath,
      exportedAudioPath,
      words,
      segments,
      cutRanges,
      muteRanges,
      gainRanges,
      speedRanges,
      globalGainDb,
      silenceTrimGroups,
      transcriptionModel,
      language,
    });
  }, [
    videoPath,
    exportedAudioPath,
    words,
    segments,
    cutRanges,
    muteRanges,
    gainRanges,
    speedRanges,
    globalGainDb,
    silenceTrimGroups,
    transcriptionModel,
    language,
  ]);

  const hasUnsavedChanges = Boolean(projectSignature) && projectSignature !== lastSavedSignature;

  const loadProjectFromData = (data: any) => {
    useEditorStore.getState().loadProject(data);
    const loadedSignature = JSON.stringify({
      videoPath: data.videoPath,
      exportedAudioPath: data.exportedAudioPath ?? null,
      words: data.words || [],
      segments: data.segments || [],
      cutRanges: [...(data.cutRanges || []), ...(data.deletedRanges || []).map((r: any) => ({ id: r.id, start: r.start, end: r.end }))],
      muteRanges: data.muteRanges || [],
      gainRanges: data.gainRanges || [],
      speedRanges: data.speedRanges || [],
      globalGainDb: typeof data.globalGainDb === 'number' ? data.globalGainDb : 0,
      silenceTrimGroups: data.silenceTrimGroups || [],
      transcriptionModel: data.transcriptionModel ?? null,
      language: data.language || '',
    });
    setLastSavedSignature(loadedSignature);
  };

  const runGuarded = async (action: () => Promise<void>) => {
    if (!hasUnsavedChanges) {
      await action();
      return;
    }
    setPendingProceedAction(() => action);
    setShowUnsavedPrompt(true);
  };

  useKeyboardShortcuts();

  useEffect(() => {
    useLicenseStore.getState().checkStatus();
  }, []);

  // Handle Escape key to exit timeline zone modes and close menus
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        setCutMode(false);
        setMuteMode(false);
        setGainMode(false);
        setSpeedMode(false);
        setShowFileMenu(false);
      }
    };
    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, []);

  useEffect(() => {
    window.electronAPI!.getBackendUrl().then(setBackendUrl);
  }, [setBackendUrl]);

  useEffect(() => {
    if (videoPath) return;
    const savedPath = sessionStorage.getItem(LAST_MEDIA_PATH_KEY);
    if (savedPath) {
      loadVideo(savedPath);
    }
  }, [videoPath, loadVideo]);

  useEffect(() => {
    if (videoPath) {
      sessionStorage.setItem(LAST_MEDIA_PATH_KEY, videoPath);
      return;
    }
    sessionStorage.removeItem(LAST_MEDIA_PATH_KEY);
  }, [videoPath]);

  const handleLoadProject = async () => {
    await runGuarded(async () => {
      try {
        const projectPath = await window.electronAPI!.openProject();
        if (!projectPath) return;
        const content = await window.electronAPI!.readFile(projectPath);
        const data = JSON.parse(content);
        setProjectFilePath(projectPath);
        loadProjectFromData(data);
        setProjectName(projectPath.split(/[/\\]/).pop()?.replace(/\.aive$/i, '') ?? null);
      } catch (err) {
        console.error('Failed to load project:', err);
        alert(`Failed to load project: ${err}`);
      }
    });
  };

  const writeProjectToPath = async (path: string): Promise<boolean> => {
    try {
      const data = useEditorStore.getState().saveProject();
      const resolvedPath = path.endsWith('.aive') ? path : `${path}.aive`;
      await window.electronAPI!.writeFile(resolvedPath, JSON.stringify(data, null, 2));
      setProjectFilePath(resolvedPath);
      setProjectName(resolvedPath.split(/[/\\]/).pop()?.replace(/\.aive$/i, '') ?? null);
      if (projectSignature) {
        setLastSavedSignature(projectSignature);
      }
      return true;
    } catch (err) {
      console.error('Failed to save project:', err);
      alert(`Failed to save project: ${err}`);
      return false;
    }
  };

  const handleSaveProjectAs = async (): Promise<boolean> => {
    const savePath = await window.electronAPI!.saveProject();
    if (!savePath) return false;
    return writeProjectToPath(savePath);
  };

  const handleSaveProject = async (): Promise<boolean> => {
    if (!projectFilePath) {
      return handleSaveProjectAs();
    }
    return writeProjectToPath(projectFilePath);
  };

  const handleOpenFile = async () => {
    await runGuarded(async () => {
      const path = await window.electronAPI!.openFile();
      if (path) {
        setLastSavedSignature(null);
        setProjectFilePath(null);
        setProjectName(null);
        loadVideo(path);
        if (canEdit) {
          await transcribeVideo(path);
        }
      }
    });
  };

  const handleNewProject = () => {
    runGuarded(async () => {
      useEditorStore.getState().reset();
      setLastSavedSignature(null);
      setActivePanel(null);
      setProjectFilePath(null);
      setProjectName(null);
      setCutMode(false);
      setMuteMode(false);
      setGainMode(false);
      setSpeedMode(false);
    });
  };

  const transcribeVideo = async (path: string) => {
    setTranscribing(true, 0, 'Checking model...');
    try {
      // Step 1: ensure model is downloaded (may take a while on first run)
      const MODEL_SIZES: Record<string, string> = {
        'tiny':              '~75 MB',
        'tiny.en':           '~75 MB',
        'base':              '~140 MB',
        'base.en':           '~140 MB',
        'small':             '~460 MB',
        'small.en':          '~460 MB',
        'medium':            '~1.5 GB',
        'medium.en':         '~1.5 GB',
        'large':             '~2.9 GB',
        'large-v2':          '~2.9 GB',
        'large-v3':          '~2.9 GB',
        'large-v3-turbo':    '~1.6 GB',
        'distil-large-v3':   '~1.5 GB',
        'distil-medium.en':  '~750 MB',
        'distil-small.en':   '~190 MB',
      };
      const modelLabel = MODEL_SIZES[whisperModel] ?? 'unknown size';
      setTranscribing(true, 5, `Downloading ${whisperModel} model (${modelLabel})...`);
      await window.electronAPI.ensureModel(whisperModel);

      // Step 2: run transcription
      setTranscribing(true, 20, 'Transcribing audio...');
      const data = await window.electronAPI.transcribe(path, whisperModel);
      setTranscription(data);
      setTranscriptionModel(whisperModel);
    } catch (err) {
      console.error('Transcription error:', err);
      alert(`Transcription failed. Check the console for details.\n\n${err}`);
    } finally {
      setTranscribing(false);
    }
  };

  const handleReprocessProject = async () => {
    if (!videoPath) return;

    await runGuarded(async () => {
      setShowReprocessConfirm(true);
    });
  };

  const confirmReprocessProject = async () => {
    if (!videoPath) return;
    setShowReprocessConfirm(false);
    await transcribeVideo(videoPath);
  };

  const handleUnsavedSaveAndContinue = async () => {
    const action = pendingProceedAction;
    if (!action) {
      setShowUnsavedPrompt(false);
      return;
    }
    const didSave = await handleSaveProject();
    if (!didSave) return;
    setShowUnsavedPrompt(false);
    setPendingProceedAction(null);
    await action();
  };

  const handleUnsavedDiscardAndContinue = async () => {
    const action = pendingProceedAction;
    setShowUnsavedPrompt(false);
    setPendingProceedAction(null);
    if (action) {
      await action();
    }
  };

  const handleUnsavedCancel = () => {
    setShowUnsavedPrompt(false);
    setPendingProceedAction(null);
  };

  const togglePanel = (panel: Panel) => {
    setActivePanel((prev) => (prev === panel ? null : panel));
  };

  const handleCut = () => {
    if (markInTime !== null && markOutTime !== null) {
      const startTime = Math.min(markInTime, markOutTime);
      const endTime = Math.max(markInTime, markOutTime);
      if (endTime - startTime >= 0.01) {
        addCutRange(startTime, endTime);
        setActivePanel('zones');
      }
      clearMarkRange();
      return;
    }

    if (selectedWordIndices.length > 0) {
      // If words are selected, apply cut immediately
      const sorted = [...selectedWordIndices].sort((a, b) => a - b);
      const startTime = words[sorted[0]].start;
      const endTime = words[sorted[sorted.length - 1]].end;
      addCutRange(startTime, endTime);
    } else {
      // Toggle cut mode
      setCutMode(!cutMode);
      setMuteMode(false); // Exit mute mode
      setGainMode(false); // Exit gain mode
      setSpeedMode(false); // Exit speed mode
    }
  };

  const handleMute = () => {
    if (markInTime !== null && markOutTime !== null) {
      const startTime = Math.min(markInTime, markOutTime);
      const endTime = Math.max(markInTime, markOutTime);
      if (endTime - startTime >= 0.01) {
        addMuteRange(startTime, endTime);
        setActivePanel('zones');
      }
      clearMarkRange();
      return;
    }

    if (selectedWordIndices.length > 0) {
      // If words are selected, apply mute immediately
      const sorted = [...selectedWordIndices].sort((a, b) => a - b);
      const startTime = words[sorted[0]].start;
      const endTime = words[sorted[sorted.length - 1]].end;
      addMuteRange(startTime, endTime);
    } else {
      // Toggle mute mode
      setMuteMode(!muteMode);
      setCutMode(false); // Exit cut mode
      setGainMode(false); // Exit gain mode
      setSpeedMode(false); // Exit speed mode
    }
  };

  const handleGain = () => {
    if (markInTime !== null && markOutTime !== null) {
      const startTime = Math.min(markInTime, markOutTime);
      const endTime = Math.max(markInTime, markOutTime);
      if (endTime - startTime >= 0.01) {
        addGainRange(startTime, endTime, gainModeDb);
        setActivePanel('zones');
      }
      clearMarkRange();
      return;
    }

    if (selectedWordIndices.length > 0) {
      const sorted = [...selectedWordIndices].sort((a, b) => a - b);
      const startTime = words[sorted[0]].start;
      const endTime = words[sorted[sorted.length - 1]].end;
      addGainRange(startTime, endTime, gainModeDb);
    } else {
      setGainMode(!gainMode);
      setCutMode(false);
      setMuteMode(false);
      setSpeedMode(false);
    }
  };

  const handleSpeed = () => {
    if (markInTime !== null && markOutTime !== null) {
      const startTime = Math.min(markInTime, markOutTime);
      const endTime = Math.max(markInTime, markOutTime);
      if (endTime - startTime >= 0.01) {
        addSpeedRange(startTime, endTime, speedModeValue);
        setActivePanel('zones');
      }
      clearMarkRange();
      return;
    }

    if (selectedWordIndices.length > 0) {
      const sorted = [...selectedWordIndices].sort((a, b) => a - b);
      const startTime = words[sorted[0]].start;
      const endTime = words[sorted[sorted.length - 1]].end;
      addSpeedRange(startTime, endTime, speedModeValue);
    } else {
      setSpeedMode(!speedMode);
      setCutMode(false);
      setMuteMode(false);
      setGainMode(false);
    }
  };

  if (!videoPath) {
    return (
      <div className="h-screen flex flex-col bg-editor-bg">
        <div className="flex-1 flex flex-col items-center justify-center gap-8 px-6">
          <div className="flex flex-col items-center gap-3">
            <Film className="w-14 h-14 text-editor-accent opacity-80" />
            <h1 className="text-3xl font-semibold tracking-tight">TalkEdit</h1>
            <p className="text-editor-text-muted text-sm max-w-sm text-center">
              Offline AI-powered video editor.
            </p>
          </div>

          {/* Whisper model selector */}
          <div className="flex items-center gap-3">
            <label className="text-xs text-editor-text-muted whitespace-nowrap">Model:</label>
            <select
              value={whisperModel}
              onChange={(e) => setWhisperModel(e.target.value)}
              className="px-3 py-1.5 bg-editor-surface border border-editor-border rounded-lg text-xs text-black focus:outline-none focus:border-editor-accent"
            >
              <optgroup label="Multilingual (any language)">
                <option value="tiny">tiny — ~75 MB · fastest, low accuracy</option>
                <option value="base">base — ~140 MB · fast, decent accuracy</option>
                <option value="small">small — ~460 MB · good balance</option>
                <option value="medium">medium — ~1.5 GB · better accuracy</option>
                <option value="large-v2">large-v2 — ~2.9 GB · high accuracy</option>
                <option value="large-v3">large-v3 — ~2.9 GB · best overall ★</option>
                <option value="large-v3-turbo">large-v3-turbo — ~1.6 GB · fast + accurate ★</option>
                <option value="distil-large-v3">distil-large-v3 — ~1.5 GB · fast, near large-v3 quality</option>
              </optgroup>
              <optgroup label="English-only (faster &amp; more accurate for English)">
                <option value="tiny.en">tiny.en — ~75 MB · fastest English</option>
                <option value="base.en">base.en — ~140 MB · fast English</option>
                <option value="small.en">small.en — ~460 MB · good English</option>
                <option value="medium.en">medium.en — ~1.5 GB · great English</option>
                <option value="distil-small.en">distil-small.en — ~190 MB · fast English ★</option>
                <option value="distil-medium.en">distil-medium.en — ~750 MB · best fast English ★</option>
              </optgroup>
            </select>
          </div>
          <p className="text-[11px] text-editor-text-muted text-center max-w-sm">
            For noisy/YouTube videos use <span className="text-white">large-v3</span> or <span className="text-white">large-v3-turbo</span>.
            English-only models are ~10% faster and more accurate for English content.
          </p>

          <div className="flex flex-col items-center gap-3">
            <button
              onClick={handleOpenFile}
              className="flex items-center gap-2 px-6 py-3 bg-editor-accent hover:bg-editor-accent-hover rounded-lg text-white font-medium transition-colors"
            >
              <FolderOpen className="w-5 h-5" />
              Open Video File
            </button>
            <button
              onClick={handleLoadProject}
              className="flex items-center gap-2 px-4 py-2 text-sm text-editor-text-muted hover:text-editor-text hover:bg-editor-surface rounded-lg transition-colors"
            >
              <FileInput className="w-4 h-4" />
              Load Project (.aive)
            </button>
          </div>
        </div>

        {licenseStatus?.tag === 'Trial' && (
          <div className="h-9 flex items-center justify-center gap-2 px-4 bg-editor-accent/10 border-t border-editor-accent/20 shrink-0">
            <Clock className="w-3.5 h-3.5 text-editor-accent shrink-0" />
            <span className="text-xs text-editor-accent">
              Free trial: {licenseStatus.days_remaining} day{licenseStatus.days_remaining !== 1 ? 's' : ''} remaining
            </span>
            <button
              onClick={() => setShowLicenseDialog(true)}
              className="text-xs text-editor-accent underline font-medium hover:text-editor-accent-hover ml-2"
            >
              Activate license
            </button>
          </div>
        )}

        {licenseStatus?.tag === 'Expired' && (
          <div className="h-9 flex items-center justify-center gap-2 px-4 bg-red-500/15 border-t border-red-500/30 shrink-0">
            <AlertTriangle className="w-3.5 h-3.5 text-red-400 shrink-0" />
            <span className="text-xs text-red-300">Trial expired</span>
            <button
              onClick={() => setShowLicenseDialog(true)}
              className="text-xs text-red-300 underline font-medium hover:text-red-200 ml-2"
            >
              Activate license
            </button>
          </div>
        )}
      </div>
    );
  }

  return (
    <div className="h-screen flex flex-col bg-editor-bg overflow-hidden">
      {/* Top bar */}
      <header className="h-12 flex items-center px-4 border-b border-editor-border shrink-0">
        <div className="flex items-center gap-0.5">
          <div className="relative">
            <ToolbarButton
              icon={<FolderOpen className="w-4 h-4" />}
              label="File"
              onClick={() => setShowFileMenu((p) => !p)}
              active={showFileMenu}
            />
            {showFileMenu && (
              <>
                <div className="fixed inset-0 z-40" onClick={() => setShowFileMenu(false)} />
                <div className="absolute left-0 top-full mt-1 z-50 w-44 rounded-lg border border-editor-border bg-editor-surface shadow-xl py-1">
                  <DropdownItem icon={<FilePlus2 className="w-4 h-4" />} label="New Project" onClick={() => { setShowFileMenu(false); handleNewProject(); }} />
                  <DropdownItem icon={<FolderOpen className="w-4 h-4" />} label="Open File" onClick={() => { setShowFileMenu(false); handleOpenFile(); }} />
                  <DropdownItem icon={<FileInput className="w-4 h-4" />} label="Load Project" onClick={() => { setShowFileMenu(false); handleLoadProject(); }} />
                  <div className="border-t border-editor-border my-1" />
                  <DropdownItem icon={<Save className="w-4 h-4" />} label="Save" onClick={() => { setShowFileMenu(false); handleSaveProject(); }} disabled={words.length === 0} />
                  <DropdownItem icon={<Save className="w-4 h-4" />} label="Save As" onClick={() => { setShowFileMenu(false); handleSaveProjectAs(); }} disabled={words.length === 0} />
                </div>
              </>
            )}
          </div>
          <ToolbarButton
            icon={<Scissors className="w-4 h-4" />}
            label="Cut"
            onClick={handleCut}
            active={cutMode}
            disabled={!canEdit}
          />
          <ToolbarButton
            icon={<VolumeX className="w-4 h-4" />}
            label="Mute"
            onClick={handleMute}
            active={muteMode}
            disabled={!canEdit}
          />
          <div className="flex items-center gap-1">
            <ToolbarButton
              icon={<SlidersHorizontal className="w-4 h-4" />}
              label="Gain Zone"
              onClick={handleGain}
              active={gainMode}
              disabled={!canEdit}
            />
            <input
              type="number"
              min={-24}
              max={24}
              step={0.5}
              value={gainModeDb}
              onChange={(e) => setGainModeDb(Math.max(-24, Math.min(24, Number(e.target.value) || 0)))}
              className="w-16 px-1.5 py-1 text-xs bg-editor-surface border border-editor-border rounded text-editor-text focus:outline-none focus:border-editor-accent"
              title="Gain dB for new gain zones"
              disabled={!canEdit}
            />
          </div>
          <div className="flex items-center gap-1">
            <ToolbarButton
              icon={<Gauge className="w-4 h-4" />}
              label="Speed Zone"
              onClick={handleSpeed}
              active={speedMode}
              disabled={!canEdit}
            />
            <input
              type="number"
              min={0.25}
              max={4}
              step={0.05}
              value={speedModeValue}
              onChange={(e) => setSpeedModeValue(Math.max(0.25, Math.min(4, Number(e.target.value) || 1)))}
              className="w-16 px-1.5 py-1 text-xs bg-editor-surface border border-editor-border rounded text-editor-text focus:outline-none focus:border-editor-accent"
              title="Playback rate for new speed zones"
              disabled={!canEdit}
            />
          </div>
          <ToolbarButton
            icon={<Grid3x3 className="w-4 h-4" />}
            label="Zones"
            active={activePanel === 'zones'}
            onClick={() => togglePanel('zones')}
            disabled={!videoPath || !canEdit}
          />
          <ToolbarButton
            icon={<span className="text-[10px] font-semibold">PA</span>}
            label="Pause Trim"
            active={activePanel === 'silence'}
            onClick={() => togglePanel('silence')}
            disabled={!videoPath || !canEdit}
          />
          <ToolbarButton
            icon={<MapPin className="w-4 h-4" />}
            label="Markers"
            active={activePanel === 'markers'}
            onClick={() => togglePanel('markers')}
            disabled={!videoPath || !canEdit}
          />
          <ToolbarButton
            icon={<Music className="w-4 h-4" />}
            label="Music"
            active={activePanel === 'music'}
            onClick={() => togglePanel('music')}
            disabled={!videoPath || !canEdit}
          />
          <ToolbarButton
            icon={<ListVideo className="w-4 h-4" />}
            label="Append"
            active={activePanel === 'append'}
            onClick={() => togglePanel('append')}
            disabled={!videoPath || !canEdit}
          />
          <div className="flex items-center gap-1.5 px-2 py-1 rounded-md bg-editor-surface border border-editor-border">
            <select
              value={whisperModel}
              onChange={(e) => setWhisperModel(e.target.value)}
              className="bg-editor-surface text-xs text-editor-text focus:outline-none [color-scheme:dark]"
              title="Transcription model"
            >
              <optgroup label="Multilingual">
                <option value="tiny">tiny</option>
                <option value="base">base</option>
                <option value="small">small</option>
                <option value="medium">medium</option>
                <option value="large-v2">large-v2</option>
                <option value="large-v3">large-v3</option>
                <option value="large-v3-turbo">large-v3-turbo</option>
                <option value="distil-large-v3">distil-large-v3</option>
              </optgroup>
              <optgroup label="English">
                <option value="tiny.en">tiny.en</option>
                <option value="base.en">base.en</option>
                <option value="small.en">small.en</option>
                <option value="medium.en">medium.en</option>
                <option value="distil-small.en">distil-small.en</option>
                <option value="distil-medium.en">distil-medium.en</option>
              </optgroup>
            </select>
            <button
              onClick={handleReprocessProject}
              disabled={isTranscribing || !videoPath || !canEdit}
              title="Reprocess transcript with selected model"
              className="flex items-center gap-1 px-2 py-1 rounded text-xs text-editor-text hover:bg-editor-bg disabled:opacity-40 disabled:cursor-not-allowed"
            >
              <RefreshCw className={`w-3 h-3 ${isTranscribing ? 'animate-spin' : ''}`} />
              Reprocess
            </button>
          </div>
          <ToolbarButton
            icon={<Sparkles className="w-4 h-4" />}
            label="AI"
            active={activePanel === 'ai'}
            onClick={() => togglePanel('ai')}
            disabled={words.length === 0 || !canEdit}
          />
          <ToolbarButton
            icon={<Download className="w-4 h-4" />}
            label="Export"
            active={activePanel === 'export'}
            onClick={() => togglePanel('export')}
            disabled={words.length === 0}
          />
          <ToolbarButton
            icon={<Settings className="w-4 h-4" />}
            label="Settings"
            active={activePanel === 'settings'}
            onClick={() => togglePanel('settings')}
          />
        </div>
      </header>

      {/* Main content */}
      <div className="main-content flex-1 flex overflow-hidden">
        {/* Left: video + transcript */}
        <div className="flex-1 flex flex-col min-w-0">
          <div ref={splitRef} className="flex-1 flex min-h-0" style={{ position: 'relative' }}>
            {/* Video player */}
            <div className="p-3 flex items-center justify-center bg-black/20 overflow-hidden" style={{ width: `${splitRatio * 100}%`, minWidth: 0 }}>
              <VideoPlayer />
            </div>

            {/* Draggable divider */}
            <div
              className="w-1 shrink-0 bg-editor-border cursor-col-resize hover:bg-editor-accent/50 active:bg-editor-accent transition-colors relative z-10"
              style={{ cursor: isDraggingSplit.current ? 'col-resize' : 'col-resize' }}
              onMouseDown={startSplitDrag}
            />

            {/* Transcript */}
            <div className="border-l border-editor-border flex flex-col min-h-0" style={{ width: `${(1 - splitRatio) * 100}%`, minWidth: 0 }}>
              {videoPath && (
                <div className="flex items-center gap-2 px-3 py-1.5 border-b border-editor-border shrink-0 bg-editor-surface/50">
                  {projectName && (
                    <span className="text-xs font-semibold text-editor-accent shrink-0">{projectName}</span>
                  )}
                  <span className="text-xs font-medium truncate text-editor-text">{videoPath.split(/[/\\]/).pop()}</span>
                  <span className="text-xs text-editor-text-muted ml-auto shrink-0">
                                      {words.length} words &middot; {cutRanges.length} cuts &middot; {muteRanges.length} mutes &middot; {gainRanges.length} gains &middot; {speedRanges.length} speeds
                  </span>
                  {transcriptionModel && (
                    <span className="px-1.5 py-0.5 rounded border border-editor-border bg-editor-surface text-[10px] uppercase tracking-wide text-editor-text-muted shrink-0">
                      {transcriptionModel}
                    </span>
                  )}
                </div>
              )}
              {isTranscribing ? (
                <div className="flex-1 flex flex-col items-center justify-center gap-5">
                  {/* Animated waveform */}
                  <div className="flex items-end gap-[3px] h-10">
                    {[35, 60, 45, 80, 55, 70, 40, 65, 50, 75, 40, 58].map((h, i) => (
                      <div
                        key={i}
                        className="w-[5px] rounded-full bg-editor-accent wave-bar"
                        style={{
                          height: `${h}%`,
                          animationDelay: `${i * 75}ms`,
                        }}
                      />
                    ))}
                  </div>
                  <div className="text-center space-y-1">
                    <p className="text-sm font-medium text-editor-text">Processing audio</p>
                    <p className="text-xs text-editor-text-muted">{transcriptionStatus || 'Please wait...'}</p>
                  </div>
                </div>
              ) : words.length > 0 ? (
                <TranscriptEditor
                  cutMode={cutMode}
                  muteMode={muteMode}
                  gainMode={gainMode}
                  gainModeDb={gainModeDb}
                  speedMode={speedMode}
                  speedModeValue={speedModeValue}
                />
              ) : (
                <div className="flex-1 flex items-center justify-center text-editor-text-muted text-sm">
                  No transcript yet
                </div>
              )}
            </div>
          </div>

          {/* Waveform timeline */}
          <div className="h-32 border-t border-editor-border shrink-0">
            <WaveformTimeline
              cutMode={cutMode}
              muteMode={muteMode}
              gainMode={gainMode}
              gainModeDb={gainModeDb}
              speedMode={speedMode}
              speedModeValue={speedModeValue}
            />
          </div>
        </div>

        {/* Right panel (AI / Export / Settings) */}
        {activePanel && (
          <div className="flex shrink-0">
            {/* Draggable sidebar divider */}
            <div
              className="w-1 shrink-0 bg-editor-border cursor-col-resize hover:bg-editor-accent/50 active:bg-editor-accent transition-colors relative z-10"
              onMouseDown={startSidebarDrag}
            />
            <div className="overflow-y-auto" style={{ width: sidebarWidth }}>
            {activePanel === 'zones' && (
              <ZoneEditor />
            )}
            {activePanel === 'silence' && <SilenceTrimmerPanel />}
            {activePanel === 'markers' && <MarkersPanel />}
            {activePanel === 'music' && <BackgroundMusicPanel />}
            {activePanel === 'append' && <AppendClipPanel />}
            {activePanel === 'ai' && <AIPanel />}
            {activePanel === 'export' && <ExportDialog />}
            {activePanel === 'settings' && <SettingsPanel />}
          </div>
        </div>
      )}
      </div>
      {import.meta.env.DEV && <DevPanel />}

      <LicenseDialog />

      {showReprocessConfirm && (
        <div
          className="fixed inset-0 z-[60] flex items-center justify-center bg-black/60 px-4"
          onClick={() => setShowReprocessConfirm(false)}
        >
          <div
            className="w-full max-w-md rounded-xl border border-editor-border bg-editor-bg p-4 space-y-3"
            onClick={(e) => e.stopPropagation()}
          >
            <h3 className="text-sm font-semibold">Reprocess transcript?</h3>
            <p className="text-xs text-editor-text-muted leading-relaxed">
              This will reprocess the current file with <span className="text-editor-text font-medium">{whisperModel}</span> and replace the current transcript words and timings.
            </p>
            <div className="flex items-center justify-end gap-2 pt-1">
              <button
                onClick={() => setShowReprocessConfirm(false)}
                className="px-3 py-1.5 rounded-md text-xs text-editor-text-muted hover:text-editor-text hover:bg-editor-surface"
              >
                Cancel
              </button>
              <button
                onClick={confirmReprocessProject}
                className="px-3 py-1.5 rounded-md text-xs bg-editor-accent hover:bg-editor-accent-hover text-white"
              >
                Reprocess Now
              </button>
            </div>
          </div>
        </div>
      )}

      {showUnsavedPrompt && (
        <div
          className="fixed inset-0 z-[70] flex items-center justify-center bg-black/60 px-4"
          onClick={handleUnsavedCancel}
        >
          <div
            className="w-full max-w-md rounded-xl border border-editor-border bg-editor-bg p-4 space-y-3"
            onClick={(e) => e.stopPropagation()}
          >
            <h3 className="text-sm font-semibold">Save changes first?</h3>
            <p className="text-xs text-editor-text-muted leading-relaxed">
              There are unsaved changes in this project. Save before continuing?
            </p>
            <div className="flex items-center justify-end gap-2 pt-1">
              <button
                onClick={handleUnsavedCancel}
                className="px-3 py-1.5 rounded-md text-xs text-editor-text-muted hover:text-editor-text hover:bg-editor-surface"
              >
                Cancel
              </button>
              <button
                onClick={handleUnsavedDiscardAndContinue}
                className="px-3 py-1.5 rounded-md text-xs text-editor-text hover:bg-editor-surface"
              >
                Don't Save
              </button>
              <button
                onClick={handleUnsavedSaveAndContinue}
                className="px-3 py-1.5 rounded-md text-xs bg-editor-accent hover:bg-editor-accent-hover text-white"
              >
                Save
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

function ToolbarButton({
  icon,
  label,
  active,
  onClick,
  disabled,
}: {
  icon: React.ReactNode;
  label: string;
  active?: boolean;
  onClick: () => void;
  disabled?: boolean;
}) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      title={label}
      className={`flex items-center gap-1.5 px-3 py-1.5 rounded-md text-xs font-medium transition-colors ${
        active
          ? 'bg-editor-accent text-white'
          : 'text-editor-text-muted hover:text-editor-text hover:bg-editor-surface'
      } ${disabled ? 'opacity-40 cursor-not-allowed' : ''}`}
    >
      {icon}
      {label}
    </button>
  );
}

function DropdownItem({
  icon,
  label,
  onClick,
  disabled,
}: {
  icon: React.ReactNode;
  label: string;
  onClick: () => void;
  disabled?: boolean;
}) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      className={`w-full flex items-center gap-2 px-3 py-1.5 text-xs text-left transition-colors ${
        disabled
          ? 'opacity-40 cursor-not-allowed'
          : 'text-editor-text-muted hover:text-editor-text hover:bg-editor-bg'
      }`}
    >
      {icon}
      {label}
    </button>
  );
}
