import { describe, it, expect, beforeEach, vi } from 'vitest';
import { screen, fireEvent, waitFor } from '@testing-library/react';
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 { toast } from 'sonner';
import DetailsStep from './DetailsStep';
import type { SessionCardData } from '../SessionServiceCard';

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

const session: SessionCardData = {
  uuid: 's1',
  services: [{ service_name: 'لیزر' }],
  doctor_name: 'دکتر فتحی',
  final_price_rials: 1_000_000,
  patient_debt_rials: 0,
  discount_rials: 0,
  visit_price_rials: 0,
  payments: [],
};

beforeEach(() => {
  post.mockReset();
  (toast.error as ReturnType<typeof vi.fn>).mockReset();
});

describe('DetailsStep — صدور فاکتور', () => {
  it('فاکتور را می‌سازد، draft را finalize می‌کند و بعد onFinish', async () => {
    post.mockImplementation((url: string) =>
      url === '/api/v1/billing/invoices'
        ? Promise.resolve({ success: true, data: { data: { uuid: 'iv1', status: 'draft' } } })
        : Promise.resolve({ success: true, data: {} }),
    );
    const onFinish = vi.fn();
    renderWithProviders(<DetailsStep session={session} recordUuid="r1" onBack={() => {}} onFinish={onFinish} />);

    fireEvent.click(screen.getByText('صدور فاکتور'));

    await waitFor(() => expect(onFinish).toHaveBeenCalled());
    expect(post).toHaveBeenCalledWith('/api/v1/billing/invoices', { session_uuid: 's1' });
    expect(post).toHaveBeenCalledWith('/api/v1/billing/invoices/iv1/finalize', {});
  });

  it('فاکتور غیر draft (idempotent create) دیگر finalize نمی‌شود', async () => {
    post.mockResolvedValue({ success: true, data: { data: { uuid: 'iv1', status: 'finalized' } } });
    const onFinish = vi.fn();
    renderWithProviders(<DetailsStep session={session} onBack={() => {}} onFinish={onFinish} />);

    fireEvent.click(screen.getByText('صدور فاکتور'));

    await waitFor(() => expect(onFinish).toHaveBeenCalled());
    expect(post).toHaveBeenCalledTimes(1);
  });

  it('session با invoice_uuid موجود: بدون درخواست، مستقیم onFinish', async () => {
    const onFinish = vi.fn();
    renderWithProviders(
      <DetailsStep session={{ ...session, invoice_uuid: 'iv0' }} onBack={() => {}} onFinish={onFinish} />,
    );

    fireEvent.click(screen.getByText('صدور فاکتور'));

    await waitFor(() => expect(onFinish).toHaveBeenCalled());
    expect(post).not.toHaveBeenCalled();
  });

  it('خطای صدور: toast خطا و onFinish صدا زده نمی‌شود', async () => {
    post.mockRejectedValue(new Error('boom'));
    const onFinish = vi.fn();
    renderWithProviders(<DetailsStep session={session} onBack={() => {}} onFinish={onFinish} />);

    fireEvent.click(screen.getByText('صدور فاکتور'));

    await waitFor(() => expect(toast.error).toHaveBeenCalledWith('صدور فاکتور ناموفق بود'));
    expect(onFinish).not.toHaveBeenCalled();
  });
});
