import { useState, useEffect, useRef, Fragment } from 'react';
import { VTTParser, VTTValidator, type VTTCue } from '../../lib/vtt';
import type { GlossaryTerm } from '../../types/api';

const CPS_THRESHOLD = 20;

function computeCps(cue: VTTCue): number {
  const chars = cue.text.replace(/[\n\r]/g, ' ').trim().length;
  const duration = cue.endTime - cue.startTime;
  if (duration <= 0) return 0;
  return chars / duration;
}

type TextSegment = { text: string; glossaryMatch?: { preferred: string; notes?: string } };

function buildSegments(text: string, glossaryTerms: GlossaryTerm[], language: string): TextSegment[] {
  if (!glossaryTerms.length) return [{ text }];

  // Build a combined regex from all source terms
  const patterns = glossaryTerms
    .filter(t => t.translations[language])
    .map(t => ({ pattern: t.source_term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), term: t }));
  if (!patterns.length) return [{ text }];

  const regex = new RegExp(`(${patterns.map(p => p.pattern).join('|')})`, 'gi');
  const parts = text.split(regex);
  const segments: TextSegment[] = [];

  for (const part of parts) {
    if (!part) continue;
    const matchedTerm = patterns.find(p => new RegExp(`^${p.pattern}$`, 'i').test(part));
    if (matchedTerm) {
      segments.push({
        text: part,
        glossaryMatch: {
          preferred: matchedTerm.term.translations[language] || '',
          notes: undefined,
        },
      });
    } else {
      segments.push({ text: part });
    }
  }
  return segments;
}

// Pure function for validating a single cue's timing (no hooks dependency)
function validateCueTimingAtIndex(allCues: VTTCue[], index: number): string[] {
  const cueErrorList: string[] = [];
  const cue = allCues[index];

  // start < end
  if (cue.startTime >= cue.endTime) {
    cueErrorList.push('Start time must be before end time');
  }

  // No overlap with previous
  if (index > 0 && cue.startTime < allCues[index - 1].endTime) {
    cueErrorList.push('Overlaps with previous cue');
  }

  // No overlap with next
  if (index < allCues.length - 1 && cue.endTime > allCues[index + 1].startTime) {
    cueErrorList.push('Overlaps with next cue');
  }

  return cueErrorList;
}

// Pure function to validate all cues
function computeCueErrors(cuesToValidate: VTTCue[]): Map<number, string[]> {
  const newCueErrors = new Map<number, string[]>();
  for (let i = 0; i < cuesToValidate.length; i++) {
    const cueErrorList = validateCueTimingAtIndex(cuesToValidate, i);
    if (cueErrorList.length > 0) {
      newCueErrors.set(i, cueErrorList);
    }
  }
  return newCueErrors;
}

interface VttEditorProps {
  vttContent: string;
  onChange: (content: string) => void;
  onCueSave?: (cueIndex: number, vttContent: string) => Promise<void>;
  onCueInserted?: (insertedIndex: number, totalCues: number) => void;
  onCueDeleted?: (deletedIndex: number, totalCuesAfterDelete: number) => void;
  onCuePlay?: (startTime: number) => void;
  title: string;
  readOnly?: boolean;
  glossaryTerms?: GlossaryTerm[];
  language?: string;
  insertAtTimeMs?: number | null;
  onInsertAtTimeDone?: () => void;
  /** True when this editor is displaying the source language VTT */
  isSourceLanguage?: boolean;
  /** Number of target languages that would have QC reset on source save */
  affectedLanguagesCount?: number;
  /** Called when user clicks "Re-translate all" — triggers retranslate_languages=true save */
  onRetranslate?: () => Promise<void>;
}

export function VttEditor({ vttContent, onChange, onCueSave, onCueInserted, onCueDeleted, onCuePlay, title, readOnly = false, glossaryTerms = [], language = 'en', insertAtTimeMs, onInsertAtTimeDone, isSourceLanguage = false, affectedLanguagesCount = 0, onRetranslate }: VttEditorProps) {
  const [cues, setCues] = useState<VTTCue[]>([]);
  const [errors, setErrors] = useState<string[]>([]);
  const [editingCue, setEditingCue] = useState<number | null>(null);
  const [hoveredCue, setHoveredCue] = useState<number | null>(null);
  const [cueToDelete, setCueToDelete] = useState<number | null>(null);
  const [cueErrors, setCueErrors] = useState<Map<number, string[]>>(new Map());
  const [savingCues, setSavingCues] = useState<Set<number>>(new Set());
  const [cueSaveErrors, setCueSaveErrors] = useState<Map<number, string>>(new Map());

  useEffect(() => {
    try {
      const parsedCues = VTTParser.parse(vttContent);
      setCues(parsedCues);

      // Validate content
      const validation = VTTValidator.validate(vttContent);
      setErrors(validation.errors);

      // Run per-cue validation
      setCueErrors(computeCueErrors(parsedCues));
    } catch (error) {
      setErrors([`Failed to parse VTT: ${error instanceof Error ? error.message : 'Unknown error'}`]);
    }
  }, [vttContent]);

  // Imperatively insert a cue near insertAtTimeMs when triggered from parent (e.g., timeline right-click)
  useEffect(() => {
    if (insertAtTimeMs == null || readOnly || cues.length === 0) return;
    const targetS = insertAtTimeMs / 1000;
    // Find the cue whose start time is nearest but after targetS, or insert at end
    let insertBeforeIdx = cues.findIndex(c => c.startTime >= targetS);
    if (insertBeforeIdx === -1) insertBeforeIdx = cues.length; // insert after last
    // Reuse insertCue logic inline: insertBefore insertBeforeIdx
    let startTime: number, endTime: number;
    if (insertBeforeIdx === 0) {
      startTime = Math.max(0, targetS - 1);
      endTime = Math.min(targetS + 1, cues[0].startTime);
    } else if (insertBeforeIdx === cues.length) {
      startTime = cues[cues.length - 1].endTime + 0.1;
      endTime = startTime + 2.0;
    } else {
      const prev = cues[insertBeforeIdx - 1];
      startTime = Math.max(prev.endTime, targetS - 1);
      endTime = Math.min(targetS + 1, cues[insertBeforeIdx].startTime);
    }
    if (endTime - startTime < 0.5) endTime = startTime + 0.5;
    const newCue: VTTCue = { startTime, endTime, text: '[Enter caption text]' };
    const updatedCues = [...cues];
    updatedCues.splice(insertBeforeIdx, 0, newCue);
    const newVtt = updateCuesLocal(updatedCues);
    onCueInserted?.(insertBeforeIdx, updatedCues.length);
    setEditingCue(insertBeforeIdx);
    void saveCue(insertBeforeIdx, newVtt);
    onInsertAtTimeDone?.();
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [insertAtTimeMs]);

  const updateCuesLocal = (updatedCues: VTTCue[]) => {
    setCues(updatedCues);
    setCueErrors(computeCueErrors(updatedCues));
    const newVttContent = VTTParser.build(updatedCues);
    onChange(newVttContent);
    return newVttContent;
  };

  const saveCue = async (index: number, newVttContent: string) => {
    if (!onCueSave) return;

    // Mark cue as saving
    setSavingCues(prev => new Set([...prev, index]));
    // Clear any previous error for this cue
    setCueSaveErrors(prev => {
      const newMap = new Map(prev);
      newMap.delete(index);
      return newMap;
    });

    try {
      await onCueSave(index, newVttContent);
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Failed to save';
      setCueSaveErrors(prev => new Map([...prev, [index, errorMessage]]));
    } finally {
      setSavingCues(prev => {
        const newSet = new Set(prev);
        newSet.delete(index);
        return newSet;
      });
    }
  };

  const updateCueText = (index: number, newText: string) => {
    const updatedCues = [...cues];
    updatedCues[index] = { ...updatedCues[index], text: newText };
    const newVttContent = updateCuesLocal(updatedCues);
    setEditingCue(null);
    saveCue(index, newVttContent);
  };

  const updateCueTiming = (index: number, startTime: number, endTime: number) => {
    const updatedCues = [...cues];
    updatedCues[index] = { ...updatedCues[index], startTime, endTime };
    const newVttContent = updateCuesLocal(updatedCues);
    saveCue(index, newVttContent);
  };

  const insertCue = (index: number, position: 'before' | 'after') => {
    const currentCue = cues[index];
    let startTime: number, endTime: number;

    if (position === 'before') {
      const prevCue = index > 0 ? cues[index - 1] : null;
      if (prevCue) {
        // Midpoint between previous end and current start
        startTime = (prevCue.endTime + currentCue.startTime) / 2;
        endTime = currentCue.startTime;
      } else {
        // First cue: start at 0
        startTime = 0;
        endTime = Math.max(0.5, currentCue.startTime);
      }
    } else {
      // 'after'
      const nextCue = index < cues.length - 1 ? cues[index + 1] : null;
      if (nextCue) {
        // Midpoint between current end and next start
        startTime = currentCue.endTime;
        endTime = (currentCue.endTime + nextCue.startTime) / 2;
      } else {
        // Last cue: extend 2 seconds
        startTime = currentCue.endTime + 0.1;
        endTime = currentCue.endTime + 2.0;
      }
    }

    // Ensure minimum duration of 0.5s
    if (endTime - startTime < 0.5) {
      endTime = startTime + 0.5;
    }

    const newCue: VTTCue = { startTime, endTime, text: '[Enter caption text]' };
    const updatedCues = [...cues];
    const insertIndex = position === 'before' ? index : index + 1;
    updatedCues.splice(insertIndex, 0, newCue);

    const newVttContent = updateCuesLocal(updatedCues);
    // Notify parent about insertion so it can queue TTS for shifted cues
    onCueInserted?.(insertIndex, updatedCues.length);
    // Auto-enter edit mode for the new cue
    setEditingCue(insertIndex);
    // Persist immediately so the cue survives navigation even if text is not edited
    void saveCue(insertIndex, newVttContent);
  };

  const deleteCue = (index: number) => {
    const updatedCues = cues.filter((_, i) => i !== index);
    const newVttContent = updateCuesLocal(updatedCues);
    setCueToDelete(null);
    // Notify parent about deletion so it can queue TTS for shifted cues
    onCueDeleted?.(index, updatedCues.length);
    // Save after delete - use index of deleted cue (will save full VTT)
    saveCue(index, newVttContent);
  };

  const formatTime = (seconds: number): string => {
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const secs = seconds % 60;

    const wholeSeconds = Math.floor(secs);
    const milliseconds = Math.round((secs - wholeSeconds) * 1000);

    if (hours > 0) {
      return `${hours}:${minutes.toString().padStart(2, '0')}:${wholeSeconds.toString().padStart(2, '0')}.${milliseconds.toString().padStart(3, '0')}`;
    }
    return `${minutes}:${wholeSeconds.toString().padStart(2, '0')}.${milliseconds.toString().padStart(3, '0')}`;
  };

  const totalErrorCount = Array.from(cueErrors.values()).reduce((sum, errs) => sum + errs.length, 0);

  const [retranslating, setRetranslating] = useState(false);

  const handleRetranslate = async () => {
    if (!onRetranslate) return;
    setRetranslating(true);
    try {
      await onRetranslate();
    } finally {
      setRetranslating(false);
    }
  };

  return (
    <div className="border border-gray-300 rounded-lg">
      {/* Source-language invalidation banner */}
      {isSourceLanguage && !readOnly && affectedLanguagesCount > 0 && (
        <div className="flex items-center justify-between gap-3 px-4 py-2.5 bg-amber-50 border-b border-amber-200 rounded-t-lg">
          <p className="text-sm text-amber-800">
            Saving will reset QC for <strong>{affectedLanguagesCount}</strong> translated {affectedLanguagesCount === 1 ? 'language' : 'languages'}.
          </p>
          {onRetranslate && (
            <button
              onClick={handleRetranslate}
              disabled={retranslating}
              className="flex-shrink-0 px-3 py-1 text-xs font-medium bg-amber-600 text-white rounded hover:bg-amber-700 disabled:opacity-50"
            >
              {retranslating ? 'Translating…' : 'Re-translate all'}
            </button>
          )}
        </div>
      )}
      {/* Header */}
      <div className="bg-gray-50 px-4 py-3 border-b border-gray-300">
        <div className="flex items-center justify-between">
          <h3 className="text-lg font-medium text-gray-900">{title}</h3>
          {totalErrorCount > 0 && (
            <span className="text-sm text-amber-600 font-medium">
              ⚠️ {totalErrorCount} validation {totalErrorCount === 1 ? 'warning' : 'warnings'}
            </span>
          )}
        </div>
        {errors.length > 0 && (
          <div className="mt-2">
            <div className="text-sm text-red-600">
              <p className="font-medium">Validation Errors:</p>
              <ul className="list-disc list-inside mt-1">
                {errors.map((error, i) => (
                  <li key={i}>{error}</li>
                ))}
              </ul>
            </div>
          </div>
        )}
      </div>

      {/* Cue List */}
      <div className="max-h-96 overflow-y-auto">
        {cues.length === 0 ? (
          <div className="p-4 text-center text-gray-500">
            No cues found in VTT content
          </div>
        ) : (
          <div className="divide-y divide-gray-200">
            {/* Gap bar before first cue — shows when there's silence/music before first caption */}
            {!readOnly && cues.length > 0 && cues[0].startTime > 0.5 && (
              <GapInsertRow
                gapSeconds={cues[0].startTime}
                onInsert={() => insertCue(0, 'before')}
              />
            )}
            {cues.map((cue, index) => (
              <Fragment key={index}>
              <div
                className="p-4 hover:bg-gray-50"
                onMouseEnter={() => setHoveredCue(index)}
                onMouseLeave={() => setHoveredCue(null)}
              >
                {/* Timing Row */}
                <div className="flex items-center justify-between mb-2">
                  <div className="flex items-center gap-1">
                    {/* Cue Number */}
                    <span className="inline-flex items-center justify-center w-6 h-6 text-xs font-bold text-white bg-orange-400 rounded-full mr-2">
                      {index + 1}
                    </span>
                    {readOnly ? (
                      <span className="text-sm text-gray-500 font-mono">
                        {formatTime(cue.startTime)} → {formatTime(cue.endTime)}
                      </span>
                    ) : (
                      <>
                        <TimestampInput
                          value={cue.startTime}
                          onChange={(newStart) => updateCueTiming(index, newStart, cue.endTime)}
                          hasError={cueErrors.get(index)?.some(e => e.includes('Start') || e.includes('previous'))}
                        />
                        <span className="text-gray-400 mx-1">→</span>
                        <TimestampInput
                          value={cue.endTime}
                          onChange={(newEnd) => updateCueTiming(index, cue.startTime, newEnd)}
                          hasError={cueErrors.get(index)?.some(e => e.includes('end') || e.includes('next'))}
                        />
                      </>
                    )}
                    <span className="ml-2 text-xs text-gray-400">
                      ({((cue.endTime - cue.startTime) * 1000).toFixed(0)}ms)
                    </span>
                    {/* Saving indicator */}
                    {savingCues.has(index) && (
                      <span className="ml-2 flex items-center gap-1 text-xs text-blue-600">
                        <SpinnerIcon />
                        Saving...
                      </span>
                    )}
                    {/* Play-from-cue button (R-7) */}
                    {onCuePlay && hoveredCue === index && (
                      <button
                        onClick={() => onCuePlay(cue.startTime)}
                        className="ml-1 p-1 text-gray-400 hover:text-green-600 hover:bg-green-50 rounded transition-colors"
                        title="Play from this cue"
                      >
                        ▶
                      </button>
                    )}
                  </div>

                  {/* Action Buttons — always visible in edit mode */}
                  {!readOnly && !savingCues.has(index) && (
                    <CueActionButtons
                      onInsertBefore={() => insertCue(index, 'before')}
                      onInsertAfter={() => insertCue(index, 'after')}
                      onDelete={() => setCueToDelete(index)}
                    />
                  )}
                </div>

                {/* Save error */}
                {cueSaveErrors.get(index) && (
                  <div className="mb-2 flex items-center gap-2">
                    <span className="text-xs text-red-600 flex items-center gap-1">
                      <WarningIcon />
                      {cueSaveErrors.get(index)}
                    </span>
                    <button
                      onClick={() => saveCue(index, VTTParser.build(cues))}
                      className="text-xs text-blue-600 hover:text-blue-800 underline"
                    >
                      Retry
                    </button>
                  </div>
                )}

                {/* Per-cue validation warnings */}
                {cueErrors.get(index) && (
                  <div className="mb-2">
                    {cueErrors.get(index)!.map((err, errIdx) => (
                      <div key={errIdx} className="text-xs text-amber-600 flex items-center gap-1">
                        <WarningIcon />
                        {err}
                      </div>
                    ))}
                  </div>
                )}

                {/* CPS badge */}
                {(() => {
                  const cps = computeCps(cue);
                  return cps > CPS_THRESHOLD ? (
                    <div className="mb-1 flex items-center gap-1">
                      <span className="text-xs px-1.5 py-0.5 bg-amber-100 text-amber-700 rounded font-medium" title={`${cps.toFixed(1)} characters per second — above the ${CPS_THRESHOLD} CPS recommended limit`}>
                        ⚡ {cps.toFixed(0)} CPS
                      </span>
                    </div>
                  ) : null;
                })()}

                {/* Text Content */}
                {editingCue === index ? (
                  <CueEditor
                    initialText={cue.text}
                    onSave={(newText) => updateCueText(index, newText)}
                    onCancel={() => setEditingCue(null)}
                  />
                ) : (
                  <div className="group">
                    <div className="text-gray-900 whitespace-pre-wrap leading-relaxed">
                      {buildSegments(cue.text, glossaryTerms, language).map((seg, si) =>
                        seg.glossaryMatch ? (
                          <span
                            key={si}
                            className="underline decoration-amber-400 decoration-2 underline-offset-2 cursor-help"
                            title={`Preferred: ${seg.glossaryMatch.preferred}`}
                          >
                            {seg.text}
                          </span>
                        ) : (
                          <span key={si}>{seg.text}</span>
                        )
                      )}
                    </div>
                    {!readOnly && (
                      <button
                        onClick={() => setEditingCue(index)}
                        className="mt-2 opacity-0 group-hover:opacity-100 text-sm text-blue-600 hover:text-blue-800 transition-opacity"
                      >
                        Edit text
                      </button>
                    )}
                  </div>
                )}
              </div>
              {/* Gap bar between cues — shown when there's a gap > 0.5s */}
              {!readOnly && index < cues.length - 1 && (cues[index + 1].startTime - cue.endTime) > 0.5 && (
                <GapInsertRow
                  gapSeconds={cues[index + 1].startTime - cue.endTime}
                  onInsert={() => insertCue(index + 1, 'before')}
                />
              )}
              </Fragment>
            ))}
          </div>
        )}
      </div>

      {/* Footer Stats */}
      <div className="bg-gray-50 px-4 py-2 border-t border-gray-300 text-sm text-gray-600">
        {cues.length} cues • Total duration: {formatTime(Math.max(...cues.map(c => c.endTime), 0))}
      </div>

      {/* Delete Confirmation Modal */}
      {cueToDelete !== null && (
        <DeleteConfirmModal
          cue={cues[cueToDelete]}
          formatTime={formatTime}
          onConfirm={() => deleteCue(cueToDelete)}
          onCancel={() => setCueToDelete(null)}
        />
      )}
    </div>
  );
}

// TimestampInput Component
interface TimestampInputProps {
  value: number;
  onChange: (newValue: number) => void;
  hasError?: boolean;
}

function TimestampInput({ value, onChange, hasError }: TimestampInputProps) {
  const [inputValue, setInputValue] = useState(VTTParser.formatTimestamp(value));
  const [isEditing, setIsEditing] = useState(false);
  const [parseError, setParseError] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    if (!isEditing) {
      setInputValue(VTTParser.formatTimestamp(value));
    }
  }, [value, isEditing]);

  const handleFocus = () => {
    setIsEditing(true);
  };

  const handleBlur = () => {
    try {
      const parsed = VTTParser.parseTimestamp(inputValue);
      // Clamp to minimum 0
      const clampedValue = Math.max(0, parsed);
      onChange(clampedValue);
      setParseError(false);
    } catch {
      // Revert to original value on parse error
      setInputValue(VTTParser.formatTimestamp(value));
      setParseError(false);
    }
    setIsEditing(false);
  };

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === 'Enter') {
      inputRef.current?.blur();
    } else if (e.key === 'Escape') {
      setInputValue(VTTParser.formatTimestamp(value));
      setParseError(false);
      setIsEditing(false);
    }
  };

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const newValue = e.target.value;
    setInputValue(newValue);

    // Validate as user types
    try {
      VTTParser.parseTimestamp(newValue);
      setParseError(false);
    } catch {
      setParseError(true);
    }
  };

  return (
    <input
      ref={inputRef}
      type="text"
      value={inputValue}
      onChange={handleChange}
      onFocus={handleFocus}
      onBlur={handleBlur}
      onKeyDown={handleKeyDown}
      className={`
        w-28 px-2 py-0.5 text-sm font-mono rounded border
        focus:outline-none focus:ring-2 focus:ring-blue-500
        ${parseError || hasError ? 'border-red-400 bg-red-50' : 'border-gray-300 bg-white'}
      `}
      title="Edit timestamp (format: 0:00.000 or 00:00:00.000)"
    />
  );
}

// GapInsertRow — clickable row shown in silent gaps before or between cues
function GapInsertRow({ gapSeconds, onInsert }: { gapSeconds: number; onInsert: () => void }) {
  const [hovered, setHovered] = useState(false);
  const label = `${gapSeconds.toFixed(1)}s gap`;
  return (
    <div
      className={`flex items-center justify-center gap-2 py-1.5 cursor-pointer select-none border-y border-dashed transition-colors ${hovered ? 'bg-blue-50 border-blue-300' : 'bg-gray-50 border-gray-200'}`}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
      onClick={onInsert}
      title={`Insert cue in this gap (${label})`}
    >
      <span className={`text-xs font-medium ${hovered ? 'text-blue-600' : 'text-gray-400'}`}>
        + Add cue here &nbsp;·&nbsp; {label}
      </span>
    </div>
  );
}

// CueActionButtons Component
interface CueActionButtonsProps {
  onInsertBefore: () => void;
  onInsertAfter: () => void;
  onDelete: () => void;
}

function CueActionButtons({ onInsertBefore, onInsertAfter, onDelete }: CueActionButtonsProps) {
  return (
    <div className="flex items-center gap-1">
      <button
        onClick={onInsertBefore}
        className="p-1 text-gray-400 hover:text-blue-600 hover:bg-blue-50 rounded transition-colors"
        title="Insert cue before"
      >
        <InsertBeforeIcon />
      </button>
      <button
        onClick={onInsertAfter}
        className="p-1 text-gray-400 hover:text-blue-600 hover:bg-blue-50 rounded transition-colors"
        title="Insert cue after"
      >
        <InsertAfterIcon />
      </button>
      <button
        onClick={onDelete}
        className="p-1 text-gray-400 hover:text-red-600 hover:bg-red-50 rounded transition-colors"
        title="Delete cue"
      >
        <TrashIcon />
      </button>
    </div>
  );
}

// DeleteConfirmModal Component
interface DeleteConfirmModalProps {
  cue: VTTCue;
  formatTime: (seconds: number) => string;
  onConfirm: () => void;
  onCancel: () => void;
}

function DeleteConfirmModal({ cue, formatTime, onConfirm, onCancel }: DeleteConfirmModalProps) {
  const previewText = cue.text.length > 50 ? cue.text.slice(0, 50) + '...' : cue.text;

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center">
      {/* Backdrop */}
      <div
        className="absolute inset-0 bg-black bg-opacity-50"
        onClick={onCancel}
      />

      {/* Modal */}
      <div className="relative bg-white rounded-lg shadow-xl max-w-md w-full mx-4 p-6">
        <h3 className="text-lg font-semibold text-gray-900 mb-2">
          Delete Caption Cue?
        </h3>

        <p className="text-gray-600 mb-4">
          Are you sure you want to delete this cue? This action cannot be undone.
        </p>

        <div className="bg-gray-50 rounded-lg p-3 mb-4">
          <div className="text-sm text-gray-500 font-mono mb-1">
            {formatTime(cue.startTime)} → {formatTime(cue.endTime)}
          </div>
          <div className="text-gray-700 text-sm">
            "{previewText}"
          </div>
        </div>

        <div className="flex justify-end gap-3">
          <button
            onClick={onCancel}
            className="px-4 py-2 text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-md transition-colors"
          >
            Cancel
          </button>
          <button
            onClick={onConfirm}
            className="px-4 py-2 text-white bg-red-600 hover:bg-red-700 rounded-md transition-colors"
          >
            Delete
          </button>
        </div>
      </div>
    </div>
  );
}

// CueEditor Component (existing, unchanged)
interface CueEditorProps {
  initialText: string;
  onSave: (text: string) => void;
  onCancel: () => void;
}

function CueEditor({ initialText, onSave, onCancel }: CueEditorProps) {
  const [text, setText] = useState(initialText);

  const handleSave = () => {
    onSave(text);
  };

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === 'Escape') {
      onCancel();
    } else if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
      handleSave();
    }
  };

  return (
    <div className="space-y-2">
      <textarea
        value={text}
        onChange={(e) => setText(e.target.value)}
        onKeyDown={handleKeyDown}
        className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 resize-none"
        rows={3}
        autoFocus
      />
      <div className="flex gap-2">
        <button
          onClick={handleSave}
          className="px-3 py-1 bg-blue-600 text-white text-sm rounded hover:bg-blue-700"
        >
          Save (Ctrl+Enter)
        </button>
        <button
          onClick={onCancel}
          className="px-3 py-1 bg-gray-300 text-gray-700 text-sm rounded hover:bg-gray-400"
        >
          Cancel (Esc)
        </button>
      </div>
    </div>
  );
}

// Icon Components
function InsertBeforeIcon() {
  return (
    <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
      <path strokeLinecap="round" strokeLinejoin="round" d="M12 4v16m0-16l-4 4m4-4l4 4" />
      <line x1="6" y1="20" x2="18" y2="20" strokeLinecap="round" />
    </svg>
  );
}

function InsertAfterIcon() {
  return (
    <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
      <path strokeLinecap="round" strokeLinejoin="round" d="M12 20V4m0 16l-4-4m4 4l4-4" />
      <line x1="6" y1="4" x2="18" y2="4" strokeLinecap="round" />
    </svg>
  );
}

function TrashIcon() {
  return (
    <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
      <path strokeLinecap="round" strokeLinejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
    </svg>
  );
}

function WarningIcon() {
  return (
    <svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
      <path strokeLinecap="round" strokeLinejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
    </svg>
  );
}

function SpinnerIcon() {
  return (
    <svg className="w-3 h-3 animate-spin" viewBox="0 0 24 24">
      <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
      <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
    </svg>
  );
}
