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

import { installMockBridge } from "../helpers/bridge";
import { openSettings } from "../helpers/settings";

test("settings sections share the Appearance rhythm", async ({ page }) => {
  await installMockBridge(page);
  await page.goto("/");
  await openSettings(page, "appearance");

  const appearanceList = page
    .getByTestId("settings-theme")
    .locator('[data-slot="settings-section-list"]');
  const [referenceGap] = await appearanceList
    .locator(":scope > *")
    .evaluateAll((elements) =>
      elements.slice(1).map((element, index) => {
        const previous = elements[index];
        return (
          element.getBoundingClientRect().top -
          previous.getBoundingClientRect().bottom
        );
      }),
    );

  expect(referenceGap).toBeGreaterThan(0);

  for (const section of [
    "notifications",
    "voice",
    "agents",
    "shortcuts",
    "profile",
  ] as const) {
    await page.getByTestId(`settings-nav-${section}`).click();

    const list = page
      .getByTestId(`settings-${section}`)
      .locator('[data-slot="settings-section-list"]');
    await expect(list).toBeVisible();

    const gaps = await list.locator(":scope > *").evaluateAll((elements) =>
      elements.slice(1).map((element, index) => {
        const previous = elements[index];
        return (
          element.getBoundingClientRect().top -
          previous.getBoundingClientRect().bottom
        );
      }),
    );
    expect(gaps.length).toBeGreaterThan(0);
    expect(gaps.every((gap) => Math.abs(gap - referenceGap) <= 1)).toBe(true);
  }

  await page.getByTestId("settings-nav-agents").click();
  const headerToCardGap = async (testId: string) => {
    const group = page.getByTestId(testId);
    return group.evaluate((element) => {
      const lastHeaderLine = element.querySelector(
        '[data-slot="settings-section-header"] > div:first-child > :last-child',
      );
      const card = element.querySelector('[data-slot="settings-section-card"]');
      if (
        !(lastHeaderLine instanceof HTMLElement) ||
        !(card instanceof HTMLElement)
      ) {
        throw new Error("Missing section header or card");
      }
      return (
        card.getBoundingClientRect().top -
        lastHeaderLine.getBoundingClientRect().bottom
      );
    });
  };
  const [titleOnlyGap, subtitleGap] = await Promise.all([
    headerToCardGap("agents-preferences-card"),
    headerToCardGap("settings-harnesses"),
  ]);
  expect(titleOnlyGap).toBeGreaterThan(0);
  expect(Math.abs(titleOnlyGap - subtitleGap)).toBeLessThanOrEqual(1);
});

test("Profile sections keep visible cards and aligned actions", async ({
  page,
}) => {
  await installMockBridge(page);
  await page.goto("/");
  await openSettings(page, "profile");

  const identity = page.getByTestId("profile-identity-card");
  const identityCard = identity.locator(
    'xpath=ancestor::*[@data-slot="settings-section-card"][1]',
  );
  await expect(identityCard).toBeVisible();
  await expect(
    page.getByText("Identity details", { exact: true }),
  ).toBeVisible();
  await expect(page.getByTestId("profile-identity-details")).toBeHidden();

  const signOut = page.getByTestId("settings-signout");
  const signOutCard = signOut.locator('[data-slot="settings-section-card"]');
  await expect(signOutCard).toBeVisible();
  await expect(
    signOutCard.getByRole("button", { name: "Delete my data" }),
  ).toBeVisible();
  await expect(signOut.getByText("Sign out", { exact: true })).toHaveCount(1);
  await expect(
    signOut.getByText("Sign out of Buzz", { exact: true }),
  ).toHaveCount(0);

  const profileInfo = page.getByTestId("profile-metadata-card");
  await profileInfo.scrollIntoViewIfNeeded();
  const [titleBottom, editBottom] = await Promise.all([
    profileInfo
      .getByRole("heading", { name: "Profile info" })
      .evaluate((element) => element.getBoundingClientRect().bottom),
    page
      .getByTestId("profile-metadata-edit")
      .evaluate((element) => element.getBoundingClientRect().bottom),
  ]);
  expect(Math.abs(titleBottom - editBottom)).toBeLessThanOrEqual(1);

  await page.getByTestId("settings-nav-updates").click();
  await expect(
    page
      .getByTestId("settings-updates")
      .getByText("Update status", { exact: true }),
  ).toHaveCount(1);
});
