import { describe, it, expect, beforeEach, vi } from 'vitest';
import { screen } from '@testing-library/react';
import { renderWithProviders } from '../../test/utils';

vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn() } }));
vi.mock('../../lib/api', () => ({
  api: { get: vi.fn(), post: vi.fn(), patch: vi.fn(), put: vi.fn(), delete: vi.fn() },
  ApiError: class extends Error {},
}));

import { api } from '../../lib/api';
import NewAppointmentModal from './NewAppointmentModal';

const get = api.get as ReturnType<typeof vi.fn>;

const slot = {
  start: 1_780_000_000,
  end: 1_780_001_800,
  start_time: '۰۹:۰۰',
  end_time: '۰۹:۳۰',
  doctor_uuid: 'doc-1',
  doctor_name: 'دکتر رضایی',
};

beforeEach(() => {
  get.mockReset();
  get.mockResolvedValue({ success: true, data: [] });
});

const props = (overrides: Record<string, unknown> = {}) => ({
  slot,
  onClose: vi.fn(),
  onSuccess: vi.fn(),
  ...overrides,
});

/** عنوان مرحله‌های نوار بالای مودال. */
const stepLabels = () =>
  Array.from(document.querySelectorAll('ol[aria-label="مراحل ثبت نوبت"] li'))
    .map(li => li.textContent?.replace(/^\d+/, '').trim());

const pickerProps = () => props({ serviceMode: true, date: '1405-05-18', services: [] });

describe('NewAppointmentModal — ویزارد', () => {
  /**
   * فرم قبلاً یک صفحهٔ بلند بود: خدمت و زمان، بیمار و هزینه با هم. هر بار یک مرحله
   * دیده می‌شود تا مودال از ارتفاع صفحه بلندتر نشود.
   */
  it('حالت انتخابگر سه مرحله دارد و از مرحلهٔ اول شروع می‌شود', () => {
    renderWithProviders(<NewAppointmentModal {...pickerProps()} />);

    expect(stepLabels()).toEqual(['خدمت و زمان', 'بیمار', 'تأیید و ثبت']);
    expect(screen.getByRole('heading', { name: 'خدمت و زمان' })).toBeInTheDocument();
    expect(screen.queryByRole('heading', { name: 'بیمار' })).not.toBeInTheDocument();
  });

  it('مرحله‌ای که داده‌اش از قبل معلوم است ساخته نمی‌شود', () => {
    // نوبت اسلاتی: زمان از خودِ اسلات می‌آید، پس مرحلهٔ «خدمت و زمان» بی‌معناست.
    renderWithProviders(<NewAppointmentModal {...props()} />);

    expect(stepLabels()).toEqual(['بیمار', 'تأیید و ثبت']);
  });

  it('بیمارِ از پیش معلوم، مرحلهٔ بیمار را حذف می‌کند', () => {
    renderWithProviders(<NewAppointmentModal {...props({
      patient: { name: 'علی محمدی', mobile: '09123456789', national_code: '1234567890' },
    })} />);

    // تنها مرحلهٔ باقی‌مانده «تأیید و ثبت» است، پس نوار مراحل هم لازم نیست.
    expect(document.querySelector('ol[aria-label="مراحل ثبت نوبت"]')).toBeNull();
    expect(screen.getByRole('heading', { name: 'تأیید و ثبت' })).toBeInTheDocument();
  });

  it('تا وقتی مرحله کامل نشده، دکمهٔ بعدی غیرفعال است و دلیلش را می‌گوید', () => {
    renderWithProviders(<NewAppointmentModal {...pickerProps()} />);

    expect(screen.getByRole('button', { name: 'مرحلهٔ بعد' })).toBeDisabled();
    expect(screen.getByText(/یک سرویس انتخاب کنید/)).toBeInTheDocument();
    // دکمهٔ ثبت فقط در مرحلهٔ آخر وجود دارد.
    expect(screen.queryByRole('button', { name: 'ثبت نوبت' })).not.toBeInTheDocument();
  });

  it('در مرحلهٔ اول دکمهٔ «مرحلهٔ قبل» نیست، ولی «انصراف» همیشه هست', () => {
    renderWithProviders(<NewAppointmentModal {...pickerProps()} />);

    expect(screen.queryByRole('button', { name: 'مرحلهٔ قبل' })).not.toBeInTheDocument();
    expect(screen.getByRole('button', { name: 'انصراف' })).toBeInTheDocument();
  });

  it('مرحلهٔ آخر خلاصهٔ نوبت را نشان می‌دهد', () => {
    renderWithProviders(<NewAppointmentModal {...props({
      patient: { name: 'علی محمدی', mobile: '09123456789', national_code: '1234567890' },
    })} />);

    expect(screen.getByText('علی محمدی')).toBeInTheDocument();
    expect(screen.getByText('09123456789')).toBeInTheDocument();
  });

  it('دکمهٔ اصلی در فوتر ثابت است، نه داخل ناحیهٔ اسکرول', () => {
    renderWithProviders(<NewAppointmentModal {...pickerProps()} />);

    const next = screen.getByRole('button', { name: 'مرحلهٔ بعد' });

    expect(next.closest('.modal-foot')).not.toBeNull();
    expect(next.closest('.modal-body')).toBeNull();
  });
});
