import { describe, it, expect, beforeEach, vi } from 'vitest';
import { screen, 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 {},
}));

vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn() } }));

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

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

const groups = [
  {
    uuid: 'g1',
    name: 'نواحی بدن',
    min_select: 1,
    max_select: null,
    items: [{ uuid: 'i1', name: 'صورت' }],
  },
];

const items = [
  { uuid: 'i1', name: 'صورت' },
  { uuid: 'i2', name: 'بیکینی' },
];

function mockApi() {
  get.mockImplementation((path: string) => {
    if (path.endsWith('/groups')) return Promise.resolve({ success: true, data: groups });
    if (path === '/api/v1/service-items') return Promise.resolve({ success: true, data: items });
    return Promise.resolve({ success: true, data: null });
  });
  post.mockResolvedValue({
    success: true,
    data: {
      valid: false,
      errors: [{ code: 'min_select', message: 'انتخاب حداقل ۱ مورد از «نواحی بدن» الزامی است' }],
      total_duration_minutes: 23,
      total_price_rials: 800000,
      breakdown: [
        { item_uuid: 'i1', item_name: 'صورت', counted_as: 'solo', minutes: 15, price_rials: 500000 },
        { item_uuid: 'i2', item_name: 'بیکینی', counted_as: 'additional', minutes: 8, price_rials: 300000 },
      ],
    },
  });
  patch.mockResolvedValue({ success: true, data: groups[0] });
}

describe('ServiceGroupsTab', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    mockApi();
  });

  it('shows each group with its min and max', async () => {
    renderWithProviders(<ServiceGroupsTab serviceUuid="s1" canEdit />, { route: '/admin/services/s1' });

    await waitFor(() => expect(screen.getByDisplayValue('نواحی بدن')).toBeInTheDocument());
    expect(screen.getByDisplayValue('1')).toBeInTheDocument();
    // حداکثرِ خالی یعنی نامحدود — نه صفر.
    expect(screen.getByPlaceholderText('نامحدود')).toHaveValue(null);
  });

  /**
   * ⭐ پیش‌نمایش نباید بدون انتخاب، درخواستی بزند: فراخوانی با سبد خالی هم نویز شبکه
   * است هم خطای «حداقل انتخاب» را بی‌جا نشان می‌دهد.
   */
  it('does not call validate until something is selected', async () => {
    renderWithProviders(<ServiceGroupsTab serviceUuid="s1" canEdit />, { route: '/admin/services/s1' });

    await waitFor(() => expect(screen.getByText('پیش‌نمایش انتخاب')).toBeInTheDocument());

    expect(post).not.toHaveBeenCalledWith('/api/v1/service-selection/validate', expect.anything());
    expect(screen.getByText(/چند آیتم انتخاب کنید/)).toBeInTheDocument();
  });

  it('explains the meaning of an empty maximum', async () => {
    renderWithProviders(<ServiceGroupsTab serviceUuid="s1" canEdit />, { route: '/admin/services/s1' });

    await waitFor(() =>
      expect(screen.getByText(/حداکثرِ خالی یعنی نامحدود/)).toBeInTheDocument(),
    );
  });
});
