// src/hooks/useShoppingLists.tsx
import { useState, useCallback, useEffect, useMemo } from 'react';
import { useAuth } from '../hooks/useAuth';
import { useUserData } from '../hooks/useUserData';
import { useApi } from './useApi';
import * as apiClient from '../services/apiClient';
import type { ShoppingList, ShoppingListItem } from '../types';

/**
 * A custom hook to manage all state and logic related to shopping lists.
 * It encapsulates API calls and state updates for creating, deleting, and modifying lists and their items.
 */
const useShoppingListsHook = () => {
  const { user } = useAuth();
  // We get the lists and the global setter from the DataContext.
  const { shoppingLists, setShoppingLists } = useUserData();
  
  const [activeListId, setActiveListId] = useState<number | null>(null);

  // API hooks for shopping list operations
  const { execute: createListApi, error: createError, loading: isCreatingList } = useApi<ShoppingList, [string]>(
    (name) => apiClient.createShoppingList(name)
  );
  const { execute: deleteListApi, error: deleteError, loading: isDeletingList } = useApi<null, [number]>(
    (listId) => apiClient.deleteShoppingList(listId)
  );
  const { execute: addItemApi, error: addItemError, loading: isAddingItem } = useApi<ShoppingListItem, [number, { masterItemId?: number, customItemName?: string }]>(
    (listId, item) => apiClient.addShoppingListItem(listId, item)
  );
  const { execute: updateItemApi, error: updateItemError, loading: isUpdatingItem } = useApi<ShoppingListItem, [number, Partial<ShoppingListItem>]>(
    (itemId, updates) => apiClient.updateShoppingListItem(itemId, updates)
  );
  const { execute: removeItemApi, error: removeItemError, loading: isRemovingItem } = useApi<null, [number]>(
    (itemId) => apiClient.removeShoppingListItem(itemId)
  );

  // Consolidate errors from all API hooks into a single displayable error.
  const error = useMemo(() => {
    const firstError = createError || deleteError || addItemError || updateItemError || removeItemError;
    return firstError ? firstError.message : null;
  }, [createError, deleteError, addItemError, updateItemError, removeItemError]);

  // Effect to select the first list as active when lists are loaded or the user changes.
  useEffect(() => {
    if (user && shoppingLists.length > 0 && !shoppingLists.some(l => l.shopping_list_id === activeListId)) {
      setActiveListId(shoppingLists[0].shopping_list_id);
    } else if (!user || shoppingLists.length === 0) {
      setActiveListId(null);
    }
  }, [shoppingLists, user, activeListId]);

  const createList = useCallback(async (name: string) => {
    if (!user) return;
    const newList = await createListApi(name);
    if (newList) {
      setShoppingLists(prev => [...prev, newList]);
    }
  }, [user, setShoppingLists, createListApi]);

  const deleteList = useCallback(async (listId: number) => {
    if (!user) return;
    const result = await deleteListApi(listId);
    // A successful DELETE will have a null result from useApi (for 204 No Content)
    if (result === null) {
      const newLists = shoppingLists.filter(l => l.shopping_list_id !== listId);
      setShoppingLists(newLists);
      if (activeListId === listId) {
        setActiveListId(newLists.length > 0 ? newLists[0].shopping_list_id : null);
      }
    }
  }, [user, shoppingLists, activeListId, setShoppingLists, deleteListApi]);

  const addItemToList = useCallback(async (listId: number, item: { masterItemId?: number, customItemName?: string }) => {
    if (!user) return;
    const newItem = await addItemApi(listId, item);
    if (newItem) {
      setShoppingLists(prevLists => prevLists.map(list => {
        if (list.shopping_list_id === listId) {
          const itemExists = list.items.some(i => i.shopping_list_item_id === newItem.shopping_list_item_id);
          if (itemExists) return list;
          return { ...list, items: [...list.items, newItem] };
        }
        return list;
      }));
    }
  }, [user, setShoppingLists, addItemApi]);

  const updateItemInList = useCallback(async (itemId: number, updates: Partial<ShoppingListItem>) => {
    if (!user || !activeListId) return;
    const updatedItem = await updateItemApi(itemId, updates);
    if (updatedItem) {
      setShoppingLists(prevLists => prevLists.map(list => {
        if (list.shopping_list_id === activeListId) {
          return { ...list, items: list.items.map(i => i.shopping_list_item_id === itemId ? updatedItem : i) };
        }
        return list;
      }));
    }
  }, [user, activeListId, setShoppingLists, updateItemApi]);

  const removeItemFromList = useCallback(async (itemId: number) => {
    if (!user || !activeListId) return;
    const result = await removeItemApi(itemId);
    if (result === null) {
      setShoppingLists(prevLists => prevLists.map(list => {
        if (list.shopping_list_id === activeListId) {
          return { ...list, items: list.items.filter(i => i.shopping_list_item_id !== itemId) };
        }
        return list;
      }));
    }
  }, [user, activeListId, setShoppingLists, removeItemApi]);

  return {
    shoppingLists,
    activeListId,
    setActiveListId,
    createList,
    deleteList,
    addItemToList,
    updateItemInList,
    removeItemFromList,
    isCreatingList,
    isDeletingList,
    isAddingItem,
    isUpdatingItem,
    isRemovingItem,
    error,
  };
};

export { useShoppingListsHook as useShoppingLists };