import { renderHook } from '@testing-library/react';
import { act } from 'react';
import usePortal from '../usePortal';

describe('usePortal', () => {
  afterEach(() => {
    document.body.innerHTML = '';
  });

  it('creates portal element when id and shouldCreate are provided', () => {
    const { result } = renderHook(() => usePortal('test-portal', true));

    expect(result.current).toBeTruthy();
    expect(document.querySelector('#test-portal')).toBeTruthy();
  });

  it('returns null when id is undefined', () => {
    const { result } = renderHook(() => usePortal(undefined, true));

    expect(result.current).toBeNull();
    expect(document.querySelector('#test-portal')).toBeNull();
  });

  it('returns null when shouldCreate is false', () => {
    const { result } = renderHook(() => usePortal('test-portal', false));

    expect(result.current).toBeNull();
    expect(document.querySelector('#test-portal')).toBeNull();
  });

  it('cleans up portal on unmount', async () => {
    const { result, rerender, unmount } = renderHook(
      ({ shouldCreate }: { shouldCreate: boolean }) => usePortal('test-portal', shouldCreate),
      { initialProps: { shouldCreate: true } },
    );

    expect(document.querySelector('#test-portal')).toBeTruthy();

    // First set shouldCreate to false to trigger cleanup
    act(() => {
      rerender({ shouldCreate: false });
    });

    // Then unmount
    act(() => {
      unmount();
    });

    // Wait for cleanup to complete
    await act(async () => {
      await new Promise((resolve) => setTimeout(resolve, 100));
    });

    expect(document.querySelector('#test-portal')).toBeNull();
  });

  it('reuses existing portal if it exists', () => {
    const existingPortal = document.createElement('div');
    existingPortal.id = 'existing-portal';
    document.body.appendChild(existingPortal);

    const { result } = renderHook(() => usePortal('existing-portal', true));

    expect(result.current).toBe(existingPortal);
    expect(document.querySelectorAll('#existing-portal')).toHaveLength(1);
  });

  it('updates element reference when id changes', () => {
    const { result, rerender } = renderHook(({ id }) => usePortal(id, true), {
      initialProps: { id: 'portal-1' },
    });

    expect(document.querySelector('#portal-1')).toBeTruthy();

    act(() => {
      rerender({ id: 'portal-2' });
    });

    expect(document.querySelector('#portal-2')).toBeTruthy();
    expect(result.current?.id).toBe('portal-2');
  });
});
