// src/hooks/useFlyerItems.test.ts
import { renderHook } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { useFlyerItems } from './useFlyerItems';
import * as useFlyerItemsQueryModule from './queries/useFlyerItemsQuery';
import { createMockFlyer, createMockFlyerItem } from '../tests/utils/mockFactories';

// Mock the underlying query hook to isolate the useFlyerItems hook's logic.
vi.mock('./queries/useFlyerItemsQuery');

const mockedUseFlyerItemsQuery = vi.mocked(useFlyerItemsQueryModule.useFlyerItemsQuery);

describe('useFlyerItems Hook', () => {
  const mockFlyer = createMockFlyer({
    flyer_id: 123,
    file_name: 'test-flyer.jpg',
    image_url: 'https://example.com/test.jpg',
    icon_url: 'https://example.com/icon.jpg',
    checksum: 'abc',
    valid_from: '2024-01-01',
    valid_to: '2024-01-07',
    item_count: 1,
    store: {
      store_id: 1,
      name: 'Test Store',
    },
  });

  const mockFlyerItems = [
    createMockFlyerItem({
      flyer_item_id: 1,
      flyer_id: 123,
      item: 'Apples',
      price_display: '$1.99',
      price_in_cents: 199,
      quantity: '1lb',
    }),
  ];

  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('should return initial state when flyer is null', () => {
    // Arrange: Mock the return value of the query hook.
    mockedUseFlyerItemsQuery.mockReturnValue({
      data: undefined,
      isLoading: false,
      error: null,
    } as ReturnType<typeof useFlyerItemsQueryModule.useFlyerItemsQuery>);

    // Act: Render the hook with a null flyer.
    const { result } = renderHook(() => useFlyerItems(null));

    // Assert: Check that the hook returns the correct initial state.
    expect(result.current.flyerItems).toEqual([]);
    expect(result.current.isLoading).toBe(false);
    expect(result.current.error).toBeNull();
    // Assert: Check that useFlyerItemsQuery was called with undefined flyerId.
    expect(mockedUseFlyerItemsQuery).toHaveBeenCalledWith(undefined);
  });

  it('should call useFlyerItemsQuery with flyerId when a flyer is provided', () => {
    mockedUseFlyerItemsQuery.mockReturnValue({
      data: undefined,
      isLoading: true,
      error: null,
    } as ReturnType<typeof useFlyerItemsQueryModule.useFlyerItemsQuery>);

    renderHook(() => useFlyerItems(mockFlyer));

    // Assert: Check that useFlyerItemsQuery was called with the correct flyerId.
    expect(mockedUseFlyerItemsQuery).toHaveBeenCalledWith(123);
  });

  it('should return isLoading: true when the query is loading', () => {
    mockedUseFlyerItemsQuery.mockReturnValue({
      data: undefined,
      isLoading: true,
      error: null,
    } as ReturnType<typeof useFlyerItemsQueryModule.useFlyerItemsQuery>);

    const { result } = renderHook(() => useFlyerItems(mockFlyer));

    expect(result.current.isLoading).toBe(true);
  });

  it('should return flyerItems when the query provides data', () => {
    mockedUseFlyerItemsQuery.mockReturnValue({
      data: mockFlyerItems,
      isLoading: false,
      error: null,
    } as ReturnType<typeof useFlyerItemsQueryModule.useFlyerItemsQuery>);

    const { result } = renderHook(() => useFlyerItems(mockFlyer));

    expect(result.current.isLoading).toBe(false);
    expect(result.current.flyerItems).toEqual(mockFlyerItems);
    expect(result.current.error).toBeNull();
  });

  it('should return an error when the query returns an error', () => {
    const mockError = new Error('Failed to fetch');
    mockedUseFlyerItemsQuery.mockReturnValue({
      data: undefined,
      isLoading: false,
      error: mockError,
    } as ReturnType<typeof useFlyerItemsQueryModule.useFlyerItemsQuery>);

    const { result } = renderHook(() => useFlyerItems(mockFlyer));

    expect(result.current.isLoading).toBe(false);
    expect(result.current.flyerItems).toEqual([]);
    expect(result.current.error).toEqual(mockError);
  });
});
