/**
 * PageNavigationContext
 *
 * Context provider for sharing page navigation state with child components.
 * Wraps the usePageNavigationState hook to provide state machine access
 * throughout the component tree without prop drilling.
 *
 * Usage:
 * ```tsx
 * // In parent (constructor.tsx or RuntimePresentation.tsx)
 * <PageNavigationProvider preloadCache={preloadOrchestrator} transitionSettings={transitionSettings}>
 *   <CanvasBackground />
 *   <Elements />
 * </PageNavigationProvider>
 *
 * // In child components
 * const { phase, onBackgroundReady, isSwitching } = usePageNavigationContext();
 * ```
 */

import React, { createContext, useContext, ReactNode, useMemo } from 'react';
import {
  usePageNavigationState,
  UsePageNavigationStateOptions,
  UsePageNavigationStateResult,
} from '../hooks/usePageNavigationState';

// ============================================================================
// Context
// ============================================================================

const PageNavigationContext =
  createContext<UsePageNavigationStateResult | null>(null);

// ============================================================================
// Provider
// ============================================================================

export interface PageNavigationProviderProps
  extends UsePageNavigationStateOptions {
  children: ReactNode;
}

/**
 * Provider component that wraps usePageNavigationState and exposes it via context.
 *
 * @example
 * ```tsx
 * <PageNavigationProvider
 *   preloadCache={preloadOrchestrator}
 *   transitionSettings={transitionSettings}
 * >
 *   <CanvasBackground ... />
 *   <PageElements ... />
 * </PageNavigationProvider>
 * ```
 */
export function PageNavigationProvider({
  children,
  ...options
}: PageNavigationProviderProps) {
  const navState = usePageNavigationState(options);

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

// ============================================================================
// Hooks
// ============================================================================

/**
 * Hook to access page navigation state from context.
 * Must be used within a PageNavigationProvider.
 *
 * @throws Error if used outside of PageNavigationProvider
 *
 * @example
 * ```tsx
 * function CanvasBackground() {
 *   const { onBackgroundReady, isSwitching, isNewBgReady } = usePageNavigationContext();
 *
 *   return (
 *     <img
 *       onLoad={onBackgroundReady}
 *       style={{ opacity: isNewBgReady ? 1 : 0 }}
 *     />
 *   );
 * }
 * ```
 */
export function usePageNavigationContext(): UsePageNavigationStateResult {
  const ctx = useContext(PageNavigationContext);
  if (!ctx) {
    throw new Error(
      'usePageNavigationContext must be used within a PageNavigationProvider',
    );
  }
  return ctx;
}

/**
 * Hook to optionally access page navigation state from context.
 * Returns null if used outside of PageNavigationProvider.
 * Useful for components that may be used both inside and outside the provider.
 *
 * @example
 * ```tsx
 * function FlexibleComponent() {
 *   const navState = usePageNavigationContextOptional();
 *
 *   if (navState) {
 *     // Inside provider - use navigation state
 *     return <div>Phase: {navState.phase}</div>;
 *   }
 *
 *   // Outside provider - render without navigation state
 *   return <div>Standalone mode</div>;
 * }
 * ```
 */
export function usePageNavigationContextOptional(): UsePageNavigationStateResult | null {
  return useContext(PageNavigationContext);
}

// ============================================================================
// Selector Hook
// ============================================================================

/**
 * Hook to select specific parts of the navigation state.
 * Helps with performance by allowing components to subscribe to only what they need.
 *
 * @example
 * ```tsx
 * // Only re-render when phase changes
 * const phase = usePageNavigationSelector(state => state.phase);
 *
 * // Get multiple values
 * const { isSwitching, isNewBgReady } = usePageNavigationSelector(state => ({
 *   isSwitching: state.isSwitching,
 *   isNewBgReady: state.isNewBgReady,
 * }));
 * ```
 */
export function usePageNavigationSelector<T>(
  selector: (state: UsePageNavigationStateResult) => T,
): T {
  const ctx = usePageNavigationContext();
  // Note: This doesn't prevent re-renders on its own since the context value changes.
  // For true selector optimization, consider using useSyncExternalStore or a state management library.
  // This is primarily for code organization/readability.
  return useMemo(() => selector(ctx), [ctx, selector]);
}

// ============================================================================
// Exports
// ============================================================================

export type { UsePageNavigationStateResult } from '../hooks/usePageNavigationState';
