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

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 { useAuthStore } from '../../stores/authStore';
import NewAppointmentModal from './NewAppointmentModal';

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

const START = 1_900_000_000;

const slot = {
  start: 0, end: 0, start_time: '', end_time: '',
  doctor_uuid: 'doc1', doctor_name: 'مینا یوسفی',
};

const resource = { uuid: 'r-2', name: 'لیزر CO2' };

const services = [
  { uuid: 's-1', name: 'کرایوتراپی', duration_minutes: 25, price_rials: 1_000_000, service_section: { uuid: 'sec-1', name: 'خدمات درمانگاه' } },
  { uuid: 's-2', name: 'RF فرکشنال', duration_minutes: 50, price_rials: 2_000_000, service_section: { uuid: 'sec-1', name: 'خدمات درمانگاه' } },
];

/** بیمارِ یافت‌شده تا فرم معتبر شود؛ زمان‌های خالی از تقویم منبع. */
function mockApi() {
  get.mockImplementation((url: string) => {
    if (url.includes('patient-lookup')) {
      return Promise.resolve({ success: true, data: { found: true, name: 'رضا رحیمی', mobile: '09120001307', national_code: '0012345678' } });
    }
    if (url.includes('/service-slots')) {
      return Promise.resolve({ success: true, data: {
        total_duration_minutes: 25,
        start_times: [{ start: START, end: START + 1500, start_time: '12:00', end_time: '12:25' }],
      } });
    }
    return Promise.resolve({ success: true, data: {} });
  });
}

/** انتخاب بخش → سرویس → زمان، همان مسیرِ مودالِ طرح. */
async function pickServiceAndTime() {
  fireEvent.keyDown(screen.getByRole('combobox'), { key: 'ArrowDown' });
  fireEvent.click(await screen.findByText('خدمات درمانگاه'));
  // ردیف سرویس یک checkbox است نه دکمه: انتخابش حالت دارد و باید برای screen reader
  // «انتخاب‌شده/نشده» اعلام شود.
  fireEvent.click(await screen.findByRole('checkbox', { name: /کرایوتراپی/ }));
  fireEvent.click(await screen.findByRole('button', { name: '12:00' }));
}

beforeEach(() => {
  get.mockReset();
  post.mockReset();
  useAuthStore.setState({ primaryRole: 'clinic' } as any);
  post.mockResolvedValue({ success: true, data: { uuid: 'new1' } });
  mockApi();
});

describe('مودال ثبت نوبتِ منبع', () => {
  it('نام منبع و پزشک ناظر بالای فرم می‌آید و زمان‌ها از تقویم منبع خوانده می‌شوند', async () => {
    renderWithProviders(
      <NewAppointmentModal slot={slot} resource={resource} services={services} date="2026-08-04" onClose={() => {}} onSuccess={() => {}} />,
    );

    expect(screen.getByText('لیزر CO2')).toBeInTheDocument();
    expect(screen.getByText('مینا یوسفی')).toBeInTheDocument();

    await pickServiceAndTime();

    await waitFor(() => expect(
      get.mock.calls.some((c: any[]) => typeof c[0] === 'string' && c[0].includes('/api/v1/resource/r-2/service-slots')),
    ).toBe(true));
  });

  it('ثبت، نوبت را با resource_uuid و مدتِ سرویس‌ها می‌فرستد', async () => {
    renderWithProviders(
      <NewAppointmentModal slot={slot} resource={resource} services={services} date="2026-08-04" onClose={() => {}} onSuccess={() => {}} />,
    );

    await pickServiceAndTime();

    fireEvent.change(screen.getByPlaceholderText('کد ملی ۱۰ رقمی'), { target: { value: '0012345678' } });
    fireEvent.click(screen.getByRole('button', { name: 'جستجو' }));
    await screen.findByText('بیمار یافت شد');

    fireEvent.click(screen.getByRole('button', { name: 'ثبت نوبت' }));

    await waitFor(() => expect(post).toHaveBeenCalled());
    const [url, body] = post.mock.calls[0];
    expect(url).toBe('/api/v1/my/appointment');
    expect(body).toMatchObject({
      resource_uuid: 'r-2',
      duration_from_services: true,
      service_item_uuids: ['s-1'],
      service_durations: { 's-1': 25 },
      slot_start: START,
      patient_national_code: '0012345678',
    });
  });

  it('بدون انتخاب سرویس و زمان، ثبت غیرفعال می‌ماند', async () => {
    renderWithProviders(
      <NewAppointmentModal slot={slot} resource={resource} services={services} date="2026-08-04" onClose={() => {}} onSuccess={() => {}} />,
    );

    fireEvent.change(screen.getByPlaceholderText('کد ملی ۱۰ رقمی'), { target: { value: '0012345678' } });
    fireEvent.click(screen.getByRole('button', { name: 'جستجو' }));
    await screen.findByText('بیمار یافت شد');

    expect(screen.getByRole('button', { name: 'ثبت نوبت' })).toBeDisabled();
  });

  it('دلیلِ غیرفعال بودنِ ثبت را می‌گوید و با پیشرفتِ فرم عوض می‌شود', async () => {
    renderWithProviders(
      <NewAppointmentModal slot={slot} resource={resource} services={services} date="2026-08-04" onClose={() => {}} onSuccess={() => {}} />,
    );

    expect(await screen.findByText(/یک سرویس انتخاب کنید/)).toBeInTheDocument();

    fireEvent.keyDown(screen.getByRole('combobox'), { key: 'ArrowDown' });
    fireEvent.click(await screen.findByText('خدمات درمانگاه'));
    fireEvent.click(await screen.findByRole('checkbox', { name: /کرایوتراپی/ }));

    // سرویس هست، زمان نه — پیام باید مرحلهٔ بعد را نشان دهد نه همان قبلی.
    expect(await screen.findByText(/ساعت شروع را انتخاب کنید/)).toBeInTheDocument();

    fireEvent.click(await screen.findByRole('button', { name: '12:00' }));
    expect(await screen.findByText(/ابتدا بیمار را جستجو کنید/)).toBeInTheDocument();
  });

  it('تاریخ نوبت به‌صورت جلالی بالای فرم می‌آید', () => {
    renderWithProviders(
      <NewAppointmentModal slot={slot} resource={resource} services={services} date="2026-08-04" onClose={() => {}} onSuccess={() => {}} />,
    );

    // بدون این، کاربر روزِ در حال رزرو را هیچ‌جای مودال نمی‌دید.
    expect(screen.getByText('تاریخ:')).toBeInTheDocument();
    expect(screen.getByText('۱۴۰۵/۰۵/۱۳')).toBeInTheDocument();
  });

  it('معیار جستجو یک seg با حالتِ اعلام‌شده است', () => {
    renderWithProviders(
      <NewAppointmentModal slot={slot} resource={resource} services={services} date="2026-08-04" onClose={() => {}} onSuccess={() => {}} />,
    );

    const national = screen.getByRole('button', { name: 'کد ملی' });
    const mobile = screen.getByRole('button', { name: 'شماره موبایل' });
    expect(national).toHaveAttribute('aria-pressed', 'true');
    expect(mobile).toHaveAttribute('aria-pressed', 'false');

    fireEvent.click(mobile);
    expect(screen.getByRole('button', { name: 'شماره موبایل' })).toHaveAttribute('aria-pressed', 'true');
    expect(screen.getByPlaceholderText('مثال: 09123456789')).toBeInTheDocument();
  });

  it('منبعِ بدون سرویس، پیام راهنما می‌دهد نه فهرست خالی', () => {
    renderWithProviders(
      <NewAppointmentModal slot={slot} resource={resource} services={[]} date="2026-08-04" onClose={() => {}} onSuccess={() => {}} />,
    );

    expect(screen.getByText(/برای این منبع سرویسی تعریف نشده است/)).toBeInTheDocument();
  });
});
