import { useEffect, useState, 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 { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';
import {
  Film,
  FolderOpen,
  Settings,
  Sparkles,
  Download,
  FolderSearch,
  FileInput,
  Save,
} from 'lucide-react';

const IS_ELECTRON = !!window.electronAPI;

type Panel = 'ai' | 'settings' | 'export' | null;

export default function App() {
  const {
    videoPath,
    words,
    isTranscribing,
    transcriptionProgress,
    transcriptionStatus,
    loadVideo,
    setBackendUrl,
    setTranscription,
    setTranscribing,
    backendUrl,
  } = useEditorStore();

  const [activePanel, setActivePanel] = useState<Panel>(null);
  const [manualPath, setManualPath] = useState('');
  const [whisperModel, setWhisperModel] = useState('base');
  const fileInputRef = useRef<HTMLInputElement>(null);

  useKeyboardShortcuts();

  useEffect(() => {
    if (IS_ELECTRON) {
      window.electronAPI!.getBackendUrl().then(setBackendUrl);
    }
    // In Tauri on Linux/WebKit2GTK the ipc:// custom protocol is blocked by
    // WebKit internals; postMessage fallback works but logs noisy warnings.
    // The backend URL is fixed at 127.0.0.1:8000 so we rely on the store default.
  }, [setBackendUrl]);

  const handleLoadProject = async () => {
    if (!IS_ELECTRON) return;
    try {
      const projectPath = await window.electronAPI!.openProject();
      if (!projectPath) return;
      const content = await window.electronAPI!.readFile(projectPath);
      const data = JSON.parse(content);
      useEditorStore.getState().loadProject(data);
    } catch (err) {
      console.error('Failed to load project:', err);
      alert(`Failed to load project: ${err}`);
    }
  };

  const handleSaveProject = async () => {
    if (!IS_ELECTRON) return;
    try {
      const savePath = await window.electronAPI!.saveProject();
      if (!savePath) return;
      const data = useEditorStore.getState().saveProject();
      const path = savePath.endsWith('.aive') ? savePath : `${savePath}.aive`;
      await window.electronAPI!.writeFile(path, JSON.stringify(data, null, 2));
    } catch (err) {
      console.error('Failed to save project:', err);
      alert(`Failed to save project: ${err}`);
    }
  };

  const handleOpenFile = async () => {
    if (IS_ELECTRON) {
      const path = await window.electronAPI!.openFile();
      if (path) {
        loadVideo(path);
        await transcribeVideo(path);
      }
    } else {
      // Browser: use the manual path input
      const path = manualPath.trim();
      if (path) {
        loadVideo(path);
        await transcribeVideo(path);
      }
    }
  };

  const handleManualSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const path = manualPath.trim();
    if (!path) return;
    loadVideo(path);
    await transcribeVideo(path);
  };

  const transcribeVideo = async (path: string) => {
    setTranscribing(true, 0, 'Checking model...');
    try {
      if (!window.electronAPI?.transcribe) {
        throw new Error('Transcription not available');
      }
      // 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);
    } catch (err) {
      console.error('Transcription error:', err);
      alert(`Transcription failed. Check the console for details.\n\n${err}`);
    } finally {
      setTranscribing(false);
    }
  };

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

  if (!videoPath) {
    return (
      <div className="h-screen flex flex-col items-center justify-center gap-8 bg-editor-bg 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-white 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>

        {IS_ELECTRON ? (
          <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>
        ) : (
          /* Browser: manual path input */
          <div className="w-full max-w-lg space-y-3">
            <div className="flex items-center gap-2 px-3 py-1.5 bg-editor-warning/10 border border-editor-warning/30 rounded-lg">
              <span className="text-editor-warning text-xs">
                Running in browser — paste the full path to your video file below.
              </span>
            </div>
            <form onSubmit={handleManualSubmit} className="flex gap-2">
              <div className="flex-1 relative">
                <FolderSearch className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-editor-text-muted pointer-events-none" />
                <input
                  ref={fileInputRef}
                  type="text"
                  value={manualPath}
                  onChange={(e) => setManualPath(e.target.value)}
                  placeholder="C:\Videos\my-video.mp4"
                  className="w-full pl-9 pr-3 py-2.5 bg-editor-surface border border-editor-border rounded-lg text-sm text-editor-text placeholder:text-editor-text-muted/40 focus:outline-none focus:border-editor-accent"
                  autoFocus
                />
              </div>
              <button
                type="submit"
                disabled={!manualPath.trim()}
                className="flex items-center gap-2 px-5 py-2.5 bg-editor-accent hover:bg-editor-accent-hover disabled:opacity-40 rounded-lg text-sm text-white font-medium transition-colors whitespace-nowrap"
              >
                <Film className="w-4 h-4" />
                Load &amp; Transcribe
              </button>
            </form>
            <p className="text-[11px] text-editor-text-muted text-center">
              Supported: MP4, AVI, MOV, MKV, WebM, M4A
            </p>
          </div>
        )}
      </div>
    );
  }

  return (
    <div className="h-screen flex flex-col bg-editor-bg overflow-hidden">
      {/* Top bar */}
      <header className="h-12 flex items-center justify-between px-4 border-b border-editor-border shrink-0">
        <div className="flex items-center gap-3">
          <Film className="w-5 h-5 text-editor-accent" />
          <span className="text-sm font-medium truncate max-w-[300px]">
            {videoPath.split(/[\\/]/).pop()}
          </span>
        </div>
        <div className="flex items-center gap-1">
          <ToolbarButton
            icon={<FolderOpen className="w-4 h-4" />}
            label="Open"
            onClick={IS_ELECTRON ? handleOpenFile : () => useEditorStore.getState().reset()}
          />
          {IS_ELECTRON && (
            <ToolbarButton
              icon={<Save className="w-4 h-4" />}
              label="Save"
              onClick={handleSaveProject}
              disabled={words.length === 0}
            />
          )}
          {IS_ELECTRON && (
            <ToolbarButton
              icon={<FileInput className="w-4 h-4" />}
              label="Load"
              onClick={handleLoadProject}
            />
          )}
          <ToolbarButton
            icon={<Sparkles className="w-4 h-4" />}
            label="AI"
            active={activePanel === 'ai'}
            onClick={() => togglePanel('ai')}
            disabled={words.length === 0}
          />
          <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="flex-1 flex overflow-hidden">
        {/* Left: video + transcript */}
        <div className="flex-1 flex flex-col min-w-0">
          <div className="flex-1 flex min-h-0">
            {/* Video player */}
            <div className="w-1/2 p-3 flex items-center justify-center bg-black/20">
              <VideoPlayer />
            </div>

            {/* Transcript */}
            <div className="w-1/2 border-l border-editor-border flex flex-col min-h-0">
              {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 />
              ) : (
                <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 />
          </div>
        </div>

        {/* Right panel (AI / Export / Settings) */}
        {activePanel && (
          <div className="w-80 border-l border-editor-border overflow-y-auto shrink-0">
            {activePanel === 'ai' && <AIPanel />}
            {activePanel === 'export' && <ExportDialog />}
            {activePanel === 'settings' && <SettingsPanel />}
          </div>
        )}
      </div>
      {import.meta.env.DEV && <DevPanel />}
    </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>
  );
}
