import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { RenderResult, render, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { SessionTestProvider } from "@xtablo/shared/contexts/SessionContext";
import { ThemeProvider } from "@xtablo/shared/contexts/ThemeContext";
import React from "react";
import { I18nextProvider } from "react-i18next";
import { BrowserRouter, MemoryRouter, Route, Routes } from "react-router-dom";
import testI18n from "../i18n.test";
import { TestUserStoreProvider } from "../providers/UserStoreProvider";

const defaultUser = {
  id: "123",
  short_user_id: "123",
  name: "John Doe",
  first_name: "John",
  last_name: "Doe",
  email: "john@example.com",
  avatar_url: "https://example.com/avatar.jpg",
  streamToken: "test-stream-token",
  is_temporary: false,
  last_signed_in: null,
  plan: "none" as const,
  created_at: new Date().toISOString(),
};

export const renderWithRouter = (ui: React.ReactNode, { route = "/" } = {}) => {
  window.history.pushState({}, "Test page", route);

  return {
    user: userEvent.setup(),
    ...render(ui, { wrapper: BrowserRouter }),
  };
};

interface RenderWithProvidersOptions {
  route?: string;
  path?: string;
  language?: string;
}

export const renderWithProviders = (
  ui: React.ReactNode,
  { route, path, language = "en" }: RenderWithProvidersOptions = {}
): RenderResult => {
  // Set the language for this test
  testI18n.changeLanguage(language);
  // Create a new QueryClient instance for each test to avoid state pollution
  const testQueryClient = new QueryClient({
    defaultOptions: {
      queries: {
        retry: false,
        staleTime: Infinity,
      },
    },
  });

  const RouterWrapper = route && path ? MemoryRouter : BrowserRouter;
  const routerProps = route && path ? { initialEntries: [route] } : {};

  const content =
    route && path ? (
      <Routes>
        <Route path={path} element={ui} />
      </Routes>
    ) : (
      ui
    );

  return render(
    <I18nextProvider i18n={testI18n}>
      <RouterWrapper {...routerProps}>
        <ThemeProvider>
          <QueryClientProvider client={testQueryClient}>
            <SessionTestProvider
              testUser={{
                id: defaultUser.id,
                app_metadata: {},
                aud: "test",
                created_at: "2021-01-01",
                user_metadata: {
                  first_name: defaultUser.first_name,
                  last_name: defaultUser.last_name,
                  avatar_url: defaultUser.avatar_url,
                  full_name: defaultUser.name,
                },
              }}
            >
              <TestUserStoreProvider user={defaultUser}>{content}</TestUserStoreProvider>
            </SessionTestProvider>
          </QueryClientProvider>
        </ThemeProvider>
      </RouterWrapper>
    </I18nextProvider>
  );
};

export const waitForGridToBeInTheDOM = (): Promise<void> => {
  return waitFor(() => {
    expect(document.querySelector(".ag-root-wrapper")).toBeInTheDocument();
  });
};
