import { act, render, screen, waitFor } from '@testing-library/react';
import { AuthProvider, useAuth } from './auth-context';

function Probe() {
  const { admin, loading, error, logout } = useAuth();
  return (
    <div>
      <div data-testid="loading">{String(loading)}</div>
      <div data-testid="admin">{admin?.email ?? 'null'}</div>
      <div data-testid="error">{error ?? 'null'}</div>
      <button type="button" onClick={() => void logout()}>logout</button>
    </div>
  );
}

let fetchSpy: jest.SpyInstance;

beforeEach(() => {
  fetchSpy = jest.spyOn(global, 'fetch');
});

afterEach(() => {
  jest.restoreAllMocks();
});

describe('AuthProvider', () => {
  it('exposes a loading state then sets admin from /api/auth/me', async () => {
    fetchSpy.mockResolvedValue(
      new Response(JSON.stringify({ admin: { id: 'a-1', email: 'me@x.com', role: 'OWNER', tenantId: 't1', tenantSlug: 'default', tenantName: 'Default' } }), {
        status: 200,
        headers: { 'Content-Type': 'application/json' },
      }),
    );
    render(
      <AuthProvider>
        <Probe />
      </AuthProvider>,
    );
    await waitFor(() => expect(screen.getByTestId('admin')).toHaveTextContent('me@x.com'));
    expect(screen.getByTestId('loading')).toHaveTextContent('false');
  });

  it('sets admin to null on 401', async () => {
    fetchSpy.mockResolvedValue(
      new Response(JSON.stringify({ message: 'Unauthorized' }), {
        status: 401,
        headers: { 'Content-Type': 'application/json' },
      }),
    );
    render(
      <AuthProvider>
        <Probe />
      </AuthProvider>,
    );
    await waitFor(() => expect(screen.getByTestId('admin')).toHaveTextContent('null'));
  });

  it('calls POST /api/auth/logout when logout is invoked', async () => {
    fetchSpy
      .mockResolvedValueOnce(
        new Response(JSON.stringify({ admin: { id: 'a-1', email: 'me@x.com' } }), {
          status: 200,
          headers: { 'Content-Type': 'application/json' },
        }),
      )
      .mockResolvedValueOnce(new Response(null, { status: 204 }));
    render(
      <AuthProvider>
        <Probe />
      </AuthProvider>,
    );
    await waitFor(() => expect(screen.getByTestId('admin')).toHaveTextContent('me@x.com'));
    await act(async () => {
      screen.getByText('logout').click();
    });
    await waitFor(() => expect(fetchSpy).toHaveBeenCalledWith('/api/auth/logout', expect.objectContaining({ method: 'POST' })));
    expect(screen.getByTestId('admin')).toHaveTextContent('null');
  });
});
