import { describe, it, expect, afterEach, vi } from 'vitest';
import { screen, fireEvent, waitFor } from '@testing-library/react';
import { EngagementCreateDialog } from './EngagementCreateDialog';
import { installFetchMock, renderWithProviders } from '@/test/testUtils';

describe('EngagementCreateDialog', () => {
  let fetchMock: ReturnType<typeof installFetchMock>;

  afterEach(() => {
    fetchMock?.restore();
  });

  it('rejects empty client name client-side without calling the backend', () => {
    fetchMock = installFetchMock([]);
    renderWithProviders(<EngagementCreateDialog onClose={vi.fn()} />);
    fireEvent.click(screen.getByRole('button', { name: /arm engagement/i }));
    expect(screen.getByText(/client requis/i)).toBeInTheDocument();
    expect(fetchMock.calls).toHaveLength(0);
  });

  it('maps 422 backend errors (details[].loc) to per-field messages', async () => {
    fetchMock = installFetchMock([
      {
        status: 422,
        body: {
          error: 'validation_error',
          message: 'request failed',
          details: [
            {
              loc: ['client_name'],
              msg: 'String should have at least 1 character',
              type: 'string_too_short',
            },
          ],
        },
      },
    ]);
    renderWithProviders(<EngagementCreateDialog onClose={vi.fn()} />);

    fireEvent.change(screen.getByLabelText(/client name/i), { target: { value: 'x' } });
    fireEvent.click(screen.getByRole('button', { name: /arm engagement/i }));

    await waitFor(() => {
      expect(screen.getByText(/at least 1 character/i)).toBeInTheDocument();
    });
  });

  it('invalidates the engagements query and closes on success', async () => {
    const onClose = vi.fn();
    fetchMock = installFetchMock([
      {
        status: 201,
        body: {
          id: 'eng_new',
          client_name: 'OPERATION ZETA',
          description: null,
          status: 'draft',
          c2_type: 'mythic',
          start_date: null,
          end_date: null,
        },
      },
    ]);
    renderWithProviders(<EngagementCreateDialog onClose={onClose} />);

    fireEvent.change(screen.getByLabelText(/client name/i), {
      target: { value: 'OPERATION ZETA' },
    });
    fireEvent.click(screen.getByRole('button', { name: /arm engagement/i }));

    await waitFor(() => {
      expect(onClose).toHaveBeenCalledTimes(1);
    });
    expect(fetchMock.calls[0]?.url).toBe('/api/v1/engagements/');
    expect(fetchMock.calls[0]?.init?.method).toBe('POST');
  });

  it('surfaces a generic top-of-form error on 401', async () => {
    fetchMock = installFetchMock([
      {
        status: 401,
        body: { error: 'not_authenticated', message: 'no active session' },
      },
    ]);
    renderWithProviders(<EngagementCreateDialog onClose={vi.fn()} />);
    fireEvent.change(screen.getByLabelText(/client name/i), {
      target: { value: 'Anyone' },
    });
    fireEvent.click(screen.getByRole('button', { name: /arm engagement/i }));
    const alert = await screen.findByRole('alert');
    expect(alert.textContent).toMatch(/session expirée/i);
  });
});
