/**
 * @file ProcessingUIContext.tsx - Manages UI-level state for the work item processing view.
 * This includes the currently selected folder tree node, unsaved changes detection, modal visibility (unsaved changes and close work item), auto-save coordination, navigation blocking via useSmartBlocker, and responsive mobile detection.
 */

import type { TreeNode } from '../components/Processing/DetailsFolderPanel/sections/FolderSection/FolderTree.tsx';
import {
  createContext,
  type ReactNode,
  type RefObject,
  useContext,
  useEffect,
  useRef,
  useState,
} from 'react';
import { useMediaQuery } from 'react-responsive';
import { breakpoints } from '../utils/bootstrapBreakpoints.ts';
import { type Blocker, type NavigateOptions } from 'react-router-dom';
import { useSmartBlocker } from '../hooks/useSmartBlocker.ts';

/** Shape of the processing UI context value provided to consumers. */
type ProcessingUIContextType = {
  // The selected FolderTree node used in the Fields/Notes/Tracking panel
  selectedNode: TreeNode | undefined;
  setSelectedNode: (node: TreeNode) => void;

  // Whether the selected FolderTree node's fields have changed
  selectedNodeFieldsHaveChanged: boolean;
  setSelectedNodeFieldsHaveChanged: (changed: boolean) => void;

  // Whether the "Unsaved Changes" modal is shown
  unsavedChangesModalShown: boolean;
  setUnsavedChangesModalShown: (shown: boolean) => void;

  // The new selected FolderTree node after changes to fields are discarded
  newNodeAfterChangesDiscarded: TreeNode | undefined;
  setNewNodeAfterChangesDiscarded: (node: TreeNode | undefined) => void;

  // Functions used in the "Unsaved Changes" modal
  showUnsavedChangesModal: (newNode: TreeNode) => void;
  hideUnsavedChangesModal: () => void;
  discardChanges: () => void;

  // Whether the "Close Work Item" modal is shown
  closeWorkItemModalShown: boolean;
  setCloseWorkItemModalShown: (shown: boolean) => void;

  // Functions used in the "Close Work Item" modal
  showCloseWorkItemModal: () => void;
  hideCloseWorkItemModal: (actionTaken?: boolean) => void;

  // Whether the work item is ready to be saved
  saveWorkItem: boolean;
  setSaveWorkItem: (save: boolean) => void;

  // Next node to be selected in FolderTree
  // Used when auto-saving
  autoSavingNextNode: TreeNode | undefined;
  setAutoSavingNextNode: (nextNode: TreeNode | undefined) => void;

  // Whether the work item is ready to be closed
  closeWorkItem: boolean;
  setCloseWorkItem: (close: boolean) => void;

  // Work item close button ref object
  closeButtonRef: RefObject<HTMLButtonElement | null>;

  // useSmartBlocker state
  blocker: Blocker;
  safeNavigate: (to: string, options?: NavigateOptions) => void;

  // Whether the work item is successfully closed
  workItemClosed: boolean;
  setWorkItemClosed: (closed: boolean) => void;

  // Whether the device using the processing UI is a mobile screen size
  isMobile: boolean;
};

const ProcessingUIContext = createContext<ProcessingUIContextType | undefined>(
  undefined
);

/**
 * Provider component that manages all transient UI state for the processing view, including folder tree selection, unsaved changes and close work item modals, auto-save coordination, navigation blocking, and mobile detection.
 *
 * @param children Child ReactNodes to be rendered within context
 */
export function ProcessingUIProvider({ children }: { children: ReactNode }) {
  const [selectedNode, setSelectedNode] = useState<TreeNode>();
  const [selectedNodeFieldsHaveChanged, setSelectedNodeFieldsHaveChanged] =
    useState(false);
  const [unsavedChangesModalShown, setUnsavedChangesModalShown] =
    useState(false);
  const [newNodeAfterChangesDiscarded, setNewNodeAfterChangesDiscarded] =
    useState<TreeNode>();
  const [closeWorkItemModalShown, setCloseWorkItemModalShown] = useState(false);
  const [saveWorkItem, setSaveWorkItem] = useState(false);
  const [autoSavingNextNode, setAutoSavingNextNode] = useState<TreeNode>();
  const [closeWorkItem, setCloseWorkItem] = useState(false);
  const closeButtonRef = useRef<HTMLButtonElement | null>(null);
  const [workItemClosed, setWorkItemClosed] = useState(false);

  /**
   * Shows the "Unsaved Changes" modal.
   *
   * @param newNode New TreeNode to be selected after changes are discarded
   */
  const showUnsavedChangesModal = (newNode: TreeNode) => {
    setNewNodeAfterChangesDiscarded(newNode);
    setUnsavedChangesModalShown(true);
  };

  /**
   * Hides the "Unsaved Changes" modal.
   */
  const hideUnsavedChangesModal = () => {
    setUnsavedChangesModalShown(false);
  };

  /**
   * Discards the changes to the currently-selected FolderTree node.
   */
  const discardChanges = () => {
    if (newNodeAfterChangesDiscarded) {
      setSelectedNode(newNodeAfterChangesDiscarded);
      setSelectedNodeFieldsHaveChanged(false);
      hideUnsavedChangesModal();
    }
  };

  /**
   * Shows the "Close Work Item" modal.
   */
  const showCloseWorkItemModal = () => {
    setSaveWorkItem(false);
    setCloseWorkItem(false);
    setCloseWorkItemModalShown(true);
  };

  /**
   * Hides the "Close Work Item" modal.
   *
   * @param actionTaken Whether a save/discard action is being taken when hiding the modal
   */
  const hideCloseWorkItemModal = (actionTaken?: boolean) => {
    if (!actionTaken && blocker.state === 'blocked') {
      blocker.reset();
    }
    setCloseWorkItemModalShown(false);
  };

  // Block navigation away from the processing page when a node is selected
  // When the blocker activates, programmatically click the close button so the normal close work item flow runs
  const { blocker, safeNavigate } = useSmartBlocker(selectedNode !== undefined);
  useEffect(() => {
    if (blocker.state === 'blocked') {
      // Trigger work item close button to initiate the save/discard flow
      closeButtonRef.current?.click();
    }
  }, [blocker.state]);

  // Responsive breakpoint: treat screens below xxl as mobile layout
  const isMobile = useMediaQuery({ maxWidth: breakpoints.xxl - 1 });

  const value = {
    selectedNode,
    setSelectedNode,
    selectedNodeFieldsHaveChanged,
    setSelectedNodeFieldsHaveChanged,
    unsavedChangesModalShown,
    setUnsavedChangesModalShown,
    newNodeAfterChangesDiscarded,
    setNewNodeAfterChangesDiscarded,
    showUnsavedChangesModal,
    hideUnsavedChangesModal,
    discardChanges,
    closeWorkItemModalShown,
    setCloseWorkItemModalShown,
    showCloseWorkItemModal,
    hideCloseWorkItemModal,
    saveWorkItem,
    setSaveWorkItem,
    autoSavingNextNode,
    setAutoSavingNextNode,
    closeWorkItem,
    setCloseWorkItem,
    closeButtonRef,
    blocker,
    safeNavigate,
    workItemClosed,
    setWorkItemClosed,
    isMobile,
  };

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

/**
 * Hook to access the ProcessingUIContext. Must be called within a ProcessingUIProvider.
 *
 * @returns The current processing UI state and control functions
 * @throws Error if called outside a ProcessingUIProvider
 */
export function useProcessingUI() {
  const context = useContext(ProcessingUIContext);
  if (context === undefined) {
    throw new Error(
      'useProcessingUI must be used within a ProcessingUIProvider'
    );
  }
  return context;
}
