// src/pages/HomePage.test.tsx
import React from 'react';
import { render, screen } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { MemoryRouter, useOutletContext } from 'react-router-dom';
import { HomePage } from './HomePage';
import { createMockFlyer, createMockFlyerItem } from '../tests/utils/mockFactories';
import type { Flyer, FlyerItem } from '../types';
import type { FlyerDisplayProps } from '../features/flyer/FlyerDisplay'; // Keep this for FlyerDisplay mock
import type { ExtractedDataTableProps } from '../features/flyer/ExtractedDataTable'; // Import the props for ExtractedDataTable

// Mock child components to isolate the HomePage logic
vi.mock('../features/flyer/FlyerDisplay', () => ({
  FlyerDisplay: (props: FlyerDisplayProps) => <div data-testid="flyer-display" data-image-url={props.imageUrl} />,
}));
vi.mock('../features/flyer/AnalysisPanel', () => ({
  AnalysisPanel: () => <div data-testid="analysis-panel" />,
}));

// Mock the useOutletContext hook from react-router-dom
vi.mock('react-router-dom', async (importOriginal) => {
  const original = await importOriginal<typeof import('react-router-dom')>();
  return {
    ...original,
    useOutletContext: vi.fn(),
  };
});

// Mock ExtractedDataTable separately to use the imported props interface
import { ExtractedDataTable } from '../features/flyer/ExtractedDataTable';
vi.mock('../features/flyer/ExtractedDataTable', () => ({
  // Wrap the mock component in vi.fn() to allow spying on its calls.
  ExtractedDataTable: vi.fn((props: ExtractedDataTableProps) => <div data-testid="extracted-data-table">{props.items.length} items</div>),
}));

const mockedUseOutletContext = vi.mocked(useOutletContext);

describe('HomePage Component', () => {
  const mockOnOpenCorrectionTool = vi.fn();

  // Define a default context that can be overridden in specific tests
  const mockContext = {
    totalActiveItems: 10,
    masterItems: [],
    addWatchedItem: vi.fn(),
    shoppingLists: [],
    activeListId: null,
    addItemToList: vi.fn(),
  };

  beforeEach(() => {
    vi.clearAllMocks();
    // Provide the default mock implementation for the context hook
    mockedUseOutletContext.mockReturnValue(mockContext);
  });

  const renderInRouter = (ui: React.ReactElement) => {
    return render(<MemoryRouter>{ui}</MemoryRouter>);
  };

  it('should render the welcome message when no flyer is selected', () => {
    renderInRouter(
      <HomePage selectedFlyer={null} flyerItems={[]} onOpenCorrectionTool={mockOnOpenCorrectionTool} />
    );

    expect(screen.getByRole('heading', { name: /welcome to flyer crawler/i })).toBeInTheDocument();
    expect(screen.getByText(/upload a new grocery flyer to begin/i)).toBeInTheDocument();
    expect(screen.queryByTestId('flyer-display')).not.toBeInTheDocument();
  });

  describe('when a flyer is selected', () => {
    const mockFlyer: Flyer = createMockFlyer({
      flyer_id: 1,
      image_url: 'http://example.com/flyer.jpg',
    });

    it('should render FlyerDisplay but not data tables if there are no flyer items', () => {
      renderInRouter(
        <HomePage selectedFlyer={mockFlyer} flyerItems={[]} onOpenCorrectionTool={mockOnOpenCorrectionTool} />
      );

      const flyerDisplay = screen.getByTestId('flyer-display');
      expect(flyerDisplay).toBeInTheDocument();
      expect(flyerDisplay).toHaveAttribute('data-image-url', mockFlyer.image_url);

      expect(screen.queryByTestId('extracted-data-table')).not.toBeInTheDocument();
      expect(screen.queryByTestId('analysis-panel')).not.toBeInTheDocument();
    });

    it('should render all components when there are flyer items', () => {
      const mockItems: FlyerItem[] = [createMockFlyerItem({ flyer_item_id: 101 })];

      renderInRouter(
        <HomePage selectedFlyer={mockFlyer} flyerItems={mockItems} onOpenCorrectionTool={mockOnOpenCorrectionTool} />
      );

      expect(screen.getByTestId('flyer-display')).toBeInTheDocument();
      expect(screen.getByTestId('extracted-data-table')).toBeInTheDocument();
      expect(screen.getByTestId('analysis-panel')).toBeInTheDocument();
    });

    it('should pass correct props to ExtractedDataTable', () => {
      const mockItems: FlyerItem[] = [
        createMockFlyerItem({ flyer_item_id: 101 }),
        createMockFlyerItem({ flyer_item_id: 102 }),
      ];

      renderInRouter(
        <HomePage selectedFlyer={mockFlyer} flyerItems={mockItems} onOpenCorrectionTool={mockOnOpenCorrectionTool} />
      );

      // The mock component renders the number of items it received
      const dataTable = screen.getByTestId('extracted-data-table');
      expect(dataTable).toHaveTextContent('2 items');

      // We can also check the props passed to the mock component by inspecting the mock itself.
      // This is a more robust way to test prop passing.
      const ExtractedDataTableMock = vi.mocked(ExtractedDataTable);
      const props = ExtractedDataTableMock.mock.calls[ExtractedDataTableMock.mock.calls.length - 1][0];

      expect(props.items).toEqual(mockItems);
    });
  });
});