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 {},
}));

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

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

const AT = Math.floor(new Date('2026-08-07T09:30:00Z').getTime() / 1000);

function session(over: Record<string, unknown> = {}) {
  return {
    uuid: 'ses-1',
    case_uuid: 'case-1',
    service_name: 'لیزر توتال',
    patient_name: 'محمد رسولی',
    resource_name: 'کندلا ۲۰۲۳',
    session_number: 2,
    total_sessions: 3,
    status: 'booked',
    due_at: AT,
    started_at: null,
    finished_at: null,
    note: null,
    performed_by: null,
    appointment: { uuid: 'a-1', slot_start: AT, slot_end: AT + 1800, status: 'confirmed' },
    areas: [{ status: 'completed' }, { status: 'pending' }],
    ...over,
  };
}

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

describe('صفحهٔ جلسات امروز پرسنل', () => {
  it('نام بیمار و دستگاه را نشان می‌دهد، نه فقط نام سرویس', async () => {
    get.mockResolvedValue({ success: true, data: [session()] });

    renderWithProviders(<StaffTreatmentSessionsPage />);

    expect(await screen.findByText('محمد رسولی')).toBeInTheDocument();
    expect(screen.getByText('کندلا ۲۰۲۳')).toBeInTheDocument();
    expect(screen.getByText('لیزر توتال')).toBeInTheDocument();
  });

  /** صف است: کار باقی‌مانده باید بالای کارِ تمام‌شده بنشیند. */
  it('کار باقی‌مانده را از کار تمام‌شده جدا می‌کند', async () => {
    get.mockResolvedValue({
      success: true,
      data: [
        session({ uuid: 's-done', status: 'done', patient_name: 'بیمار تمام‌شده' }),
        session({ uuid: 's-open', status: 'booked', patient_name: 'بیمار در انتظار' }),
      ],
    });

    renderWithProviders(<StaffTreatmentSessionsPage />);

    const pendingHead = await screen.findByText('در انتظار انجام');
    const doneHead    = screen.getByText('تمام‌شده');
    expect(pendingHead.compareDocumentPosition(doneHead) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();

    const open = screen.getByText('بیمار در انتظار');
    const done = screen.getByText('بیمار تمام‌شده');
    expect(open.compareDocumentPosition(done) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
  });

  /** غیبت برای امروز بسته است، هرچند جلسه دوباره برنامه‌ریزی می‌شود. */
  it('غیبت را در گروه تمام‌شده می‌گذارد', async () => {
    get.mockResolvedValue({ success: true, data: [session({ status: 'no_show' })] });

    renderWithProviders(<StaffTreatmentSessionsPage />);

    expect(await screen.findByText('تمام‌شده')).toBeInTheDocument();
    expect(screen.getByText('کار باقی‌مانده‌ای ندارید.')).toBeInTheDocument();
  });

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

    renderWithProviders(<StaffTreatmentSessionsPage />);

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

  it('فهرست خالی پیام خودش را دارد', async () => {
    get.mockResolvedValue({ success: true, data: [] });

    renderWithProviders(<StaffTreatmentSessionsPage />);

    expect(await screen.findByText(/جلسه‌ای برای شما ثبت نشده/)).toBeInTheDocument();
  });

  it('کل ردیف لینکِ همان جلسه است', async () => {
    get.mockResolvedValue({ success: true, data: [session()] });

    renderWithProviders(<StaffTreatmentSessionsPage />);

    const row = (await screen.findByText('محمد رسولی')).closest('a');
    expect(row).toHaveAttribute('href', '/admin/my-sessions/ses-1');
  });
});
