import { expect, test } from "@playwright/test";
import {
  captureBrowserFailures,
  clickUntilVisible,
  gotoLiveView,
  loginWithPassword,
  markerKinds,
  projectEmail,
  projectText,
  registerAndConfirm,
  selectOptionContaining,
  waitForMapReady,
} from "./helpers";

test("two users complete medicine tracking, handover, realtime chat, and blind reviews", async ({
  browser,
  request,
}, testInfo) => {
  const runID = process.env.E2E_RUN_ID;
  const fixturePassword = process.env.E2E_FIXTURE_PASSWORD;
  const requestTitle = projectText(
    runID ? `Staging E2E medicine pickup ${runID}` : "E2E medicine pickup",
    testInfo.project.name,
  );
  const requesterEmail = projectEmail("requester", testInfo.project.name);
  const helperEmail = projectEmail("helper", testInfo.project.name);
  const requester =
    runID && fixturePassword
      ? await loginWithPassword(browser, requesterEmail, fixturePassword)
      : await registerAndConfirm(browser, request, requesterEmail, "E2E Requester");
  const helper =
    runID && fixturePassword
      ? await loginWithPassword(browser, helperEmail, fixturePassword)
      : await registerAndConfirm(browser, request, helperEmail, "E2E Helper");
  const assertRequesterClean = captureBrowserFailures(requester.page);
  const assertHelperClean = captureBrowserFailures(helper.page);

  await gotoLiveView(requester.page, "/requests/new");
  await selectOptionContaining(requester.page, "Category", "Medicine pickup");
  await requester.page.getByLabel("Medicine pickup status").selectOption("reserved");
  await requester.page.getByLabel("Short title").fill(requestTitle);
  await requester.page
    .getByLabel("What help do you need?")
    .fill("Please collect the legal medicine that is already reserved.");
  await requester.page.getByLabel("Urgency").selectOption("now");
  const expiresAt = new Date(Date.now() + 3 * 60 * 60 * 1000)
    .toISOString()
    .slice(0, 16);
  await requester.page.getByLabel("Request expires (UTC)").fill(expiresAt);
  await requester.page.getByLabel("Approximate area").fill("E2E central district");
  await requester.page.getByLabel("Location visibility").selectOption("approximate_public");
  await requester.page.getByLabel("Latitude").fill("50.4501");
  await requester.page.getByLabel("Longitude").fill("30.5234");
  await requester.page.locator("#request-form input[type=checkbox]").check();
  await requester.page.getByRole("button", { name: "Publish request" }).click();
  await expect(requester.page).toHaveURL(/\/requests\/[0-9a-f-]+$/);
  const requestURL = requester.page.url();
  await expect(requester.page.getByRole("heading", { name: requestTitle })).toBeVisible();

  await gotoLiveView(helper.page, requestURL);
  await helper.page.getByRole("button", { name: "I can help" }).click();
  await expect(helper.page.getByRole("heading", { name: "Private match chat" })).toBeVisible();
  await expect(requester.page.getByRole("heading", { name: "Private match chat" })).toBeVisible();

  await helper.page
    .getByPlaceholder("Write a safe coordination message…")
    .fill("I am on my way to the pharmacy.");
  await helper.page.getByRole("button", { name: "Send", exact: true }).click();
  await expect(requester.page.getByText("I am on my way to the pharmacy.")).toBeVisible();

  await requester.page
    .getByPlaceholder("Write a safe coordination message…")
    .fill("Thank you. The order is waiting at the counter.");
  await requester.page.getByRole("button", { name: "Send", exact: true }).click();
  await expect(helper.page.getByText("Thank you. The order is waiting at the counter.")).toBeVisible();

  const origin = new URL(process.env.BASE_URL!).origin;
  await helper.context.grantPermissions(["geolocation"], { origin });
  await helper.context.setGeolocation({
    latitude: 50.4504,
    longitude: 30.5237,
    accuracy: 5,
  });
  await helper.page.getByRole("button", { name: "Share location" }).click();
  await expect(helper.page.getByRole("button", { name: "Stop and delete position" })).toBeVisible();
  await expect.poll(() => markerKinds(requester.page)).toContain("Shared location");

  await helper.page.getByRole("button", { name: "Stop and delete position" }).click();
  await expect(helper.page.getByRole("button", { name: "Share location" })).toBeVisible();
  await expect.poll(() => markerKinds(requester.page)).not.toContain("Shared location");

  await helper.page.getByRole("button", { name: "Start helping" }).click();
  const handoverCode = (
    await requester.page.locator("text=HANDOVER CODE FOR THE HELPER").locator("..").locator(".font-mono").innerText()
  ).replace(/\s/g, "");
  expect(handoverCode).toMatch(/^\d{6}$/);

  await helper.page.getByLabel("Enter handover code").fill(handoverCode);
  await helper.page.getByRole("button", { name: "Verify handover" }).click();
  await expect(helper.page.getByText("Handover code verified.")).toBeVisible();

  await helper.page.getByRole("button", { name: "Confirm my part is complete" }).click();
  await requester.page.getByRole("button", { name: "Confirm my part is complete" }).click();
  await expect(requester.page.getByRole("heading", { name: "Double-blind review" })).toBeVisible();
  await expect(helper.page.getByRole("heading", { name: "Double-blind review" })).toBeVisible();

  await helper.page.getByLabel("Rating").selectOption("5");
  await helper.page.getByLabel("Comment (optional)").fill("Clear and safe coordination.");
  await helper.page.getByRole("button", { name: "Submit review" }).click();
  await expect(
    helper.page
      .locator("#main-content")
      .getByText("Review saved. It appears after both participants review."),
  ).toBeVisible();

  await waitForMapReady(requester.page);
  await gotoLiveView(requester.page, "/profile");
  await expect(requester.page.getByText("None revealed yet.")).toBeVisible();
  await expect(requester.page.getByText("Clear and safe coordination.")).toHaveCount(0);
  await gotoLiveView(requester.page, requestURL);

  await requester.page.getByLabel("Rating").selectOption("5");
  await requester.page.getByLabel("Comment (optional)").fill("Reliable volunteer.");
  await requester.page.getByRole("button", { name: "Submit review" }).click();
  await expect(
    requester.page
      .locator("#main-content")
      .getByText("Review saved. It appears after both participants review."),
  ).toBeVisible();

  await waitForMapReady(requester.page);
  await gotoLiveView(requester.page, "/profile");
  await expect(requester.page.getByText("Clear and safe coordination.")).toBeVisible();
  await waitForMapReady(helper.page);
  await gotoLiveView(helper.page, "/profile");
  await expect(helper.page.getByText("Reliable volunteer.")).toBeVisible();

  const roadsideTitle = projectText(
    runID ? `Staging E2E motorcycle chain ${runID}` : "E2E motorcycle chain",
    testInfo.project.name,
  );
  await gotoLiveView(requester.page, "/requests/new");
  await selectOptionContaining(
    requester.page,
    "Category",
    "Motorcycle roadside help",
  );
  await requester.page.getByLabel("Motorcycle problem").selectOption("broken_chain");
  await requester.page
    .getByLabel("Motorcycle is away from active traffic")
    .selectOption("true");
  await requester.page.getByLabel("Short title").fill(roadsideTitle);
  await requester.page
    .getByLabel("What help do you need?")
    .fill("The motorcycle is secured and needs help with a broken chain.");
  await requester.page.getByLabel("Urgency").selectOption("today");
  await requester.page
    .getByLabel("Request expires (UTC)")
    .fill(new Date(Date.now() + 4 * 60 * 60 * 1000).toISOString().slice(0, 16));
  await requester.page.getByLabel("Approximate area").fill("E2E secured roadside area");
  await requester.page.getByLabel("Location visibility").selectOption("hidden");
  await requester.page.getByLabel("Latitude").fill("50.4501");
  await requester.page.getByLabel("Longitude").fill("30.5234");
  await requester.page.locator("#request-form input[type=checkbox]").last().check();
  await requester.page.getByRole("button", { name: "Publish request" }).click();
  await expect(requester.page.getByRole("heading", { name: roadsideTitle })).toBeVisible();

  const roadsideURL = requester.page.url();
  await gotoLiveView(helper.page, roadsideURL);
  await clickUntilVisible(
    helper.page.getByRole("button", { name: "I can help" }),
    helper.page.getByRole("button", { name: "Withdraw from this request" }),
  );
  await clickUntilVisible(
    helper.page.getByRole("button", { name: "Withdraw from this request" }),
    helper.page.getByText("You withdrew from this request."),
  );
  await expect(requester.page.getByText("Cancelled", { exact: true })).toBeVisible();

  assertRequesterClean();
  assertHelperClean();
  await requester.context.close();
  await helper.context.close();
});
