'use client';

import * as React from 'react';
import { FileUpload } from './FileUpload';
import { AudioInfo } from './AudioInfo';
import { Waveform } from './Waveform';
import { PlaybackControls } from './PlaybackControls';
import { ZoomControls } from './ZoomControls';
import { EditControls } from './EditControls';
import { HistoryControls } from './HistoryControls';
import { useAudioPlayer } from '@/lib/hooks/useAudioPlayer';
import { useHistory } from '@/lib/hooks/useHistory';
import { useToast } from '@/components/ui/Toast';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card';
import { Slider } from '@/components/ui/Slider';
import { Loader2 } from 'lucide-react';
import type { Selection, ClipboardData } from '@/types/selection';
import {
  extractBufferSegment,
  deleteBufferSegment,
  insertBufferSegment,
  trimBuffer,
} from '@/lib/audio/buffer-utils';
import {
  createCutCommand,
  createDeleteCommand,
  createPasteCommand,
  createTrimCommand,
} from '@/lib/history/commands/edit-command';

export function AudioEditor() {
  // Zoom and scroll state
  const [zoom, setZoom] = React.useState(1);
  const [scrollOffset, setScrollOffset] = React.useState(0);
  const [amplitudeScale, setAmplitudeScale] = React.useState(1);

  // Selection state
  const [selection, setSelection] = React.useState<Selection | null>(null);
  const [clipboard, setClipboard] = React.useState<ClipboardData | null>(null);

  const {
    loadFile,
    loadBuffer,
    clearFile,
    play,
    pause,
    stop,
    seek,
    setVolume,
    isPlaying,
    isPaused,
    currentTime,
    duration,
    volume,
    audioBuffer,
    fileName,
    isLoading,
    error,
    currentTimeFormatted,
    durationFormatted,
  } = useAudioPlayer();

  const { execute, undo, redo, clear: clearHistory, state: historyState } = useHistory(50);
  const { addToast } = useToast();

  const handleFileSelect = async (file: File) => {
    try {
      await loadFile(file);
      addToast({
        title: 'File loaded',
        description: `Successfully loaded ${file.name}`,
        variant: 'success',
        duration: 3000,
      });
    } catch (err) {
      addToast({
        title: 'Error loading file',
        description: err instanceof Error ? err.message : 'Unknown error',
        variant: 'error',
        duration: 5000,
      });
    }
  };

  const handleClear = () => {
    clearFile();
    setZoom(1);
    setScrollOffset(0);
    setAmplitudeScale(1);
    setSelection(null);
    setClipboard(null);
    clearHistory();
    addToast({
      title: 'Audio cleared',
      description: 'Audio file has been removed',
      variant: 'info',
      duration: 2000,
    });
  };

  // Edit operations
  const handleCut = () => {
    if (!selection || !audioBuffer) return;

    try {
      // Copy to clipboard
      const clipData = extractBufferSegment(audioBuffer, selection.start, selection.end);
      setClipboard({
        buffer: clipData,
        start: selection.start,
        end: selection.end,
        duration: selection.end - selection.start,
      });

      // Create and execute cut command
      const command = createCutCommand(audioBuffer, selection, (buffer) => {
        loadBuffer(buffer);
      });
      execute(command);

      setSelection(null);
      addToast({
        title: 'Cut',
        description: 'Selection cut to clipboard',
        variant: 'success',
        duration: 2000,
      });
    } catch (error) {
      addToast({
        title: 'Error',
        description: 'Failed to cut selection',
        variant: 'error',
        duration: 3000,
      });
    }
  };

  const handleCopy = () => {
    if (!selection || !audioBuffer) return;

    try {
      const clipData = extractBufferSegment(audioBuffer, selection.start, selection.end);
      setClipboard({
        buffer: clipData,
        start: selection.start,
        end: selection.end,
        duration: selection.end - selection.start,
      });

      addToast({
        title: 'Copied',
        description: 'Selection copied to clipboard',
        variant: 'success',
        duration: 2000,
      });
    } catch (error) {
      addToast({
        title: 'Error',
        description: 'Failed to copy selection',
        variant: 'error',
        duration: 3000,
      });
    }
  };

  const handlePaste = () => {
    if (!clipboard || !audioBuffer) return;

    try {
      const insertTime = currentTime;

      // Create and execute paste command
      const command = createPasteCommand(audioBuffer, clipboard.buffer, insertTime, (buffer) => {
        loadBuffer(buffer);
      });
      execute(command);

      addToast({
        title: 'Pasted',
        description: 'Clipboard pasted at current position',
        variant: 'success',
        duration: 2000,
      });
    } catch (error) {
      addToast({
        title: 'Error',
        description: 'Failed to paste clipboard',
        variant: 'error',
        duration: 3000,
      });
    }
  };

  const handleDelete = () => {
    if (!selection || !audioBuffer) return;

    try {
      // Create and execute delete command
      const command = createDeleteCommand(audioBuffer, selection, (buffer) => {
        loadBuffer(buffer);
      });
      execute(command);

      setSelection(null);
      addToast({
        title: 'Deleted',
        description: 'Selection deleted',
        variant: 'success',
        duration: 2000,
      });
    } catch (error) {
      addToast({
        title: 'Error',
        description: 'Failed to delete selection',
        variant: 'error',
        duration: 3000,
      });
    }
  };

  const handleTrim = () => {
    if (!selection || !audioBuffer) return;

    try {
      // Create and execute trim command
      const command = createTrimCommand(audioBuffer, selection, (buffer) => {
        loadBuffer(buffer);
      });
      execute(command);

      setSelection(null);
      addToast({
        title: 'Trimmed',
        description: 'Audio trimmed to selection',
        variant: 'success',
        duration: 2000,
      });
    } catch (error) {
      addToast({
        title: 'Error',
        description: 'Failed to trim audio',
        variant: 'error',
        duration: 3000,
      });
    }
  };

  const handleSelectAll = () => {
    if (!audioBuffer) return;
    setSelection({ start: 0, end: duration });
  };

  const handleClearSelection = () => {
    setSelection(null);
  };

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

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

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

  // Auto-adjust scroll when zoom changes
  React.useEffect(() => {
    if (!audioBuffer) return;

    // Reset scroll if zoomed out completely
    if (zoom === 1) {
      setScrollOffset(0);
    }
  }, [zoom, audioBuffer]);

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

      // Ctrl+Z: Undo
      if (e.ctrlKey && !e.shiftKey && e.key === 'z') {
        e.preventDefault();
        if (undo()) {
          addToast({
            title: 'Undo',
            description: 'Last action undone',
            variant: 'info',
            duration: 1500,
          });
        }
      }

      // Ctrl+Y or Ctrl+Shift+Z: Redo
      if ((e.ctrlKey && e.key === 'y') || (e.ctrlKey && e.shiftKey && e.key === 'z')) {
        e.preventDefault();
        if (redo()) {
          addToast({
            title: 'Redo',
            description: 'Last action redone',
            variant: 'info',
            duration: 1500,
          });
        }
      }

      // Ctrl+A: Select all
      if (e.ctrlKey && e.key === 'a') {
        e.preventDefault();
        handleSelectAll();
      }

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

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

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

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

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

    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [selection, clipboard, audioBuffer, currentTime, undo, redo, addToast]);

  // Show error toast
  React.useEffect(() => {
    if (error) {
      addToast({
        title: 'Error',
        description: error,
        variant: 'error',
        duration: 5000,
      });
    }
  }, [error, addToast]);

  return (
    <div className="space-y-6">
      {/* File Upload or Audio Info */}
      {!audioBuffer ? (
        <FileUpload onFileSelect={handleFileSelect} />
      ) : (
        <AudioInfo
          fileName={fileName || 'Unknown'}
          audioBuffer={audioBuffer}
          onClear={handleClear}
        />
      )}

      {/* Loading State */}
      {isLoading && (
        <Card>
          <CardContent className="p-8">
            <div className="flex flex-col items-center justify-center gap-3">
              <Loader2 className="h-8 w-8 animate-spin text-primary" />
              <p className="text-sm text-muted-foreground">Loading audio file...</p>
            </div>
          </CardContent>
        </Card>
      )}

      {/* Waveform and Controls */}
      {audioBuffer && !isLoading && (
        <>
          {/* Waveform */}
          <Card>
            <CardHeader>
              <CardTitle>Waveform</CardTitle>
            </CardHeader>
            <CardContent className="space-y-4">
              <Waveform
                audioBuffer={audioBuffer}
                currentTime={currentTime}
                duration={duration}
                onSeek={seek}
                height={150}
                zoom={zoom}
                scrollOffset={scrollOffset}
                amplitudeScale={amplitudeScale}
                selection={selection}
                onSelectionChange={setSelection}
              />

              {/* Horizontal scroll for zoomed waveform */}
              {zoom > 1 && (
                <div className="space-y-2">
                  <label className="text-sm font-medium text-foreground">
                    Scroll Position
                  </label>
                  <Slider
                    value={scrollOffset}
                    onChange={setScrollOffset}
                    min={0}
                    max={Math.max(0, (800 * zoom) - 800)}
                    step={1}
                  />
                </div>
              )}
            </CardContent>
          </Card>

          {/* Edit Controls */}
          <Card>
            <CardHeader>
              <CardTitle>Edit</CardTitle>
            </CardHeader>
            <CardContent>
              <EditControls
                selection={selection}
                hasClipboard={clipboard !== null}
                onCut={handleCut}
                onCopy={handleCopy}
                onPaste={handlePaste}
                onDelete={handleDelete}
                onTrim={handleTrim}
                onClearSelection={handleClearSelection}
              />
            </CardContent>
          </Card>

          {/* History Controls */}
          <Card>
            <CardHeader>
              <CardTitle>History</CardTitle>
            </CardHeader>
            <CardContent>
              <HistoryControls
                historyState={historyState}
                onUndo={undo}
                onRedo={redo}
                onClear={clearHistory}
              />
            </CardContent>
          </Card>

          {/* Zoom Controls */}
          <Card>
            <CardHeader>
              <CardTitle>Zoom & View</CardTitle>
            </CardHeader>
            <CardContent>
              <ZoomControls
                zoom={zoom}
                onZoomChange={setZoom}
                amplitudeScale={amplitudeScale}
                onAmplitudeScaleChange={setAmplitudeScale}
                onZoomIn={handleZoomIn}
                onZoomOut={handleZoomOut}
                onFitToView={handleFitToView}
              />
            </CardContent>
          </Card>

          {/* Playback Controls */}
          <Card>
            <CardHeader>
              <CardTitle>Playback</CardTitle>
            </CardHeader>
            <CardContent>
              <PlaybackControls
                isPlaying={isPlaying}
                isPaused={isPaused}
                currentTime={currentTime}
                duration={duration}
                volume={volume}
                onPlay={play}
                onPause={pause}
                onStop={stop}
                onSeek={seek}
                onVolumeChange={setVolume}
                currentTimeFormatted={currentTimeFormatted}
                durationFormatted={durationFormatted}
              />
            </CardContent>
          </Card>
        </>
      )}
    </div>
  );
}
