import { describe, it, expect, beforeEach, vi } from 'vitest';
import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
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 ResourceBookingModal from './ResourceBookingModal';

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

const resource = {
  uuid: 'r-laser',
  name: 'لیزر CO2',
  address_uuid: 'addr-1',
} as never;

/** یکی از این دو وقت مالِ همین منبع است و دیگری مالِ دستگاه دیگری. */
const slots = [
  { start: 1783859400, end: 1783861200, assignment: { device: [{ uuid: 'r-laser', name: 'لیزر CO2' }] } },
  { start: 1783863000, end: 1783864800, assignment: { device: [{ uuid: 'r-other', name: 'لیزر دیگر' }] } },
];

beforeEach(() => {
  get.mockReset();
  post.mockReset();
  get.mockImplementation((url: string) => {
    if (url.includes('/services')) {
      return Promise.resolve({ success: true, data: [
        { service_uuid: 's-1', service_name: 'لیزر صورت', active: true, effective_duration_minutes: 30 },
        { service_uuid: 's-2', service_name: 'سرویس غیرفعال', active: false, effective_duration_minutes: 20 },
      ] });
    }
    if (url.includes('/my/clinic-doctors')) {
      return Promise.resolve({ success: true, data: { data: [{ uuid: 'd-1', name: 'دکتر مرادی' }] } });
    }
    return Promise.resolve({ success: true, data: [] });
  });
  post.mockImplementation((url: string) => {
    if (url.includes('appointment-availability')) {
      return Promise.resolve({ success: true, data: { plan: { total_minutes: 30, segments: [] }, slots, reason: null } });
    }
    if (url.includes('appointment-hold')) {
      return Promise.resolve({ success: true, data: { hold_uuid: 'h-1', assignment: {} } });
    }
    return Promise.resolve({ success: true, data: { uuid: 'appt-1' } });
  });
});

describe('ResourceBookingModal', () => {
  /** فقط سرویس‌هایی که خودِ منبع ارائه می‌دهد — سرور هم بقیه را با ۴۲۲ رد می‌کند. */
  it('فقط سرویس‌های فعالِ همین منبع را می‌آورد', async () => {
    renderWithProviders(
      <ResourceBookingModal resource={resource} onClose={vi.fn()} onBooked={vi.fn()} />,
    );

    expect(await screen.findByText('ثبت نوبت — لیزر CO2')).toBeInTheDocument();
    const called = get.mock.calls.map((c: any[]) => c[0]);
    expect(called.some((u: string) => u.includes('/api/v1/resource/r-laser/services'))).toBe(true);
  });

  /**
   * هستهٔ منبع‌محور بودن: موتور خدمت‌محور جواب می‌دهد، پس وقتی که این منبع در آن
   * پیشنهاد نشده باید حذف شود — نشان دادنش یعنی اپراتور چیزی بگیرد که ۴۰۹ می‌شود.
   */
  it('فقط وقت‌هایی را نشان می‌دهد که موتور همین منبع را در آن‌ها داده', async () => {
    const user = userEvent.setup();
    renderWithProviders(
      <ResourceBookingModal resource={resource} onClose={vi.fn()} onBooked={vi.fn()} />,
    );

    await screen.findByText('ثبت نوبت — لیزر CO2');
    await user.click(await screen.findByText('سرویس را انتخاب کنید'));
    await user.click(await screen.findByText(/لیزر صورت/));

    await waitFor(() => expect(screen.getByText(/زمان‌های خالی این منبع/)).toBeInTheDocument());

    // وقتِ منبعِ دیگر (۱۷۸۳۸۶۳۰۰۰) نباید دکمه‌ای داشته باشد.
    const buttons = screen.getAllByRole('button').map((b) => b.textContent ?? '');
    const timeButtons = buttons.filter((t) => /\d{2}:\d{2}/.test(t));
    expect(timeButtons).toHaveLength(1);
  });

  /** پزشک مسئول اجباری است: `confirm` بدون آن اصلاً کار نمی‌کند. */
  it('تا پزشک مسئول انتخاب نشود، ثبت غیرفعال است', async () => {
    const user = userEvent.setup();
    renderWithProviders(
      <ResourceBookingModal resource={resource} onClose={vi.fn()} onBooked={vi.fn()} />,
    );

    await screen.findByText('ثبت نوبت — لیزر CO2');
    expect(screen.getByRole('button', { name: 'ثبت نوبت' })).toBeDisabled();

    await user.click(await screen.findByText('سرویس را انتخاب کنید'));
    await user.click(await screen.findByText(/لیزر صورت/));
    await waitFor(() => expect(screen.getByText(/زمان‌های خالی این منبع/)).toBeInTheDocument());

    const timeBtn = screen.getAllByRole('button').find((b) => /\d{2}:\d{2}/.test(b.textContent ?? ''));
    await user.click(timeBtn!);

    // زمان انتخاب شد ولی پزشک نه → هنوز غیرفعال.
    expect(screen.getByRole('button', { name: 'ثبت نوبت' })).toBeDisabled();
    expect(await screen.findByText('پزشک انجام‌دهنده')).toBeInTheDocument();
  });
});
