import { useState, useCallback } from 'react';
import { useRowSelection } from './useRowSelection';

export interface BatchOperationResult {
  successIds: React.Key[];
  failedIds: React.Key[];
  successCount: number;
  failedCount: number;
}

export interface UseBatchOperationsCoreConfig {
  /** Function to update a single item */
  updateFn?: (id: number, values: any) => Promise<void>;
  /** Function to delete a single item */
  deleteFn?: (id: number) => Promise<void>;
}

export interface UseBatchOperationsCoreResult {
  // Selection
  selectedRowKeys: React.Key[];
  setSelectedRowKeys: React.Dispatch<React.SetStateAction<React.Key[]>>;
  rowSelection: {
    selectedRowKeys: React.Key[];
    onChange: (keys: React.Key[]) => void;
  };
  hasSelected: boolean;
  clearSelection: () => void;

  // Core operations (no UI, no notifications)
  updateMany: (keys: React.Key[], values: any) => Promise<BatchOperationResult>;
  deleteMany: (keys: React.Key[]) => Promise<BatchOperationResult>;
  updateOne: (id: number, values: any) => Promise<void>;
  deleteOne: (id: number) => Promise<void>;

  // Loading states
  isUpdating: boolean;
  isDeleting: boolean;
}

/**
 * Core hook for batch operations - NO UI logic, NO notifications
 * Use this when you need full control over the UI and feedback.
 *
 * @example
 * const {
 *   selectedRowKeys,
 *   rowSelection,
 *   updateMany,
 *   deleteMany,
 *   isUpdating,
 *   isDeleting,
 * } = useBatchOperationsCore({
 *   updateFn: async (id, values) => {
 *     await api.patch(`/audit/${id}`, values);
 *   },
 *   deleteFn: async (id) => {
 *     await api.delete(`/audit/${id}`);
 *   },
 * });
 *
 * // Handle update with custom UI
 * const handleBatchUpdate = async (values) => {
 *   const result = await updateMany(selectedRowKeys, values);
 *
 *   // Custom notification
 *   if (result.failedCount > 0) {
 *     toast.error(`Failed to update ${result.failedCount} items`);
 *   } else {
 *     toast.success(`Updated ${result.successCount} items`);
 *   }
 *
 *   // Update selection to only keep failed items
 *   setSelectedRowKeys(result.failedIds);
 * };
 */
export function useBatchOperationsCore({
  updateFn,
  deleteFn,
}: UseBatchOperationsCoreConfig = {}): UseBatchOperationsCoreResult {
  const {
    selectedRowKeys,
    setSelectedRowKeys,
    rowSelection,
    hasSelected,
    clearSelection,
  } = useRowSelection();

  const [isUpdating, setIsUpdating] = useState(false);
  const [isDeleting, setIsDeleting] = useState(false);

  // Single item operations
  const updateOne = useCallback(
    async (id: number, values: any): Promise<void> => {
      if (!updateFn) {
        throw new Error('updateFn is not provided');
      }
      await updateFn(id, values);
    },
    [updateFn],
  );

  const deleteOne = useCallback(
    async (id: number): Promise<void> => {
      if (!deleteFn) {
        throw new Error('deleteFn is not provided');
      }
      await deleteFn(id);
    },
    [deleteFn],
  );

  // Batch operations - just execute and return results, no UI logic
  const updateMany = useCallback(
    async (keys: React.Key[], values: any): Promise<BatchOperationResult> => {
      if (!updateFn) {
        throw new Error('updateFn is not provided');
      }

      setIsUpdating(true);
      const successIds: React.Key[] = [];
      const failedIds: React.Key[] = [];

      for (const id of keys) {
        try {
          await updateFn(Number(id), values);
          successIds.push(id);
        } catch {
          failedIds.push(id);
        }
      }

      setIsUpdating(false);

      return {
        successIds,
        failedIds,
        successCount: successIds.length,
        failedCount: failedIds.length,
      };
    },
    [updateFn],
  );

  const deleteMany = useCallback(
    async (keys: React.Key[]): Promise<BatchOperationResult> => {
      if (!deleteFn) {
        throw new Error('deleteFn is not provided');
      }

      setIsDeleting(true);
      const successIds: React.Key[] = [];
      const failedIds: React.Key[] = [];

      for (const id of keys) {
        try {
          await deleteFn(Number(id));
          successIds.push(id);
        } catch {
          failedIds.push(id);
        }
      }

      setIsDeleting(false);

      return {
        successIds,
        failedIds,
        successCount: successIds.length,
        failedCount: failedIds.length,
      };
    },
    [deleteFn],
  );

  return {
    // Selection
    selectedRowKeys,
    setSelectedRowKeys,
    rowSelection,
    hasSelected,
    clearSelection,

    // Core operations
    updateMany,
    deleteMany,
    updateOne,
    deleteOne,

    // Loading states
    isUpdating,
    isDeleting,
  };
}
