import { render, screen, waitFor } from '@testing-library/react';
import { describe, it, expect, vi } from 'vitest';
import { createLazyComponent } from './LazyComponent';
import { Suspense } from 'react';

// Mock component
const MockComponent = () => <div>Lazy Loaded Component</div>;

describe('LazyComponent', () => {
  it('creates lazy component factory', () => {
    const LazyTest = createLazyComponent(() =>
      Promise.resolve({ default: MockComponent }),
    );

    expect(LazyTest).toBeDefined();
    expect(typeof LazyTest).toBe('function');
  });

  it('renders lazy component when loaded', async () => {
    const LazyTest = createLazyComponent(() =>
      Promise.resolve({ default: MockComponent }),
    );

    render(
      <Suspense fallback={<div>Loading...</div>}>
        <LazyTest />
      </Suspense>,
    );

    await waitFor(() => {
      expect(screen.getByText('Lazy Loaded Component')).toBeInTheDocument();
    });
  });

  it('shows fallback while loading', () => {
    const LazyTest = createLazyComponent(
      () => new Promise(() => {}), // Never resolves
    );

    render(
      <Suspense fallback={<div>Loading...</div>}>
        <LazyTest />
      </Suspense>,
    );

    expect(screen.getByText('Loading...')).toBeInTheDocument();
  });

  it('uses custom fallback when provided', () => {
    const LazyTest = createLazyComponent(
      () => new Promise(() => {}),
      <div>Custom Loading...</div>,
    );

    render(
      <Suspense fallback={<div>Default Loading...</div>}>
        <LazyTest fallback={<div>Custom Loading...</div>} />
      </Suspense>,
    );

    // The Suspense fallback will show, but the component can also have its own
    expect(screen.getByText('Default Loading...')).toBeInTheDocument();
  });
});
