/**
 * @file useDocumentEditorHotkeys.ts - Registers keyboard shortcuts for the DocumentEditorPanel component.
 */

import { type RefObject } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { assembleHotKeyString } from '../../utils/hotKeys.ts';
import { Key } from 'ts-key-enum';
import { PdfViewerComponent } from '@syncfusion/ej2-react-pdfviewer';
import {
  deletePageAtIndex,
  duplicatePageAtIndex,
  movePageAtIndex,
  type PageLevelActionsProps,
  revertPageAtIndex,
  rotatePageAtIndex,
  splitDocumentAtIndex,
} from '../../utils/pageLevelActions.ts';
import {
  type RetrieveAndSaveDocumentProps,
  saveDocument,
} from '../../utils/retrieveAndSaveDocument.ts';
import { saveDocumentButtonExists } from '../../utils/pdfViewerInjections.tsx';
import { type Document } from '../../api/document.ts';
import * as UAParser from 'ua-parser-js';
import i18next from 'i18next';

/** Props required by {@link useDocumentEditorHotkeys}. */
interface UseDocumentEditorHotkeysProps {
  /** Reference to the Syncfusion PDF Viewer component instance */
  pdfViewerRef: RefObject<PdfViewerComponent>;

  /** Whether thumbnail images are currently visible (gates page-level actions) */
  thumbnailImagesVisible: boolean;

  /** List of documents in the current folder */
  documents: Document[];

  /** Props forwarded to the save-document utility */
  retrieveAndSaveDocumentProps: RetrieveAndSaveDocumentProps;

  /** Props forwarded to page-level action utilities */
  pageLevelActionProps: PageLevelActionsProps;

  /** Detected operating system, used to adjust modifier keys for macOS */
  os: UAParser.IOS;
}

/**
 * Registers hotkeys used in the DocumentEditorPanel component.
 */
export const useDocumentEditorHotkeys = ({
  pdfViewerRef,
  thumbnailImagesVisible,
  documents,
  retrieveAndSaveDocumentProps,
  pageLevelActionProps,
  os,
}: UseDocumentEditorHotkeysProps) => {
  const tKey = 'hooks.hotkeys.document_editor';

  // Syncfusion uses 1-based page numbers; convert to 0-based index for page-level actions
  const getCurrentPageIndex = () => {
    return (pdfViewerRef.current?.currentPageNumber as number) - 1;
  };

  // Save document hotkey
  useHotkeys(
    assembleHotKeyString([Key.Control], ['s']),
    () => {
      if (saveDocumentButtonExists()) {
        saveDocument(retrieveAndSaveDocumentProps);
      }
    },
    {
      preventDefault: true,
      description: `[doc]${i18next.t(tKey + '.save_document')}`,
    }
  );

  // Rotate page left hotkey
  useHotkeys(
    assembleHotKeyString([Key.Control, Key.Alt], [Key.ArrowLeft]),
    () => {
      if (thumbnailImagesVisible) {
        rotatePageAtIndex(pageLevelActionProps, getCurrentPageIndex(), -90);
      }
    },
    {
      preventDefault: true,
      description: `[page]${i18next.t(tKey + '.rotate_page_left')}`,
    }
  );

  // Rotate page right hotkey
  useHotkeys(
    assembleHotKeyString([Key.Control, Key.Alt], [Key.ArrowRight]),
    () => {
      if (thumbnailImagesVisible) {
        rotatePageAtIndex(pageLevelActionProps, getCurrentPageIndex(), 90);
      }
    },
    {
      preventDefault: true,
      description: `[page]${i18next.t(tKey + '.rotate_page_right')}`,
    }
  );

  // Move page up hotkey
  useHotkeys(
    assembleHotKeyString([Key.Control, Key.Alt], [Key.ArrowUp]),
    () => {
      const index = getCurrentPageIndex();
      if (index > 0 && thumbnailImagesVisible) {
        movePageAtIndex(pageLevelActionProps, index, true);
      }
    },
    {
      preventDefault: true,
      description: `[page]${i18next.t(tKey + '.move_page_up')}`,
    }
  );

  // Move page down hotkey
  useHotkeys(
    assembleHotKeyString([Key.Control, Key.Alt], [Key.ArrowDown]),
    () => {
      const index = getCurrentPageIndex();
      if (index <= documents.length && thumbnailImagesVisible) {
        movePageAtIndex(pageLevelActionProps, index, false);
      }
    },
    {
      preventDefault: true,
      description: `[page]${i18next.t(tKey + '.move_page_down')}`,
    }
  );

  // Duplicate page hotkey
  useHotkeys(
    assembleHotKeyString([Key.Control, Key.Alt], ['d']),
    () => {
      if (thumbnailImagesVisible) {
        duplicatePageAtIndex(pageLevelActionProps, getCurrentPageIndex());
      }
    },
    {
      preventDefault: true,
      description: `[page]${i18next.t(tKey + '.duplicate_page')}`,
    }
  );

  // Split document hotkey
  useHotkeys(
    assembleHotKeyString([Key.Control, Key.Alt], ['s']),
    () => {
      const index = getCurrentPageIndex();
      if (index > 0 && thumbnailImagesVisible) {
        splitDocumentAtIndex(pageLevelActionProps, index);
      }
    },
    {
      preventDefault: true,
      description: `[page]${i18next.t(tKey + '.split_document')}`,
    }
  );

  // Revert page hotkey
  useHotkeys(
    assembleHotKeyString([Key.Control, Key.Alt], ['r']),
    () => {
      if (thumbnailImagesVisible) {
        revertPageAtIndex(pageLevelActionProps, getCurrentPageIndex());
      }
    },
    {
      preventDefault: true,
      description: `[page]${i18next.t(tKey + '.revert_page')}`,
    }
  );

  // Delete page hotkey
  useHotkeys(
    assembleHotKeyString([Key.Control, Key.Alt], [Key.Backspace]),
    () => {
      if (thumbnailImagesVisible) {
        deletePageAtIndex(pageLevelActionProps, getCurrentPageIndex());
      }
    },
    {
      preventDefault: true,
      description: `[page]${i18next.t(tKey + '.delete_page')}`,
    }
  );

  // Navigate to previous page hotkey
  useHotkeys(
    assembleHotKeyString(
      os.is('macOS') ? [Key.Control, Key.Meta] : [Key.Control],
      [Key.ArrowUp]
    ),
    () => pdfViewerRef.current?.navigation.goToPreviousPage(),
    {
      preventDefault: true,
      description: `[nav]${i18next.t(tKey + '.navigate_previous_page')}`,
    }
  );

  // Navigate to next page hotkey
  useHotkeys(
    assembleHotKeyString(
      os.is('macOS') ? [Key.Control, Key.Meta] : [Key.Control],
      [Key.ArrowDown]
    ),
    () => pdfViewerRef.current?.navigation.goToNextPage(),
    {
      preventDefault: true,
      description: `[nav]${i18next.t(tKey + '.navigate_next_page')}`,
    }
  );

  // Zoom in hotkey
  useHotkeys(
    assembleHotKeyString([Key.Control], ['i']),
    () => pdfViewerRef.current?.magnification.zoomIn(),
    {
      preventDefault: true,
      description: `[nav]${i18next.t(tKey + '.zoom_in')}`,
    }
  );

  // Zoom out hotkey
  useHotkeys(
    assembleHotKeyString([Key.Control], ['o']),
    () => pdfViewerRef.current?.magnification.zoomOut(),
    {
      preventDefault: true,
      description: `[nav]${i18next.t(tKey + '.zoom_out')}`,
    }
  );
};
