/**
 * useMutationRetry Hook
 * Provides retry functionality for mutation errors
 *
 * Action 3.4.1.3: Implement retry for failed mutations
 */

import { useState, useCallback, useRef } from 'react';

export interface MutationRetryState {
  retryCount: number;
  canRetry: boolean;
  lastError: Error | null;
}

export interface MutationRetryOptions {
  maxRetries?: number;
  onRetry?: (retryCount: number) => void;
}

const DEFAULT_MAX_RETRIES = 3;

/**
 * Hook for managing mutation retry state and logic
 * @param options - Retry configuration options
 * @returns Retry state and handlers
 */
export function useMutationRetry(options: MutationRetryOptions = {}) {
  const { maxRetries = DEFAULT_MAX_RETRIES, onRetry } = options;
  const [retryState, setRetryState] = useState<MutationRetryState>({
    retryCount: 0,
    canRetry: true,
    lastError: null,
  });

  // Store the mutation function and variables for retry
  const mutationRef = useRef<{
    fn: () => Promise<void>;
    variables?: unknown;
  } | null>(null);

  /**
   * Store mutation function and variables for potential retry
   */
  const storeMutation = useCallback(
    (fn: () => Promise<void>, variables?: unknown) => {
      mutationRef.current = { fn, variables };
      setRetryState((prev) => ({
        ...prev,
        canRetry: prev.retryCount < maxRetries,
      }));
    },
    [maxRetries],
  );

  /**
   * Handle mutation error - store error and check if retry is possible
   */
  const handleMutationError = useCallback(
    (error: Error) => {
      setRetryState((prev) => ({
        retryCount: prev.retryCount,
        canRetry: prev.retryCount < maxRetries,
        lastError: error,
      }));
    },
    [maxRetries],
  );

  /**
   * Retry the stored mutation
   */
  const retryMutation = useCallback(async () => {
    if (!mutationRef.current) {
      return;
    }

    const currentRetryCount = retryState.retryCount;
    if (currentRetryCount >= maxRetries) {
      return;
    }

    setRetryState((prev) => ({
      ...prev,
      retryCount: prev.retryCount + 1,
      canRetry: prev.retryCount + 1 < maxRetries,
    }));

    if (onRetry) {
      onRetry(currentRetryCount + 1);
    }

    try {
      await mutationRef.current.fn();
      // Reset retry state on success
      setRetryState({
        retryCount: 0,
        canRetry: true,
        lastError: null,
      });
      mutationRef.current = null;
    } catch (error) {
      handleMutationError(
        error instanceof Error ? error : new Error(String(error)),
      );
    }
  }, [retryState.retryCount, maxRetries, onRetry, handleMutationError]);

  /**
   * Reset retry state (e.g., on successful mutation or manual reset)
   */
  const resetRetry = useCallback(() => {
    setRetryState({
      retryCount: 0,
      canRetry: true,
      lastError: null,
    });
    mutationRef.current = null;
  }, []);

  return {
    retryState,
    storeMutation,
    handleMutationError,
    retryMutation,
    resetRetry,
  };
}
