#!/usr/bin/env node
"use strict";

const assert = require("node:assert");
const { chromium } = require("playwright");

const BASE_URL = (process.env.MNOTE_WEB_SMOKE_BASE_URL || "http://127.0.0.1:3000").replace(/\/+$/, "");
const UI_TIMEOUT_MS = Number(process.env.MNOTE_SMOKE_UI_TIMEOUT_MS || 30_000);

async function quickLogin(page) {
  await page.goto(`${BASE_URL}/auth`, { waitUntil: "domcontentloaded", timeout: UI_TIMEOUT_MS });
  const quickLoginButton = page.getByRole("button", { name: "测试账号快速登录" });
  if (await quickLoginButton.count()) {
    await quickLoginButton.click({ timeout: UI_TIMEOUT_MS });
    await page.waitForURL((url) => url.pathname === "/", { timeout: UI_TIMEOUT_MS }).catch(() => undefined);
  }
}

async function main() {
  const browser = await chromium.launch({ headless: process.env.HEADFUL !== "1" });
  const context = await browser.newContext({ viewport: { width: 1440, height: 900 } });
  await context.addInitScript(() => {
    const sources = [];
    class FakeEventSource {
      constructor(url) {
        this.url = String(url || "");
        this.readyState = 1;
        this.listeners = new Map();
        sources.push(this);
      }

      addEventListener(type, listener) {
        const listeners = this.listeners.get(type) || [];
        listeners.push(listener);
        this.listeners.set(type, listeners);
      }

      close() {
        this.readyState = 2;
      }

      emit(type, data) {
        const event = { type, data: JSON.stringify(data) };
        for (const listener of this.listeners.get(type) || []) listener(event);
      }
    }
    window.EventSource = FakeEventSource;
    window.__mnoteFakeLocalFolderEventSources = sources;
  });
  const page = await context.newPage();
  try {
    await quickLogin(page);
    await page.goto(BASE_URL, { waitUntil: "domcontentloaded", timeout: UI_TIMEOUT_MS });
    await page.getByRole("button", { name: "新建页面" }).first().click({ timeout: UI_TIMEOUT_MS });
    await page.waitForURL((url) => url.pathname.startsWith("/documents/"), { timeout: UI_TIMEOUT_MS });
    const documentId = decodeURIComponent(new URL(page.url()).pathname.split("/").filter(Boolean).pop() || "");
    assert(documentId.startsWith("local-md:"), `新建页面应进入本地 Markdown 文档，实际 documentId=${documentId}`);

    const editor = page.locator('.document-pane[data-pane-role="primary"] .editor-surface .ProseMirror[contenteditable="true"]').first();
    await editor.waitFor({ state: "visible", timeout: UI_TIMEOUT_MS });
    await editor.click({ timeout: UI_TIMEOUT_MS });
    await page.keyboard.type("122", { delay: 5 });

    await page.evaluate((documentId) => {
      const source = window.__mnoteFakeLocalFolderEventSources?.[0];
      if (!source) throw new Error("missing_fake_event_source");
      source.emit("change", {
        sourceKind: "local_folder",
        rootUri: new URL(window.location.href).searchParams.get("rootUri") || "",
        documentId,
        relativePath: documentId.slice("local-md:".length),
        eventKind: "Create(File)",
        revision: Date.now(),
      });
    }, documentId);

    await page.waitForTimeout(1000);
    const state = await page.evaluate(() => ({
      status: document.querySelector("[data-runtime-editor-status]")?.getAttribute("data-runtime-editor-status") || "",
      conflict: Boolean(document.querySelector('[data-testid="mnote-editor-conflict-panel"]')),
      text: document.querySelector(".ProseMirror")?.innerText || "",
    }));

    assert.equal(state.conflict, false, `新建页面自身 Create(File) 事件不应触发冲突：${JSON.stringify(state)}`);
    assert(state.text.includes("122"), `用户刚输入的内容应保留：${JSON.stringify(state)}`);
    console.log(JSON.stringify({ ok: true, documentId, state }, null, 2));
  } finally {
    await context.close().catch(() => undefined);
    await browser.close().catch(() => undefined);
  }
}

main().catch((error) => {
  console.error(error && error.stack ? error.stack : error);
  process.exit(1);
});
