/**
 * useConfirmation Hook
 *
 * A composable hook for showing async confirmation dialogs.
 * Returns a promise that resolves to true (confirmed) or false (cancelled).
 *
 * This hook requires the ConfirmationProvider to be mounted in your app.
 *
 * @example
 * ```tsx
 * // In your app root:
 * import { ConfirmationProvider } from '@/prism/headless';
 *
 * function App() {
 *   return (
 *     <ConfirmationProvider>
 *       <YourApp />
 *     </ConfirmationProvider>
 *   );
 * }
 *
 * // In your component:
 * import { useConfirmation } from '@/prism/headless';
 *
 * function DeleteButton({ onDelete }: { onDelete: () => Promise<void> }) {
 *   const confirmation = useConfirmation();
 *
 *   const handleDelete = async () => {
 *     const confirmed = await confirmation.confirm({
 *       title: 'Delete Item',
 *       message: 'Are you sure you want to delete this item? This action cannot be undone.',
 *       variant: 'danger',
 *       confirmText: 'Delete',
 *       cancelText: 'Cancel',
 *     });
 *
 *     if (confirmed) {
 *       await onDelete();
 *     }
 *   };
 *
 *   return <button onClick={handleDelete}>Delete</button>;
 * }
 * ```
 *
 * ⚠️ AUTO-GENERATED BY PRISM - DO NOT EDIT
 */

'use client';

import React, {
  createContext,
  useContext,
  useState,
  useCallback,
  useRef,
  type ReactNode,
} from 'react';
import type {
  ConfirmationOptions,
  ConfirmationState,
  UseConfirmationResult,
} from '../types';

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

interface ConfirmationContextValue {
  state: ConfirmationState;
  confirm: (options: ConfirmationOptions) => Promise<boolean>;
  cancel: () => void;
  handleConfirm: () => void;
  handleCancel: () => void;
  setLoading: (loading: boolean) => void;
}

const ConfirmationContext = createContext<ConfirmationContextValue | null>(null);

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

interface ConfirmationProviderProps {
  children: ReactNode;
  /**
   * Custom dialog component. If not provided, you must render your own dialog
   * based on the state from useConfirmationState().
   */
  DialogComponent?: React.ComponentType<ConfirmationDialogProps>;
}

export interface ConfirmationDialogProps {
  isOpen: boolean;
  isLoading: boolean;
  options: ConfirmationOptions | null;
  onConfirm: () => void;
  onCancel: () => void;
}

/**
 * Provider for confirmation dialogs.
 * Must be mounted at the root of your app.
 */
export function ConfirmationProvider({
  children,
  DialogComponent,
}: ConfirmationProviderProps): JSX.Element {
  const [state, setState] = useState<ConfirmationState>({
    isOpen: false,
    isLoading: false,
    options: null,
  });

  // Store resolve function to call when user responds
  const resolveRef = useRef<((value: boolean) => void) | null>(null);

  const confirm = useCallback((options: ConfirmationOptions): Promise<boolean> => {
    return new Promise((resolve) => {
      resolveRef.current = resolve;
      setState({
        isOpen: true,
        isLoading: false,
        options,
      });
    });
  }, []);

  const handleConfirm = useCallback(() => {
    resolveRef.current?.(true);
    resolveRef.current = null;
    setState((prev) => ({
      ...prev,
      isOpen: false,
      isLoading: false,
    }));
  }, []);

  const handleCancel = useCallback(() => {
    resolveRef.current?.(false);
    resolveRef.current = null;
    setState((prev) => ({
      ...prev,
      isOpen: false,
      isLoading: false,
    }));
  }, []);

  const cancel = useCallback(() => {
    handleCancel();
  }, [handleCancel]);

  const setLoading = useCallback((loading: boolean) => {
    setState((prev) => ({ ...prev, isLoading: loading }));
  }, []);

  const value: ConfirmationContextValue = {
    state,
    confirm,
    cancel,
    handleConfirm,
    handleCancel,
    setLoading,
  };

  return (
    <ConfirmationContext.Provider value={value}>
      {children}
      {DialogComponent && (
        <DialogComponent
          isOpen={state.isOpen}
          isLoading={state.isLoading}
          options={state.options}
          onConfirm={handleConfirm}
          onCancel={handleCancel}
        />
      )}
    </ConfirmationContext.Provider>
  );
}

// ============================================================================
// Hook
// ============================================================================

/**
 * Hook for showing confirmation dialogs.
 * Must be used within a ConfirmationProvider.
 *
 * @returns Confirmation state and actions
 */
export function useConfirmation(): UseConfirmationResult {
  const context = useContext(ConfirmationContext);

  if (!context) {
    throw new Error('useConfirmation must be used within a ConfirmationProvider');
  }

  return {
    state: context.state,
    confirm: context.confirm,
    cancel: context.cancel,
  };
}

/**
 * Hook for accessing the full confirmation state (for building custom dialogs).
 * Must be used within a ConfirmationProvider.
 *
 * @returns Full confirmation context value
 */
export function useConfirmationState(): ConfirmationContextValue {
  const context = useContext(ConfirmationContext);

  if (!context) {
    throw new Error('useConfirmationState must be used within a ConfirmationProvider');
  }

  return context;
}

export default useConfirmation;
