import { expect, test, type Request } from "@playwright/test";

import { mockCoreApis } from "@e2e/fixtures/api-mocks";
import {
  clearBrowserState,
  signInWithEmailAndOpenChat,
} from "@e2e/fixtures/test-helpers";

test.beforeEach(async ({ baseURL, context, page }) => {
  await clearBrowserState(context, page, baseURL);
  await mockCoreApis(page, {
    chatSendTokenRefreshFlow: true,
  });
});

test("chat send refreshes an expired token, retries the request, and renders the reply", async ({
  page,
}) => {
  const chatSendRequests: Request[] = [];
  page.on("request", (request) => {
    if (new URL(request.url()).pathname === "/api/chat/send") {
      chatSendRequests.push(request);
    }
  });

  await signInWithEmailAndOpenChat(page);

  const message = "token refresh retry test";
  const messageInput = page.getByRole("textbox", { name: "Message" });
  await expect(messageInput).toBeVisible({ timeout: 10_000 });
  await expect(messageInput).toBeEnabled();
  await messageInput.fill(message);

  const refreshRequestPromise = page.waitForRequest("**/api/auth/refresh");
  const retriedSendResponsePromise = page.waitForResponse(
    (response) =>
      new URL(response.url()).pathname === "/api/chat/send" &&
      response.status() === 200,
  );

  await messageInput.press("Enter");

  const refreshRequest = await refreshRequestPromise;
  expect(refreshRequest.method()).toBe("POST");
  expect(refreshRequest.headers().authorization).toBeUndefined();
  expect(refreshRequest.postDataJSON()).toMatchObject({
    refreshToken: "e2e-email-refresh-token",
  });

  await retriedSendResponsePromise;
  await expect.poll(() => chatSendRequests.length).toBe(2);

  expect(chatSendRequests[0]?.postDataJSON()).toMatchObject({ message });
  expect(chatSendRequests[0]?.headers().authorization).toBe(
    "Bearer e2e-email-token",
  );
  expect(chatSendRequests[1]?.postDataJSON()).toMatchObject({ message });
  expect(chatSendRequests[1]?.headers().authorization).toBe(
    "Bearer e2e-refreshed-email-token",
  );

  await expect(page.getByText(message)).toBeVisible();
  await expect(page.getByText("Hello from the E2E boyfriend.")).toBeVisible();
});
