'use client';

import * as React from 'react';
import { Music, Plus, Upload, Trash2 } from 'lucide-react';
import { PlaybackControls } from './PlaybackControls';
import { ThemeToggle } from '@/components/layout/ThemeToggle';
import { CommandPalette } from '@/components/ui/CommandPalette';
import { Button } from '@/components/ui/Button';
import type { CommandAction } from '@/components/ui/CommandPalette';
import { useMultiTrack } from '@/lib/hooks/useMultiTrack';
import { useMultiTrackPlayer } from '@/lib/hooks/useMultiTrackPlayer';
import { useEffectChain } from '@/lib/hooks/useEffectChain';
import { useToast } from '@/components/ui/Toast';
import { TrackList } from '@/components/tracks/TrackList';
import { ImportTrackDialog } from '@/components/tracks/ImportTrackDialog';
import { formatDuration } from '@/lib/audio/decoder';
import { useHistory } from '@/lib/hooks/useHistory';
import { useRecording } from '@/lib/hooks/useRecording';
import {
  createMultiTrackCutCommand,
  createMultiTrackCopyCommand,
  createMultiTrackDeleteCommand,
  createMultiTrackPasteCommand,
  createMultiTrackDuplicateCommand,
} from '@/lib/history/commands/multi-track-edit-command';
import { extractBufferSegment } from '@/lib/audio/buffer-utils';

export function AudioEditor() {
  const [importDialogOpen, setImportDialogOpen] = React.useState(false);
  const [selectedTrackId, setSelectedTrackId] = React.useState<string | null>(null);
  const [zoom, setZoom] = React.useState(1);
  const [masterVolume, setMasterVolume] = React.useState(0.8);
  const [clipboard, setClipboard] = React.useState<AudioBuffer | null>(null);
  const [recordingTrackId, setRecordingTrackId] = React.useState<string | null>(null);

  const { addToast } = useToast();

  // Command history for undo/redo
  const { execute: executeCommand, undo, redo, state: historyState } = useHistory();
  const canUndo = historyState.canUndo;
  const canRedo = historyState.canRedo;

  // Recording hook
  const {
    state: recordingState,
    startRecording,
    stopRecording,
    requestPermission,
  } = useRecording();

  // Multi-track hooks
  const {
    tracks,
    addTrack,
    addTrackFromBuffer,
    removeTrack,
    updateTrack,
    clearTracks,
  } = useMultiTrack();

  // Log tracks to see if they update
  React.useEffect(() => {
    console.log('[AudioEditor] Tracks updated:', tracks.map(t => ({
      name: t.name,
      effectCount: t.effectChain.effects.length,
      effects: t.effectChain.effects.map(e => e.name)
    })));
  }, [tracks]);

  const {
    isPlaying,
    currentTime,
    duration,
    play,
    pause,
    stop,
    seek,
    togglePlayPause,
  } = useMultiTrackPlayer(tracks, masterVolume);

  // Master effect chain
  const {
    chain: masterEffectChain,
    presets: masterEffectPresets,
    toggleEffectEnabled: toggleMasterEffect,
    removeEffect: removeMasterEffect,
    reorder: reorderMasterEffects,
    clearChain: clearMasterChain,
    savePreset: saveMasterPreset,
    loadPresetToChain: loadMasterPreset,
    deletePreset: deleteMasterPreset,
  } = useEffectChain();

  // Multi-track handlers
  const handleImportTracks = () => {
    setImportDialogOpen(true);
  };

  const handleImportTrack = (buffer: AudioBuffer, name: string) => {
    addTrackFromBuffer(buffer, name);
  };

  const handleClearTracks = () => {
    clearTracks();
    setSelectedTrackId(null);
    addToast({
      title: 'Tracks Cleared',
      description: 'All tracks have been removed',
      variant: 'info',
      duration: 2000,
    });
  };

  const handleRemoveTrack = (trackId: string) => {
    removeTrack(trackId);
    if (selectedTrackId === trackId) {
      setSelectedTrackId(null);
    }
  };

  // Per-track effect chain handlers
  const handleToggleTrackEffect = (effectId: string) => {
    if (!selectedTrack) return;
    const updatedChain = {
      ...selectedTrack.effectChain,
      effects: selectedTrack.effectChain.effects.map((e) =>
        e.id === effectId ? { ...e, enabled: !e.enabled } : e
      ),
    };
    updateTrack(selectedTrack.id, { effectChain: updatedChain });
  };

  const handleRemoveTrackEffect = (effectId: string) => {
    if (!selectedTrack) return;
    const updatedChain = {
      ...selectedTrack.effectChain,
      effects: selectedTrack.effectChain.effects.filter((e) => e.id !== effectId),
    };
    updateTrack(selectedTrack.id, { effectChain: updatedChain });
  };

  const handleReorderTrackEffects = (fromIndex: number, toIndex: number) => {
    if (!selectedTrack) return;
    const effects = [...selectedTrack.effectChain.effects];
    const [removed] = effects.splice(fromIndex, 1);
    effects.splice(toIndex, 0, removed);
    const updatedChain = {
      ...selectedTrack.effectChain,
      effects,
    };
    updateTrack(selectedTrack.id, { effectChain: updatedChain });
  };

  const handleClearTrackChain = () => {
    if (!selectedTrack) return;
    const updatedChain = {
      ...selectedTrack.effectChain,
      effects: [],
    };
    updateTrack(selectedTrack.id, { effectChain: updatedChain });
  };

  // Selection handler
  const handleSelectionChange = (trackId: string, selection: { start: number; end: number } | null) => {
    updateTrack(trackId, { selection });
  };

  // Recording handlers
  const handleToggleRecordEnable = React.useCallback((trackId: string) => {
    const track = tracks.find((t) => t.id === trackId);
    if (!track) return;

    // Toggle record enable
    updateTrack(trackId, { recordEnabled: !track.recordEnabled });
  }, [tracks, updateTrack]);

  const handleStartRecording = React.useCallback(async () => {
    // Find first armed track
    const armedTrack = tracks.find((t) => t.recordEnabled);
    if (!armedTrack) {
      addToast({
        title: 'No Track Armed',
        description: 'Please arm a track for recording first',
        variant: 'warning',
        duration: 3000,
      });
      return;
    }

    // Request permission if needed
    const hasPermission = await requestPermission();
    if (!hasPermission) {
      addToast({
        title: 'Microphone Access Denied',
        description: 'Please allow microphone access to record',
        variant: 'error',
        duration: 3000,
      });
      return;
    }

    try {
      await startRecording();
      setRecordingTrackId(armedTrack.id);
      addToast({
        title: 'Recording Started',
        description: `Recording to ${armedTrack.name}`,
        variant: 'success',
        duration: 2000,
      });
    } catch (error) {
      console.error('Failed to start recording:', error);
      addToast({
        title: 'Recording Failed',
        description: 'Failed to start recording',
        variant: 'error',
        duration: 3000,
      });
    }
  }, [tracks, startRecording, requestPermission, addToast]);

  const handleStopRecording = React.useCallback(async () => {
    if (!recordingTrackId) return;

    try {
      const audioBuffer = await stopRecording();

      if (audioBuffer) {
        // Update the track with recorded audio
        updateTrack(recordingTrackId, { audioBuffer });

        addToast({
          title: 'Recording Complete',
          description: `Recorded ${audioBuffer.duration.toFixed(2)}s of audio`,
          variant: 'success',
          duration: 3000,
        });
      }

      setRecordingTrackId(null);
    } catch (error) {
      console.error('Failed to stop recording:', error);
      addToast({
        title: 'Recording Error',
        description: 'Failed to save recording',
        variant: 'error',
        duration: 3000,
      });
      setRecordingTrackId(null);
    }
  }, [recordingTrackId, stopRecording, updateTrack, addToast]);

  // Edit handlers
  const handleCut = React.useCallback(() => {
    const track = tracks.find((t) => t.selection);
    if (!track || !track.audioBuffer || !track.selection) return;

    // Extract to clipboard
    const extracted = extractBufferSegment(
      track.audioBuffer,
      track.selection.start,
      track.selection.end
    );
    setClipboard(extracted);

    // Execute cut command
    const command = createMultiTrackCutCommand(
      track.id,
      track.audioBuffer,
      track.selection,
      (trackId, buffer, selection) => {
        updateTrack(trackId, { audioBuffer: buffer, selection });
      }
    );
    executeCommand(command);

    addToast({
      title: 'Cut',
      description: 'Selection cut to clipboard',
      variant: 'success',
      duration: 2000,
    });
  }, [tracks, executeCommand, updateTrack, addToast]);

  const handleCopy = React.useCallback(() => {
    const track = tracks.find((t) => t.selection);
    if (!track || !track.audioBuffer || !track.selection) return;

    // Extract to clipboard
    const extracted = extractBufferSegment(
      track.audioBuffer,
      track.selection.start,
      track.selection.end
    );
    setClipboard(extracted);

    // Execute copy command (doesn't modify buffer, just for undo history)
    const command = createMultiTrackCopyCommand(
      track.id,
      track.audioBuffer,
      track.selection,
      (trackId, buffer, selection) => {
        updateTrack(trackId, { audioBuffer: buffer, selection });
      }
    );
    executeCommand(command);

    addToast({
      title: 'Copy',
      description: 'Selection copied to clipboard',
      variant: 'success',
      duration: 2000,
    });
  }, [tracks, executeCommand, updateTrack, addToast]);

  const handlePaste = React.useCallback(() => {
    if (!clipboard || !selectedTrackId) return;

    const track = tracks.find((t) => t.id === selectedTrackId);
    if (!track) return;

    // Paste at current time or at end of buffer
    const pastePosition = currentTime || track.audioBuffer?.duration || 0;

    const command = createMultiTrackPasteCommand(
      track.id,
      track.audioBuffer,
      clipboard,
      pastePosition,
      (trackId, buffer, selection) => {
        updateTrack(trackId, { audioBuffer: buffer, selection });
      }
    );
    executeCommand(command);

    addToast({
      title: 'Paste',
      description: 'Clipboard content pasted',
      variant: 'success',
      duration: 2000,
    });
  }, [clipboard, selectedTrackId, tracks, currentTime, executeCommand, updateTrack, addToast]);

  const handleDelete = React.useCallback(() => {
    const track = tracks.find((t) => t.selection);
    if (!track || !track.audioBuffer || !track.selection) return;

    const command = createMultiTrackDeleteCommand(
      track.id,
      track.audioBuffer,
      track.selection,
      (trackId, buffer, selection) => {
        updateTrack(trackId, { audioBuffer: buffer, selection });
      }
    );
    executeCommand(command);

    addToast({
      title: 'Delete',
      description: 'Selection deleted',
      variant: 'success',
      duration: 2000,
    });
  }, [tracks, executeCommand, updateTrack, addToast]);

  const handleDuplicate = React.useCallback(() => {
    const track = tracks.find((t) => t.selection);
    if (!track || !track.audioBuffer || !track.selection) return;

    const command = createMultiTrackDuplicateCommand(
      track.id,
      track.audioBuffer,
      track.selection,
      (trackId, buffer, selection) => {
        updateTrack(trackId, { audioBuffer: buffer, selection });
      }
    );
    executeCommand(command);

    addToast({
      title: 'Duplicate',
      description: 'Selection duplicated',
      variant: 'success',
      duration: 2000,
    });
  }, [tracks, executeCommand, updateTrack, addToast]);

  // Zoom controls
  const handleZoomIn = () => {
    setZoom((prev) => Math.min(20, prev + 1));
  };

  const handleZoomOut = () => {
    setZoom((prev) => Math.max(1, prev - 1));
  };

  const handleFitToView = () => {
    setZoom(1);
  };

  // Keyboard shortcuts
  React.useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      // Spacebar for play/pause - only if not interacting with form elements
      if (e.code === 'Space') {
        const target = e.target as HTMLElement;
        // Don't trigger if user is typing or interacting with buttons/form elements
        if (
          target instanceof HTMLInputElement ||
          target instanceof HTMLTextAreaElement ||
          target instanceof HTMLButtonElement ||
          target.getAttribute('role') === 'button'
        ) {
          return;
        }
        e.preventDefault();
        togglePlayPause();
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [togglePlayPause]);

  // Find selected track
  const selectedTrack = tracks.find((t) => t.id === selectedTrackId);

  // Command palette actions
  const commandActions: CommandAction[] = React.useMemo(() => {
    const actions: CommandAction[] = [
      // Playback
      {
        id: 'play',
        label: 'Play',
        description: 'Start playback',
        shortcut: 'Space',
        category: 'playback',
        action: play,
      },
      {
        id: 'pause',
        label: 'Pause',
        description: 'Pause playback',
        shortcut: 'Space',
        category: 'playback',
        action: pause,
      },
      {
        id: 'stop',
        label: 'Stop',
        description: 'Stop playback',
        category: 'playback',
        action: stop,
      },
      // View
      {
        id: 'zoom-in',
        label: 'Zoom In',
        description: 'Zoom in on waveforms',
        category: 'view',
        action: handleZoomIn,
      },
      {
        id: 'zoom-out',
        label: 'Zoom Out',
        description: 'Zoom out on waveforms',
        category: 'view',
        action: handleZoomOut,
      },
      {
        id: 'fit-to-view',
        label: 'Fit to View',
        description: 'Reset zoom to fit all tracks',
        category: 'view',
        action: handleFitToView,
      },
      // Tracks
      {
        id: 'add-track',
        label: 'Add Empty Track',
        description: 'Create a new empty track',
        category: 'tracks',
        action: () => addTrack(),
      },
      {
        id: 'import-tracks',
        label: 'Import Audio Files',
        description: 'Import multiple audio files as tracks',
        category: 'tracks',
        action: handleImportTracks,
      },
      {
        id: 'clear-tracks',
        label: 'Clear All Tracks',
        description: 'Remove all tracks',
        category: 'tracks',
        action: handleClearTracks,
      },
    ];
    return actions;
  }, [play, pause, stop, handleZoomIn, handleZoomOut, handleFitToView, handleImportTracks, handleClearTracks, addTrack]);

  // Keyboard shortcuts
  React.useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      // Prevent shortcuts if typing in an input
      const isTyping = e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement;

      // Spacebar: Play/Pause (always, unless typing in an input)
      if (e.code === 'Space' && !isTyping) {
        e.preventDefault();
        togglePlayPause();
        return;
      }

      if (isTyping) return;

      // Ctrl/Cmd+Z: Undo
      if ((e.ctrlKey || e.metaKey) && e.key === 'z' && !e.shiftKey) {
        e.preventDefault();
        if (canUndo) {
          undo();
        }
        return;
      }

      // Ctrl/Cmd+Shift+Z or Ctrl/Cmd+Y: Redo
      if (((e.ctrlKey || e.metaKey) && e.key === 'z' && e.shiftKey) || ((e.ctrlKey || e.metaKey) && e.key === 'y')) {
        e.preventDefault();
        if (canRedo) {
          redo();
        }
        return;
      }

      // Ctrl/Cmd+X: Cut
      if ((e.ctrlKey || e.metaKey) && e.key === 'x') {
        e.preventDefault();
        handleCut();
        return;
      }

      // Ctrl/Cmd+C: Copy
      if ((e.ctrlKey || e.metaKey) && e.key === 'c') {
        e.preventDefault();
        handleCopy();
        return;
      }

      // Ctrl/Cmd+V: Paste
      if ((e.ctrlKey || e.metaKey) && e.key === 'v') {
        e.preventDefault();
        handlePaste();
        return;
      }

      // Ctrl/Cmd+D: Duplicate
      if ((e.ctrlKey || e.metaKey) && e.key === 'd') {
        e.preventDefault();
        handleDuplicate();
        return;
      }

      // Delete or Backspace: Delete selection
      if (e.key === 'Delete' || e.key === 'Backspace') {
        e.preventDefault();
        handleDelete();
        return;
      }

      // Escape: Clear selection
      if (e.key === 'Escape') {
        e.preventDefault();
        setSelectedTrackId(null);
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [togglePlayPause, canUndo, canRedo, undo, redo, handleCut, handleCopy, handlePaste, handleDelete, handleDuplicate]);

  return (
    <>
      {/* Compact Header */}
      <header className="flex items-center justify-between px-4 py-2 border-b border-border bg-card flex-shrink-0 gap-4">
        {/* Left: Logo */}
        <div className="flex items-center gap-4 flex-shrink-0">
          <div className="flex items-center gap-2">
            <Music className="h-5 w-5 text-primary" />
            <h1 className="text-lg font-bold text-foreground">Audio UI</h1>
          </div>

          {/* Track Actions */}
          <div className="flex items-center gap-2 border-l border-border pl-4">
            <Button variant="outline" size="sm" onClick={() => addTrack()}>
              <Plus className="h-4 w-4 mr-1.5" />
              Add Track
            </Button>
            <Button variant="outline" size="sm" onClick={handleImportTracks}>
              <Upload className="h-4 w-4 mr-1.5" />
              Import
            </Button>
            {tracks.length > 0 && (
              <Button variant="outline" size="sm" onClick={handleClearTracks}>
                <Trash2 className="h-4 w-4 mr-1.5 text-destructive" />
                Clear All
              </Button>
            )}
          </div>
        </div>

        {/* Right: Command Palette + Theme Toggle */}
        <div className="flex items-center gap-2 flex-shrink-0">
          <CommandPalette actions={commandActions} />
          <ThemeToggle />
        </div>
      </header>

      {/* Main content area */}
      <div className="flex flex-1 overflow-hidden">
        {/* Main canvas area */}
        <main className="flex-1 flex flex-col overflow-hidden bg-background">
          {/* Multi-Track View */}
          <div className="flex-1 flex flex-col overflow-hidden">
            <TrackList
              tracks={tracks}
              zoom={zoom}
              currentTime={currentTime}
              duration={duration}
              selectedTrackId={selectedTrackId}
              onSelectTrack={setSelectedTrackId}
              onAddTrack={addTrack}
              onImportTrack={handleImportTrack}
              onRemoveTrack={handleRemoveTrack}
              onUpdateTrack={updateTrack}
              onSeek={seek}
              onSelectionChange={handleSelectionChange}
              onToggleRecordEnable={handleToggleRecordEnable}
              recordingTrackId={recordingTrackId}
              recordingLevel={recordingState.inputLevel}
            />
          </div>

        </main>
      </div>

      {/* Transport Controls */}
      <div className="border-t border-border bg-card p-3 flex justify-center">
        <PlaybackControls
          isPlaying={isPlaying}
          isPaused={!isPlaying}
          currentTime={currentTime}
          duration={duration}
          volume={masterVolume}
          onPlay={play}
          onPause={pause}
          onStop={stop}
          onSeek={seek}
          onVolumeChange={setMasterVolume}
          currentTimeFormatted={formatDuration(currentTime)}
          durationFormatted={formatDuration(duration)}
          isRecording={recordingState.isRecording}
          onStartRecording={handleStartRecording}
          onStopRecording={handleStopRecording}
        />
      </div>

      {/* Import Track Dialog */}
      <ImportTrackDialog
        open={importDialogOpen}
        onClose={() => setImportDialogOpen(false)}
        onImportTrack={handleImportTrack}
      />
    </>
  );
}
