/**
 * @file WorkItemContext.tsx - Manages all data associated with the currently open work item in the processing view.
 * This includes the selected process, queue, the work item itself, its folder fields, action buttons, allowed document templates, documents, notes, and tracking records.
 * The context acts as a centralized data store that is populated when a work item is opened and consumed by the various panels and sections of the processing page.
 */

import type { Process } from '../api/process.ts';
import type { Queue } from '../api/queue.ts';
import type { WorkItem } from '../api/workItem.ts';
import type { FolderField } from '../api/folderField.ts';
import type { Button } from '../api/buttons.ts';
import type { DocumentTemplate } from '../api/documentTemplate.ts';
import type { Document } from '../api/document.ts';
import type { Note } from '../api/note.ts';
import type { TrackingRecord } from '../api/trackingRecord.ts';
import { createContext, type ReactNode, useContext, useState } from 'react';

/** Shape of the work item context value provided to consumers. */
type WorkItemContextType = {
  // Process object for currently selected process
  process: Process | undefined;
  setProcess: (process: Process | undefined) => void;

  // Queue object for currently selected queue
  queue: Queue | undefined;
  setQueue: (queue: Queue | undefined) => void;

  // WorkItem object for currently selected work item
  workItem: WorkItem | undefined;
  setWorkItem: (workItem: WorkItem | undefined) => void;

  // FolderField object array for work item folder fields
  folderFields: FolderField[];
  setFolderFields: (folderFields: FolderField[]) => void;

  // Button object array for work item buttons
  buttons: Button[];
  setButtons: (buttons: Button[]) => void;

  // DocumentTemplate object array for process allowed document templates
  documentTemplates: DocumentTemplate[];
  setDocumentTemplates: (documentTemplates: DocumentTemplate[]) => void;

  // Document object array for work item documents
  // useState setter
  documents: Document[];
  setDocuments: (documents: Document[]) => void;

  // Note object array for work item and document notes
  // useState setter
  notes: Note[];
  setNotes: (notes: Note[]) => void;

  // TrackingRecord object array for work item tracking records
  trackingRecords: TrackingRecord[] | undefined;
  setTrackingRecords: (trackingRecords: TrackingRecord[] | undefined) => void;
};

const WorkItemContext = createContext<WorkItemContextType | undefined>(
  undefined
);

/**
 * Provider component that holds all data related to the currently open work item.
 * Data is populated by the Processing page when a work item is opened and consumed by the DetailsFolderPanel, FieldsNotesTrackingPanel, and DocumentEditorPanel, as well as related components.
 *
 * @param children Child ReactNodes to be rendered within context
 */
export function WorkItemProvider({ children }: { children: ReactNode }) {
  const [process, setProcess] = useState<Process>();
  const [queue, setQueue] = useState<Queue>();
  const [workItem, setWorkItem] = useState<WorkItem>();
  const [folderFields, setFolderFields] = useState<FolderField[]>([]);
  const [buttons, setButtons] = useState<Button[]>([]);
  const [documentTemplates, setDocumentTemplates] = useState<
    DocumentTemplate[]
  >([]);
  const [documents, setDocuments] = useState<Document[]>([]);
  const [notes, setNotes] = useState<Note[]>([]);
  const [trackingRecords, setTrackingRecords] = useState<
    TrackingRecord[] | undefined
  >([]);

  const value = {
    process,
    setProcess,
    queue,
    setQueue,
    workItem,
    setWorkItem,
    folderFields,
    setFolderFields,
    buttons,
    setButtons,
    documentTemplates,
    setDocumentTemplates,
    documents,
    setDocuments,
    notes,
    setNotes,
    trackingRecords,
    setTrackingRecords,
  };

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

/**
 * Hook to access the WorkItemContext. Must be called within a WorkItemProvider.
 *
 * @returns The current work item data and setter functions
 * @throws Error if called outside a WorkItemProvider
 */
export function useWorkItem() {
  const context = useContext(WorkItemContext);
  if (context === undefined) {
    throw new Error('useWorkItem must be used within a WorkItemProvider');
  }
  return context;
}
