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 TreatmentCasesPage from './TreatmentCasesPage';

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

function caseRow(over: Record<string, unknown> = {}) {
  return {
    uuid: 'case-1',
    status: 'active',
    total_sessions: 3,
    completed_sessions: 1,
    opened_at: 1_786_000_000,
    closed_at: null,
    service: { uuid: 'svc-1', name: 'لیزر توتال' },
    supervisor: { uuid: 'doc-1', name: 'پزشک مدیسا' },
    patient: { record_uuid: 'rec-1', name: 'محمد رسولی', mobile: '09120001111', record_number: '۱۲' },
    areas: [{ uuid: 'ca-1', name: 'دست', category_uuid: 'cat-1' }],
    ...over,
  };
}

/** فقط اندپوینت فهرست را جواب می‌دهد؛ بقیه خالی. */
function mockList(rows: unknown[]) {
  get.mockImplementation((url: string) => {
    if (url.startsWith('/api/v1/treatment-cases')) return Promise.resolve({ success: true, data: rows });
    return Promise.resolve({ success: true, data: [] });
  });
}

beforeEach(() => {
  get.mockReset();
});

describe('صفحهٔ پرونده‌های درمان', () => {
  it('نام بیمار سرتیتر کارت است، نه نام سرویس', async () => {
    mockList([caseRow()]);

    renderWithProviders(<TreatmentCasesPage />);

    const name = await screen.findByText('محمد رسولی');
    expect(name.tagName).toBe('STRONG');
    expect(screen.getByText('لیزر توتال')).toBeInTheDocument();
  });

  /** جستجو باید به سرور برود، نه اینکه فهرست را در مرورگر فیلتر کند. */
  it('عبارت جستجو را به‌صورت پارامتر q می‌فرستد', async () => {
    mockList([caseRow()]);

    renderWithProviders(<TreatmentCasesPage />);
    await screen.findByText('محمد رسولی');

    fireEvent.change(screen.getByLabelText('جستجوی پرونده'), { target: { value: 'رسولی' } });

    await waitFor(
      () => expect(get.mock.calls.some(
        (c: unknown[]) => typeof c[0] === 'string' && c[0].includes('q=%D8%B1%D8%B3%D9%88%D9%84%DB%8C'),
      )).toBe(true),
      { timeout: 2000 },
    );
  });

  it('فیلتر وضعیت به‌صورت status می‌رود', async () => {
    mockList([caseRow()]);

    renderWithProviders(<TreatmentCasesPage />);
    await screen.findByText('محمد رسولی');

    fireEvent.click(screen.getByRole('button', { name: 'رها شده' }));

    await waitFor(() => expect(get.mock.calls.some(
      (c: unknown[]) => typeof c[0] === 'string' && c[0].includes('status=abandoned'),
    )).toBe(true));
  });

  /** نتیجهٔ خالیِ جستجو با «هنوز پرونده‌ای ساخته نشده» یکی نیست. */
  it('خالیِ جستجو پیام خودش را دارد', async () => {
    mockList([]);

    renderWithProviders(<TreatmentCasesPage />);
    await screen.findByText(/پرونده‌ای یافت نشد/);

    fireEvent.change(screen.getByLabelText('جستجوی پرونده'), { target: { value: 'هیچ' } });

    expect(await screen.findByText(/برای «هیچ» پرونده‌ای پیدا نشد/, {}, { timeout: 2000 })).toBeInTheDocument();
  });

  it('خطا را از فهرست خالی جدا می‌کند', async () => {
    get.mockRejectedValue(new Error('boom'));

    renderWithProviders(<TreatmentCasesPage />);

    await waitFor(() => expect(screen.getByText(/خواندن پرونده‌ها ناموفق بود/)).toBeInTheDocument());
    expect(screen.queryByText(/پرونده‌ای یافت نشد/)).not.toBeInTheDocument();
  });

  it('بازهٔ تاریخ به‌صورت from و to می‌رود', async () => {
    mockList([caseRow()]);

    renderWithProviders(<TreatmentCasesPage />);
    await screen.findByText('محمد رسولی');

    // PersianDateInput تریگرش input نیست، پس با نام دسترس‌پذیرش پیدایش می‌کنیم.
    fireEvent.click(screen.getByLabelText('شروع از تاریخ'));

    expect(screen.getByLabelText('شروع تا تاریخ')).toBeInTheDocument();
  });

  it('تاریخ شروع ساعت هم دارد', async () => {
    mockList([caseRow({ opened_at: 1_786_000_000 })]);

    renderWithProviders(<TreatmentCasesPage />);

    // formatDateTime ساعت را با «:» می‌آورد؛ formatDate نمی‌آورد.
    const start = await screen.findByText(/^شروع:/);
    expect(start.textContent).toMatch(/:/);
  });

  it('دکمهٔ ویرایش مودال را باز می‌کند', async () => {
    mockList([caseRow()]);

    renderWithProviders(<TreatmentCasesPage />);
    fireEvent.click(await screen.findByRole('button', { name: /ویرایش/ }));

    expect(await screen.findByText('ویرایش پروندهٔ درمان')).toBeInTheDocument();
  });
});
