import { fireEvent, render, screen } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { Dialog } from './Dialog';

vi.mock('react-dom', () => ({
  createPortal: (node: React.ReactNode) => node,
}));

const defaultProps = {
  title: 'Test Dialog',
  description: 'Test Description',
};

describe('Dialog', () => {
  const onClose = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
    Object.defineProperty(window, 'matchMedia', {
      writable: true,
      value: vi.fn().mockImplementation((query) => ({
        matches: false,
        media: query,
        onchange: null,
        addListener: vi.fn(),
        removeListener: vi.fn(),
        addEventListener: vi.fn(),
        removeEventListener: vi.fn(),
        dispatchEvent: vi.fn(),
      })),
    });
  });

  describe('rendering', () => {
    it('renders nothing when isOpen is false', () => {
      render(
        <Dialog isOpen={false} onClose={onClose} {...defaultProps}>
          <div>Content</div>
        </Dialog>,
      );
      expect(screen.queryByTestId('ockDialog')).not.toBeInTheDocument();
    });

    it('renders content when isOpen is true', () => {
      render(
        <Dialog isOpen={true} onClose={onClose} {...defaultProps}>
          <div data-testid="content">Content</div>
        </Dialog>,
      );
      expect(screen.getByTestId('ockDialog')).toBeInTheDocument();
      expect(screen.getByTestId('content')).toBeInTheDocument();
    });
  });

  describe('accessibility', () => {
    it('sets all ARIA attributes correctly', () => {
      render(
        <Dialog
          isOpen={true}
          onClose={onClose}
          {...defaultProps}
          aria-label="Test Dialog"
          aria-describedby="desc"
          aria-labelledby="title"
        >
          <div>Content</div>
        </Dialog>,
      );

      const dialog = screen.getByTestId('ockDialog');
      expect(dialog).toHaveAttribute('role', 'dialog');
      expect(dialog).toHaveAttribute('aria-label', 'Test Dialog');
      expect(dialog).toHaveAttribute('aria-describedby', 'desc');
      expect(dialog).toHaveAttribute('aria-labelledby', 'title');
    });
  });

  describe('event handling', () => {
    it('does not stop propagation of other key events', () => {
      render(
        <Dialog isOpen={true} onClose={onClose} {...defaultProps}>
          <div>Content</div>
        </Dialog>,
      );

      const dialog = screen.getByTestId('ockDialog');
      const event = new KeyboardEvent('keydown', { key: 'A', bubbles: true });
      const spy = vi.spyOn(event, 'stopPropagation');
      fireEvent(dialog, event);
      expect(spy).not.toHaveBeenCalled();
    });
  });

  describe('dismissal behavior', () => {
    it('calls onClose when pressing Escape', () => {
      render(
        <Dialog isOpen={true} onClose={onClose} {...defaultProps}>
          <div>Content</div>
        </Dialog>,
      );

      fireEvent.keyDown(document, { key: 'Escape' });
      expect(onClose).toHaveBeenCalledTimes(1);
    });

    it('handles undefined onClose prop gracefully', () => {
      render(
        <Dialog isOpen={true} onClose={onClose} {...defaultProps}>
          <div>Content</div>
        </Dialog>,
      );

      fireEvent.pointerDown(document.body);
      fireEvent.keyDown(document, { key: 'Escape' });
    });
  });

  describe('portal rendering', () => {
    it('renders in portal', () => {
      const { baseElement } = render(
        <Dialog isOpen={true} onClose={onClose} {...defaultProps}>
          <div>Content</div>
        </Dialog>,
      );

      expect(baseElement.contains(screen.getByTestId('ockDialog'))).toBe(true);
    });
  });
});
