import React, { type ReactElement } from 'react';
import { render, type RenderOptions } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { I18nextProvider } from 'react-i18next';
import i18n from '../i18n'; // Adjust path to your i18n config

/**
 * Test conventions — distilled from the SmartStack.app corpus (see the
 * `/test-conventions` skill, references/frontend-vitest.md). Apply them in every
 * `*.test.tsx`:
 *
 *  • `vi.mock(...)` is HOISTED — declare each mock ABOVE the import of the module
 *    it mocks (the page/hook under test), never after.
 *  • For unit component/hook tests, MOCK `react-i18next`
 *    (`useTranslation: () => ({ t: (k) => k, i18n: {…} })`) instead of relying on
 *    a real instance — avoids the NO_I18NEXT_INSTANCE warning and lets assertions
 *    match on the i18n key. (The provider below is for integration-style page tests.)
 *  • Testing Library queries: `getByRole` / `findByRole` / `queryByTestId`.
 *  • Router: `MemoryRouter` with `initialEntries` — never `BrowserRouter`.
 *  • Random ids: `crypto.randomUUID()` — never a hardcoded literal.
 *  • API is mocked with MSW (see `msw/handlers.ts` + `server.use(...)` per test) —
 *    this harness keeps the MSW approach rather than mocking the api client.
 */

/**
 * AuthContext mock for tests.
 * Provides a default authenticated user with admin permissions.
 */
const mockAuthContext = {
  user: {
    id: 'test-user-id',
    email: 'test-admin@smartstack.io',
    name: 'Test Admin',
    role: 'Administrator',
  },
  isAuthenticated: true,
  isLoading: false,
  login: async () => {},
  logout: async () => {},
  hasPermission: () => true,
  refreshPermissions: async () => {},
};

/**
 * Wraps components with all necessary providers for testing.
 * Includes: MemoryRouter, React Query, i18n.
 */
function AllProviders({ children }: { children: React.ReactNode }) {
  const queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false, staleTime: Infinity } },
  });
  return (
    <MemoryRouter>
      <QueryClientProvider client={queryClient}>
        <I18nextProvider i18n={i18n}>
          {children}
        </I18nextProvider>
      </QueryClientProvider>
    </MemoryRouter>
  );
}

/**
 * Custom render function that wraps components with test providers.
 * Use this instead of @testing-library/react's render.
 *
 * @example
 * import { renderWithProviders, screen } from '@/test/test-utils';
 * renderWithProviders(<MyComponent />);
 * expect(screen.getByText('Hello')).toBeInTheDocument();
 */
function renderWithProviders(
  ui: ReactElement,
  options?: Omit<RenderOptions, 'wrapper'>
) {
  return render(ui, { wrapper: AllProviders, ...options });
}

// Re-export everything from testing-library
export * from '@testing-library/react';
export { renderWithProviders };
export { mockAuthContext };
