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

/**
 * باگی که این تست‌ها می‌بندند: پس‌زمینه یک onClick ساده داشت، پس هر کلیکی که روی
 * آن «تمام می‌شد» فرم نیمه‌پرشده را می‌بست — درگِ متن از داخل به بیرون، یا کلیک روی
 * گزینه‌ای که همان لحظه unmount می‌شد.
 */
function renderModal(onClose: () => void) {
  return render(
    <Modal open title="ثبت نوبت" onClose={onClose}>
      <input placeholder="نام" />
    </Modal>,
  );
}

const overlay = () => document.querySelector('.overlay') as HTMLElement;
const modal = () => document.querySelector('.modal') as HTMLElement;

beforeEach(() => {
  document.body.innerHTML = '';
});

describe('بستن مودال با پس‌زمینه', () => {
    it('فشردن و رها کردن روی پس‌زمینه، مودال را می‌بندد', () => {
        const onClose = vi.fn();
        renderModal(onClose);

        fireEvent.mouseDown(overlay());
        fireEvent.click(overlay());

        expect(onClose).toHaveBeenCalledTimes(1);
    });

    it('درگِ متن از داخل مودال به بیرون، آن را نمی‌بندد', () => {
        const onClose = vi.fn();
        renderModal(onClose);

        // شروع روی محتوای مودال، پایان روی پس‌زمینه — همان حرکتِ انتخاب متن.
        fireEvent.mouseDown(screen.getByPlaceholderText('نام'));
        fireEvent.click(overlay());

        expect(onClose).not.toHaveBeenCalled();
    });

    it('کلیک داخل مودال هیچ‌وقت آن را نمی‌بندد', () => {
        const onClose = vi.fn();
        renderModal(onClose);

        fireEvent.mouseDown(modal());
        fireEvent.click(modal());

        expect(onClose).not.toHaveBeenCalled();
    });

    it('کلیکِ بعدی روی پس‌زمینه پس از یک درگ، دوباره درست کار می‌کند', () => {
        const onClose = vi.fn();
        renderModal(onClose);

        fireEvent.mouseDown(screen.getByPlaceholderText('نام'));
        fireEvent.click(overlay());
        expect(onClose).not.toHaveBeenCalled();

        fireEvent.mouseDown(overlay());
        fireEvent.click(overlay());
        expect(onClose).toHaveBeenCalledTimes(1);
    });
});

describe('بستن مودال با Esc', () => {
    it('Esc مودال را می‌بندد', () => {
        const onClose = vi.fn();
        renderModal(onClose);

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

        expect(onClose).toHaveBeenCalledTimes(1);
    });

    it('وقتی منوی انتخاب باز است، Esc مودال را نمی‌بندد', () => {
        const onClose = vi.fn();
        renderModal(onClose);

        // همان نشانه‌ای که react-select با classNamePrefix می‌گذارد.
        const menu = document.createElement('div');
        menu.className = 'cp-select__menu';
        document.body.appendChild(menu);

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

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

    it('وقتی تقویم باز است، Esc مودال را نمی‌بندد', () => {
        const onClose = vi.fn();
        renderModal(onClose);

        const calendar = document.createElement('div');
        calendar.className = 'cp-calendar';
        document.body.appendChild(calendar);

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

        expect(onClose).not.toHaveBeenCalled();
    });

    it('کلیدهای دیگر کاری نمی‌کنند', () => {
        const onClose = vi.fn();
        renderModal(onClose);

        fireEvent.keyDown(document, { key: 'Enter' });
        fireEvent.keyDown(document, { key: 'a' });

        expect(onClose).not.toHaveBeenCalled();
    });

    it('مودالِ بسته به Esc گوش نمی‌دهد', () => {
        const onClose = vi.fn();
        render(<Modal open={false} title="ثبت نوبت" onClose={onClose}><p>محتوا</p></Modal>);

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

        expect(onClose).not.toHaveBeenCalled();
    });
});
