/**
 * @file DocumentContext.tsx - Manages the currently selected document state within the work item processing view.
 * Tracks which document is displayed in the Syncfusion PDF viewer, its loading state, whether its content has changed, and the enabled/disabled state of document-level action buttons.
 */

import {
  createContext,
  type ReactNode,
  type RefObject,
  useContext,
  useRef,
  useState,
} from 'react';
import type { PdfViewerComponent } from '@syncfusion/ej2-react-pdfviewer';

/** Shape of the document context value provided to consumers. */
type DocumentContextType = {
  // DocumentId of selected document (displayed in PDF viewer)
  selectedDocumentId: number | undefined;
  setSelectedDocumentId: (documentId: number | undefined) => void;

  // DocumentId of previously selected document
  oldSelectedDocumentId: number | undefined;
  setOldSelectedDocumentId: (documentId: number | undefined) => void;

  // Syncfusion PDF viewer ref object
  pdfViewerRef: RefObject<PdfViewerComponent | null>;

  // Whether the page thumbnails are visible in the Syncfusion PDF Viewer
  thumbnailImagesVisible: boolean;
  setThumbnailImagesVisible: (visible: boolean) => void;

  // Whether a document is currently being loaded
  documentIsLoading: boolean;
  setDocumentIsLoading: (isLoading: boolean) => void;

  // Whether document action buttons should be disabled
  documentActionButtonsDisabled: boolean;
  setDocumentActionButtonsDisabled: (disabled: boolean) => void;

  // Whether the delete document button should be disabled
  // Separate from the rest of the document action buttons, to allow deleting corrupted documents
  deleteDocumentButtonDisabled: boolean;
  setDeleteDocumentButtonDisabled: (disabled: boolean) => void;

  // Whether the selected document content has changed in PDF viewer
  selectedDocumentContentHasChanged: boolean;
  setSelectedDocumentContentHasChanged: (changed: boolean) => void;
};

const DocumentContext = createContext<DocumentContextType | undefined>(
  undefined
);

/**
 * Provider component that exposes the currently selected document's state and the Syncfusion PDF viewer ref to the component tree.
 * Consumed primarily by the DocumentEditorPanel and the FolderSection to coordinate document selection, loading, and content change detection.
 *
 * @param children Child ReactNodes to be rendered within context
 */
export function DocumentProvider({ children }: { children: ReactNode }) {
  const [selectedDocumentId, setSelectedDocumentId] = useState<
    number | undefined
  >();
  const [oldSelectedDocumentId, setOldSelectedDocumentId] = useState<
    number | undefined
  >();
  const pdfViewerRef = useRef<PdfViewerComponent>(null);
  const [thumbnailImagesVisible, setThumbnailImagesVisible] = useState(false);
  const [documentIsLoading, setDocumentIsLoading] = useState(false);
  const [documentActionButtonsDisabled, setDocumentActionButtonsDisabled] =
    useState(true);
  const [deleteDocumentButtonDisabled, setDeleteDocumentButtonDisabled] =
    useState(true);
  const [
    selectedDocumentContentHasChanged,
    setSelectedDocumentContentHasChanged,
  ] = useState(false);

  const value = {
    selectedDocumentId,
    setSelectedDocumentId,
    oldSelectedDocumentId,
    setOldSelectedDocumentId,
    pdfViewerRef,
    thumbnailImagesVisible,
    setThumbnailImagesVisible,
    documentIsLoading,
    setDocumentIsLoading,
    documentActionButtonsDisabled,
    deleteDocumentButtonDisabled,
    setDeleteDocumentButtonDisabled,
    setDocumentActionButtonsDisabled,
    selectedDocumentContentHasChanged,
    setSelectedDocumentContentHasChanged,
  };

  return (
    <DocumentContext.Provider value={value}>
      {children}
    </DocumentContext.Provider>
  );
}

/**
 * Hook to access the DocumentContext. Must be called within a DocumentProvider.
 *
 * @returns The current document state and setter functions
 * @throws Error if called outside a DocumentProvider
 */
export function useDocument() {
  const context = useContext(DocumentContext);
  if (context === undefined) {
    throw new Error('useDocument must be used within a DocumentProvider');
  }
  return context;
}
