// @vitest-environment jsdom
import { describe, it, expect, vi, afterEach } from 'vitest';
import { render, screen, fireEvent, cleanup } from '@testing-library/react';
import Modal from '../../components/ui/Modal';

describe('Modal', () => {
  afterEach(() => cleanup());

  it('renders nothing when open is false', () => {
    const { container } = render(
      <Modal open={false} onClose={() => {}} title="Test">
        <p>body</p>
      </Modal>
    );
    expect(container.querySelector('[role="dialog"]')).toBeNull();
  });

  it('renders dialog with correct ARIA shape when open', () => {
    render(
      <Modal
        open={true}
        onClose={() => {}}
        title="My Title"
        description="My description"
      >
        <p>body</p>
      </Modal>
    );
    const dialog = screen.getByRole('dialog');
    expect(dialog.getAttribute('aria-modal')).toBe('true');
    expect(dialog.getAttribute('aria-labelledby')).toBeTruthy();
    expect(dialog.getAttribute('aria-describedby')).toBeTruthy();
    expect(screen.getByText('My Title')).toBeTruthy();
    expect(screen.getByText('My description')).toBeTruthy();
  });

  it('omits aria-describedby when no description is provided', () => {
    render(
      <Modal open={true} onClose={() => {}} title="t">
        <p>b</p>
      </Modal>
    );
    const dialog = screen.getByRole('dialog');
    expect(dialog.getAttribute('aria-describedby')).toBeNull();
  });

  it('calls onClose on ESC keydown', () => {
    const onClose = vi.fn();
    render(
      <Modal open={true} onClose={onClose} title="t">
        <p>b</p>
      </Modal>
    );
    fireEvent.keyDown(document, { key: 'Escape' });
    expect(onClose).toHaveBeenCalledTimes(1);
  });

  it('does NOT call onClose on ESC when closeOnEsc is false', () => {
    const onClose = vi.fn();
    render(
      <Modal open={true} onClose={onClose} title="t" closeOnEsc={false}>
        <p>b</p>
      </Modal>
    );
    fireEvent.keyDown(document, { key: 'Escape' });
    expect(onClose).not.toHaveBeenCalled();
  });

  it('calls onClose on backdrop click', () => {
    const onClose = vi.fn();
    render(
      <Modal open={true} onClose={onClose} title="t">
        <p>b</p>
      </Modal>
    );
    fireEvent.click(screen.getByRole('dialog'));
    expect(onClose).toHaveBeenCalledTimes(1);
  });

  it('does NOT call onClose on backdrop click when closeOnBackdrop is false', () => {
    const onClose = vi.fn();
    render(
      <Modal
        open={true}
        onClose={onClose}
        title="t"
        closeOnBackdrop={false}
      >
        <p>b</p>
      </Modal>
    );
    fireEvent.click(screen.getByRole('dialog'));
    expect(onClose).not.toHaveBeenCalled();
  });

  it('renders a built-in close button with aria-label="Close" that triggers onClose', () => {
    const onClose = vi.fn();
    render(
      <Modal open={true} onClose={onClose} title="t">
        <p>b</p>
      </Modal>
    );
    const closeBtn = screen.getByRole('button', { name: /close/i });
    fireEvent.click(closeBtn);
    expect(onClose).toHaveBeenCalledTimes(1);
  });

  it('hides the built-in close button when hideCloseButton is true', () => {
    render(
      <Modal open={true} onClose={() => {}} title="t" hideCloseButton>
        <p>b</p>
      </Modal>
    );
    expect(
      screen.queryByRole('button', { name: /close/i })
    ).toBeNull();
  });

  it('locks body-scroll when open and restores on close', () => {
    const { rerender } = render(
      <Modal open={true} onClose={() => {}} title="t">
        <p>b</p>
      </Modal>
    );
    expect(document.body.style.overflow).toBe('hidden');
    rerender(
      <Modal open={false} onClose={() => {}} title="t">
        <p>b</p>
      </Modal>
    );
    expect(document.body.style.overflow).toBe('');
  });
});
