import { useEffect } from 'react';
import { matchesKeyboardShortcut } from '../util/osUtil';
import { handleCopyOperation, handlePasteOperation } from '../util/copyPasteUtil';
import { saveProject } from '../util/saveUtil';
import { ConfigManager } from '../core/config/ConfigManager';
import { useProjectStore } from '../stores/projectStore';
import { selectAllNotesInActiveRegion } from '../util/selectionUtil';
import { KGCore } from '../core/KGCore';
import { KGMidiInput } from '../core/midi-input/KGMidiInput';
import { KGMidiRegion } from '../core/region/KGMidiRegion';
import { KGAudioTrack } from '../core/track/KGAudioTrack';
import { mergeSelectedMidiRegions, splitSelectedRegionAtPlayhead } from '../util/regionEditUtil';
import { showAlert } from '../util/dialogUtil';

/**
 * Global keyboard handler for copy/paste, undo/redo, play/pause, and save operations
 * Handles keyboard shortcuts defined in the configuration
 */
export const useGlobalKeyboardHandler = () => {
  const { undo, redo, setStatus, isPlaying, startPlaying, stopTransport, toggleLoop, projectName, savedProjectName, setSavedProjectName, setProjectName, isRecording, startRecording, stopRecording, activeRegionId, selectedRegionIds, setActiveRegionId, setShowPianoRoll, showPianoRoll, openMidiPianoRollWithSheetMusicView, openSpectrogramViewer, playheadPosition, refreshProjectState } = useProjectStore();
  const lastSelectedRegionId = selectedRegionIds[selectedRegionIds.length - 1] ?? null;

  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      // Skip if user is typing in an input field
      const target = event.target;
      if (target instanceof HTMLElement && (
        target.tagName === 'INPUT' || 
        target.tagName === 'TEXTAREA' || 
        target.contentEditable === 'true' ||
        target.hasAttribute('data-chatbox-input') ||
        target.closest('.chatbox-input')
      )) {
        return;
      }

      // Enhanced prevention for system shortcuts like Cmd+S/Ctrl+S
      const isCtrlOrCmd = event.ctrlKey || event.metaKey;
      const isSKey = event.key.toLowerCase() === 's';
      
      if (isCtrlOrCmd && isSKey) {
        // Use multiple prevention methods for better browser compatibility
        event.preventDefault();
        event.stopPropagation();
        event.stopImmediatePropagation();
        
        // Early return to handle save immediately
        try {
          saveProject(projectName, savedProjectName, setStatus, (finalName) => {
            setSavedProjectName(finalName);
            if (finalName !== projectName) setProjectName(finalName);
          });
        } catch (error) {
          console.error('Save failed:', error);
          setStatus('Save failed');
        }
        return false;
      }

      // Get keyboard shortcuts from config
      const configManager = ConfigManager.instance();
      if (!configManager.getIsInitialized()) {
        return;
      }

      const undoShortcut = configManager.get('hotkeys.main.undo') as string;
      const redoShortcut = configManager.get('hotkeys.main.redo') as string;
      const copyShortcut = configManager.get('hotkeys.main.copy') as string;
      const pasteShortcut = configManager.get('hotkeys.main.paste') as string;
      const selectAllShortcut = configManager.get('hotkeys.main.select_all') as string;
      const playShortcut = configManager.get('hotkeys.main.play') as string;
      const loopShortcut = configManager.get('hotkeys.main.loop') as string;
      const saveShortcut = configManager.get('hotkeys.main.save') as string;
      const recordShortcut = configManager.get('hotkeys.main.record') as string;
      const splitShortcut = configManager.get('hotkeys.main.split_region') as string;
      const mergeShortcut = configManager.get('hotkeys.main.merge_regions') as string;

      // Check for undo shortcut
      if (undoShortcut && matchesKeyboardShortcut(event, undoShortcut)) {
        event.preventDefault();
        try {
          undo();
          setStatus('Undo performed');
        } catch (error) {
          console.error('Undo failed:', error);
          setStatus('Undo failed');
        }
        return;
      }

      // Check for redo shortcut
      if (redoShortcut && matchesKeyboardShortcut(event, redoShortcut)) {
        event.preventDefault();
        try {
          redo();
          setStatus('Redo performed');
        } catch (error) {
          console.error('Redo failed:', error);
          setStatus('Redo failed');
        }
        return;
      }

      // Check for copy shortcut
      if (copyShortcut && matchesKeyboardShortcut(event, copyShortcut)) {
        event.preventDefault();
        const copied = handleCopyOperation();
        if (copied) {
          setStatus('Items copied to clipboard');
        } else {
          setStatus('No items selected to copy');
        }
        return;
      }

      // Check for paste shortcut
      if (pasteShortcut && matchesKeyboardShortcut(event, pasteShortcut)) {
        event.preventDefault();
        const pasted = handlePasteOperation();
        if (pasted) {
          setStatus('Items pasted from clipboard');
        } else {
          setStatus('Cannot paste - no valid clipboard content or context');
        }
        return;
      }

      // Check for select-all-notes shortcut (only when piano roll is open)
      if (selectAllShortcut && matchesKeyboardShortcut(event, selectAllShortcut)) {
        event.preventDefault();
        selectAllNotesInActiveRegion();
        return;
      }

      // Check for play/pause shortcut
      if (playShortcut && matchesKeyboardShortcut(event, playShortcut)) {
        event.preventDefault();
        try {
          if (!isPlaying) {
            startPlaying();
            setStatus('Playback started');
          } else {
            stopTransport();
            setStatus(isRecording ? 'Recording stopped — notes committed' : 'Playback stopped');
          }
        } catch (error) {
          console.error('Play/pause failed:', error);
          setStatus('Play/pause failed');
        }
        return;
      }

      // Check for loop toggle shortcut
      if (loopShortcut && matchesKeyboardShortcut(event, loopShortcut)) {
        event.preventDefault();
        try {
          toggleLoop();
          setStatus('Loop toggled');
        } catch (error) {
          console.error('Loop toggle failed:', error);
          setStatus('Loop toggle failed');
        }
        return;
      }

      // Check for record toggle shortcut
      if (recordShortcut && matchesKeyboardShortcut(event, recordShortcut)) {
        event.preventDefault();
        if (isRecording) {
          stopRecording();
          setStatus('Recording stopped');
          return;
        }
        const selectedTrack = useProjectStore.getState().tracks.find(track => track.getId().toString() === useProjectStore.getState().selectedTrackId) ?? null;
        if (selectedTrack instanceof KGAudioTrack) {
          startRecording();
          setStatus('Audio recording started...');
          return;
        }
        const candidateId = activeRegionId ?? lastSelectedRegionId;
        if (!candidateId) {
          setStatus('Select a MIDI region before recording');
          return;
        }
        const tracks = KGCore.instance().getCurrentProject().getTracks();
        let isMidi = false;
        for (const track of tracks) {
          const region = track.getRegions().find(r => r.getId() === candidateId);
          if (region) { isMidi = region instanceof KGMidiRegion; break; }
        }
        if (!isMidi) {
          setStatus('Select a MIDI region before recording');
          return;
        }
        if (KGMidiInput.instance().getConnectedInputCount() === 0) {
          setStatus('No MIDI device detected');
          return;
        }
        if (!activeRegionId) {
          setActiveRegionId(candidateId);
          setShowPianoRoll(true);
        }
        startRecording();
        setStatus('Recording started...');
        return;
      }

      if (splitShortcut && matchesKeyboardShortcut(event, splitShortcut)) {
        event.preventDefault();
        void splitSelectedRegionAtPlayhead({
          selectedRegionIds,
          playheadPosition,
          refreshProjectState,
        }).then(status => {
          if (status) {
            setStatus(status);
          }
        });
        return;
      }

      if (mergeShortcut && matchesKeyboardShortcut(event, mergeShortcut)) {
        event.preventDefault();
        void mergeSelectedMidiRegions({
          selectedRegionIds,
          refreshProjectState,
        }).then(status => {
          if (status) {
            setStatus(status);
          }
        });
        return;
      }

      // Check for edit/view shortcut (E) — open piano roll for MIDI, spectrogram for audio
      if (event.key.toLowerCase() === 'e' && !event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
        event.preventDefault();
        if (showPianoRoll) {
          setShowPianoRoll(false);
          return;
        }
        const candidateId = activeRegionId ?? lastSelectedRegionId;
        if (!candidateId) {
          void showAlert('Please select a region to open the editor.');
          return;
        }
        const tracks = KGCore.instance().getCurrentProject().getTracks();
        let foundMidi = false;
        let foundAudio = false;
        for (const track of tracks) {
          const region = track.getRegions().find(r => r.getId() === candidateId);
          if (region) {
            if (region instanceof KGMidiRegion) foundMidi = true;
            else foundAudio = true;
            break;
          }
        }
        if (foundMidi) {
          openMidiPianoRollWithSheetMusicView(candidateId, false);
        } else if (foundAudio) {
          openSpectrogramViewer(candidateId);
        }
        return;
      }

      // Check for sheet music shortcut (N) — open piano roll for MIDI in sheet music view
      if (event.key.toLowerCase() === 'n' && !event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
        event.preventDefault();
        const candidateId = activeRegionId ?? lastSelectedRegionId;
        if (!candidateId) {
          void showAlert('Please select a region to open the editor.');
          return;
        }
        const tracks = KGCore.instance().getCurrentProject().getTracks();
        let foundMidi = false;
        let foundAudio = false;
        for (const track of tracks) {
          const region = track.getRegions().find(r => r.getId() === candidateId);
          if (region) {
            if (region instanceof KGMidiRegion) foundMidi = true;
            else foundAudio = true;
            break;
          }
        }
        if (foundMidi) {
          openMidiPianoRollWithSheetMusicView(candidateId, true);
        } else if (foundAudio) {
          void showAlert('Sheet music view is only available for MIDI regions.');
        }
        return;
      }

      // Check for save shortcut
      if (saveShortcut && matchesKeyboardShortcut(event, saveShortcut)) {
        event.preventDefault();
        try {
          saveProject(projectName, savedProjectName, setStatus, (finalName) => {
            setSavedProjectName(finalName);
            if (finalName !== projectName) setProjectName(finalName);
          });
        } catch (error) {
          console.error('Save failed:', error);
          setStatus('Save failed');
        }
        return;
      }
    };

    // Add global event listener with capture for earlier interception
    document.addEventListener('keydown', handleKeyDown, { capture: true });

    // Cleanup on unmount
    return () => {
      document.removeEventListener('keydown', handleKeyDown, { capture: true });
    };
  }, [
    undo,
    redo,
    setStatus,
    isPlaying,
    startPlaying,
    stopTransport,
    toggleLoop,
    projectName,
    savedProjectName,
    setSavedProjectName,
    setProjectName,
    isRecording,
    startRecording,
    stopRecording,
    activeRegionId,
    selectedRegionIds,
    lastSelectedRegionId,
    setActiveRegionId,
    setShowPianoRoll,
    showPianoRoll,
    openMidiPianoRollWithSheetMusicView,
    openSpectrogramViewer,
    playheadPosition,
    refreshProjectState,
  ]); // Include dependencies for store actions
};
