"use strict";

const { chromium } = require("playwright");
const {
  BASE_URL,
  UI_TIMEOUT_MS,
  assert,
  cleanupDocuments,
  createTempDocument,
  ensureAuthenticated,
  openDocument,
  requestJson,
} = require("./tree-shell-smoke-helpers");

async function saveDocumentContent(requestContext, workspaceId, documentId) {
  await requestJson(requestContext, "/api/documents/save", {
    method: "POST",
    data: {
      workspaceId,
      documentId,
      content: [
        {
          id: "h1",
          type: "heading",
          props: { level: 1 },
          content: [{ type: "text", text: "Page Option Smoke Heading" }],
        },
        {
          id: "p1",
          type: "paragraph",
          content: [{ type: "text", text: "Body for page option smoke." }],
        },
      ],
      blockCount: 2,
      snapshotCapturedAt: new Date().toISOString(),
    },
  });
}

async function openPageSettingsDialog(page) {
  const trigger = page.getByTestId("wolai-page-settings-trigger");
  await trigger.waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
  await trigger.click({ timeout: UI_TIMEOUT_MS });
  await page.getByRole("tablist", { name: "页面设置分组" }).waitFor({
    state: "visible",
    timeout: UI_TIMEOUT_MS,
  });
}

async function readPageOptionRuntimeState(page) {
  return page.evaluate(() => {
    const editor = document.querySelector(".ProseMirror");
    const firstParagraph = document.querySelector(".ProseMirror p");
    const heading = document.querySelector(".ProseMirror h1");
    const shell =
      document.querySelector('[data-shell-mode="document"]') ||
      document.querySelector(".document-shell") ||
      document.querySelector("article main");

    return {
      htmlWide: document.documentElement.getAttribute("data-page-wide-layout"),
      htmlSmall: document.documentElement.getAttribute("data-page-small-text"),
      htmlDensity: document.documentElement.getAttribute("data-layout-density"),
      shellMaxWidth:
        shell instanceof HTMLElement ? shell.style.maxWidth || window.getComputedStyle(shell).maxWidth : null,
      editorFontSize:
        editor instanceof HTMLElement ? window.getComputedStyle(editor).fontSize : null,
      paragraphMarginBottom:
        firstParagraph instanceof HTMLElement ? window.getComputedStyle(firstParagraph).marginBottom : null,
      headingBefore:
        heading instanceof HTMLElement ? window.getComputedStyle(heading, "::before").content : null,
    };
  });
}

async function main() {
  const browser = await chromium.launch({ headless: true });
  const context = await browser.newContext({
    viewport: { width: 1440, height: 960 },
  });
  const page = await context.newPage();

  let caughtError = null;
  let fixture = null;

  try {
    await ensureAuthenticated(page, context.request);
    const created = await createTempDocument(context.request, null);
    fixture = {
      workspaceId: created.workspaceId,
      createdIds: [created.documentId],
      documentId: created.documentId,
    };

    await saveDocumentContent(context.request, fixture.workspaceId, fixture.documentId);
    await openDocument(page, fixture.workspaceId, fixture.documentId);
    await page.locator(".ProseMirror").waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });

    await openPageSettingsDialog(page);

    const initial = await readPageOptionRuntimeState(page);
    assert(initial.htmlWide === "false", `初始 wideLayout 应为 false，实际 ${initial.htmlWide}`);
    assert(initial.htmlSmall === "false", `初始 smallText 应为 false，实际 ${initial.htmlSmall}`);
    assert(initial.htmlDensity === "normal", `初始 layoutDensity 应为 normal，实际 ${initial.htmlDensity}`);

    await page.getByRole("checkbox", { name: /自适应宽度/ }).click({ timeout: UI_TIMEOUT_MS });
    const afterWide = await readPageOptionRuntimeState(page);
    assert(afterWide.htmlWide === "true", `开启宽版后 htmlWide 应为 true，实际 ${afterWide.htmlWide}`);
    assert(afterWide.shellMaxWidth === "980px", `开启宽版后主列宽应为 980px，实际 ${afterWide.shellMaxWidth}`);

    await page.getByRole("checkbox", { name: /小字体/ }).click({ timeout: UI_TIMEOUT_MS });
    const afterSmall = await readPageOptionRuntimeState(page);
    assert(afterSmall.htmlSmall === "true", `开启小字体后 htmlSmall 应为 true，实际 ${afterSmall.htmlSmall}`);
    assert(
      typeof initial.editorFontSize === "string" &&
        typeof afterSmall.editorFontSize === "string" &&
        parseFloat(afterSmall.editorFontSize) < parseFloat(initial.editorFontSize),
      `开启小字体后编辑器字号应变小，初始 ${initial.editorFontSize}，实际 ${afterSmall.editorFontSize}`,
    );

    await page.getByRole("tab", { name: "自定义页面" }).click({ timeout: UI_TIMEOUT_MS });
    await page.getByLabel("layoutDensity").selectOption("紧凑");
    const afterDensity = await readPageOptionRuntimeState(page);
    assert(afterDensity.htmlDensity === "compact", `切换紧凑后 htmlDensity 应为 compact，实际 ${afterDensity.htmlDensity}`);
    assert(
      typeof initial.paragraphMarginBottom === "string" &&
        typeof afterDensity.paragraphMarginBottom === "string" &&
        parseFloat(afterDensity.paragraphMarginBottom) <= parseFloat(initial.paragraphMarginBottom),
      `切换紧凑后段落底部间距应更紧，初始 ${initial.paragraphMarginBottom}，实际 ${afterDensity.paragraphMarginBottom}`,
    );

    console.log(
      JSON.stringify(
        {
          ok: true,
          baseUrl: BASE_URL,
          workspaceId: fixture.workspaceId,
          documentId: fixture.documentId,
          initial,
          afterWide,
          afterSmall,
          afterDensity,
        },
        null,
        2,
      ),
    );
  } catch (error) {
    caughtError = error;
  } finally {
    if (fixture) {
      try {
        await cleanupDocuments(context.request, fixture.createdIds);
      } catch (cleanupError) {
        if (!caughtError) {
          caughtError = cleanupError;
        } else {
          console.error(
            `清理临时页面失败：${
              cleanupError instanceof Error
                ? cleanupError.stack || cleanupError.message
                : String(cleanupError)
            }`,
          );
        }
      }
    }
    await page.close().catch(() => undefined);
    await context.close().catch(() => undefined);
    await browser.close().catch(() => undefined);
  }

  if (caughtError) {
    throw caughtError;
  }
}

main().catch((error) => {
  console.error(error instanceof Error ? error.stack || error.message : String(error));
  process.exit(1);
});
