// src/pages/admin/FlyerReviewPage.test.tsx
import { render, screen, waitFor, within } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { FlyerReviewPage } from './FlyerReviewPage';
import { MemoryRouter } from 'react-router-dom';
import * as apiClient from '../../services/apiClient';
import { logger } from '../../services/logger.client';

// Must explicitly call vi.mock() for apiClient
vi.mock('../../services/apiClient');

const mockedApiClient = vi.mocked(apiClient);

// Mock LoadingSpinner to simplify DOM and avoid potential issues
vi.mock('../../components/LoadingSpinner', () => ({
  LoadingSpinner: () => <div data-testid="loading-spinner">Loading...</div>,
}));

describe('FlyerReviewPage', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('renders loading spinner initially', () => {
    // Mock a promise that doesn't resolve immediately to check loading state
    mockedApiClient.getFlyersForReview.mockReturnValue(new Promise(() => {}));

    render(
      <MemoryRouter>
        <FlyerReviewPage />
      </MemoryRouter>,
    );

    expect(screen.getByRole('status', { name: /loading flyers for review/i })).toBeInTheDocument();
  });

  it('renders empty state when no flyers are returned', async () => {
    mockedApiClient.getFlyersForReview.mockResolvedValue({
      ok: true,
      json: async () => [],
    } as Response);

    render(
      <MemoryRouter>
        <FlyerReviewPage />
      </MemoryRouter>,
    );

    await waitFor(() => {
      expect(screen.queryByRole('status')).not.toBeInTheDocument();
    });

    expect(screen.getByText(/the review queue is empty/i)).toBeInTheDocument();
  });

  it('renders a list of flyers when API returns data', async () => {
    const mockFlyers = [
      {
        flyer_id: 1,
        file_name: 'flyer1.jpg',
        created_at: '2023-01-01T00:00:00Z',
        store: { name: 'Store A' },
        icon_url: 'https://example.com/icon1.jpg',
      },
      {
        flyer_id: 2,
        file_name: 'flyer2.jpg',
        created_at: '2023-01-02T00:00:00Z',
        store: { name: 'Store B' },
        icon_url: 'https://example.com/icon2.jpg',
      },
      {
        flyer_id: 3,
        file_name: 'flyer3.jpg',
        created_at: '2023-01-03T00:00:00Z',
        store: null,
        icon_url: null,
      },
    ];

    mockedApiClient.getFlyersForReview.mockResolvedValue({
      ok: true,
      json: async () => mockFlyers,
    } as Response);

    render(
      <MemoryRouter>
        <FlyerReviewPage />
      </MemoryRouter>,
    );

    await waitFor(() => {
      expect(screen.queryByRole('status')).not.toBeInTheDocument();
    });

    expect(screen.getByText('Store A')).toBeInTheDocument();
    expect(screen.getByText('flyer1.jpg')).toBeInTheDocument();
    expect(screen.getByText('Store B')).toBeInTheDocument();
    expect(screen.getByText('flyer2.jpg')).toBeInTheDocument();

    // Test fallback for null store and icon_url
    expect(screen.getByText('Unknown Store')).toBeInTheDocument();
    expect(screen.getByText('flyer3.jpg')).toBeInTheDocument();
    const unknownStoreItem = screen.getByText('Unknown Store').closest('li');
    const unknownStoreImage = within(unknownStoreItem!).getByRole('img');
    expect(unknownStoreImage).not.toHaveAttribute('src');
    expect(unknownStoreImage).toHaveAttribute('alt', 'Unknown Store');
  });

  it('renders error message when API response is not ok', async () => {
    mockedApiClient.getFlyersForReview.mockResolvedValue({
      ok: false,
      json: async () => ({ message: 'Server error' }),
    } as Response);

    render(
      <MemoryRouter>
        <FlyerReviewPage />
      </MemoryRouter>,
    );

    await waitFor(() => {
      expect(screen.queryByRole('status')).not.toBeInTheDocument();
    });

    expect(screen.getByText('Server error')).toBeInTheDocument();
    expect(logger.error).toHaveBeenCalledWith(
      expect.objectContaining({ err: expect.any(Error) }),
      'Failed to fetch flyers for review',
    );
  });

  it('renders error message when API throws an error', async () => {
    const networkError = new Error('Network error');
    mockedApiClient.getFlyersForReview.mockRejectedValue(networkError);

    render(
      <MemoryRouter>
        <FlyerReviewPage />
      </MemoryRouter>,
    );

    await waitFor(() => {
      expect(screen.queryByRole('status')).not.toBeInTheDocument();
    });

    expect(screen.getByText('Network error')).toBeInTheDocument();
    expect(logger.error).toHaveBeenCalledWith(
      { err: networkError },
      'Failed to fetch flyers for review',
    );
  });

  it('renders a generic error for non-Error rejections', async () => {
    const nonErrorRejection = { message: 'This is not an Error object' };
    mockedApiClient.getFlyersForReview.mockRejectedValue(nonErrorRejection);

    render(
      <MemoryRouter>
        <FlyerReviewPage />
      </MemoryRouter>,
    );

    await waitFor(() => {
      expect(
        screen.getByText('An unknown error occurred while fetching data.'),
      ).toBeInTheDocument();
    });

    expect(logger.error).toHaveBeenCalledWith(
      { err: nonErrorRejection },
      'Failed to fetch flyers for review',
    );
  });
});
