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

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

async function main() {
  const suffix = Date.now().toString(36);
  const title = `TEST-HERMES-AI-smoke-${suffix}`;
  const sessionId = `mnote_smoke_${suffix}`;
  const runId = `run_smoke_${suffix}`;
  let sessionDetailHits = 0;
  const captured = [];
  const createdIds = [];
  const browser = await chromium.launch({ headless: true });
  const context = await browser.newContext({ viewport: { width: 1440, height: 960 } });
  const page = await context.newPage();

  try {
    await page.route("**/api/ai-agent/run", async (route) => {
      throw new Error(`页面 AI 不应请求旧 /api/ai-agent/run: ${route.request().url()}`);
    });
    await page.route("**/api/hermes/client/sessions", async (route) => {
      captured.push({ kind: "session", method: route.request().method(), body: route.request().postData() || "" });
      await route.fulfill({
        status: 200,
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          ok: true,
          sessionId,
          title: "当前页问答",
          traceId: "trace_smoke",
          persistence: "hermes_on_first_run",
        }),
      });
    });
    await page.route(`**/api/hermes/client/sessions/${sessionId}`, async (route) => {
      sessionDetailHits += 1;
      captured.push({ kind: "session-detail", method: route.request().method(), body: "" });
      await route.fulfill({
        status: 200,
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          ok: true,
          sessionId,
          traceId: "trace_restore",
          session: {
            sessionId,
            messages: [
              { role: "user", content: `请总结 ${title}` },
              { role: "tool", content: "mnote.page.get" },
              { role: "assistant", content: "Smoke restored from Hermes session" },
            ],
          },
        }),
      });
    });
    await page.route("**/api/hermes/client/runs", async (route) => {
      captured.push({ kind: "run", method: route.request().method(), body: route.request().postData() || "" });
      await route.fulfill({
        status: 200,
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          ok: true,
          sessionId,
          runId,
          events: [],
          traceId: "trace_smoke",
        }),
      });
    });
    await page.route(`**/api/hermes/client/events/${runId}`, async (route) => {
      captured.push({ kind: "events", method: route.request().method(), body: "" });
      await route.fulfill({
        status: 200,
        headers: { "content-type": "text/event-stream; charset=utf-8" },
        body:
          `data: ${JSON.stringify({ event: "tool.started", run_id: runId, session_id: sessionId, name: "mnote.page.get" })}\n\n` +
          `data: ${JSON.stringify({ event: "tool.completed", run_id: runId, session_id: sessionId, name: "mnote.page.get" })}\n\n` +
          `data: ${JSON.stringify({ event: "message.delta", run_id: runId, session_id: sessionId, delta: "Smoke " })}\n\n` +
          `data: ${JSON.stringify({ event: "message.delta", run_id: runId, session_id: sessionId, delta: "response" })}\n\n` +
          `data: ${JSON.stringify({ event: "run.completed", run_id: runId, session_id: sessionId, output: "Smoke response" })}\n\n`,
      });
    });

    await ensureAuthenticated(page, context.request);
    const target = await createTempDocument(context.request);
    createdIds.push(target.documentId);
    await renameDocument(context.request, target.workspaceId, target.documentId, title);
    await page.goto(
      `${BASE_URL}/documents/${encodeURIComponent(target.documentId)}?workspaceId=${encodeURIComponent(target.workspaceId)}`,
      { waitUntil: "domcontentloaded", timeout: UI_TIMEOUT_MS },
    );

    await page.getByTestId("wolai-floating-ai").click({ timeout: UI_TIMEOUT_MS });
    await page.locator("[data-page-ai-input]").fill(`请总结 ${title}`, { timeout: UI_TIMEOUT_MS });
    await page.locator('[data-page-ai-action="send"]').click({ timeout: UI_TIMEOUT_MS });
    await page.waitForFunction(
      () => (document.querySelector('[data-testid="wolai-page-ai-drawer"]')?.textContent || "").includes("Smoke response"),
      null,
      { timeout: UI_TIMEOUT_MS },
    );
    await page.waitForFunction(
      () => (document.querySelector('[data-testid="wolai-page-ai-drawer"]')?.textContent || "").includes("mnote.page.get"),
      null,
      { timeout: UI_TIMEOUT_MS },
    );

    const sessionRequest = captured.find((entry) => entry.kind === "session");
    const runRequest = captured.find((entry) => entry.kind === "run");
    const eventRequest = captured.find((entry) => entry.kind === "events");
    assert(sessionRequest, "未捕获 /api/hermes/client/sessions 请求");
    assert(runRequest, "未捕获 /api/hermes/client/runs 请求");
    assert(eventRequest, "未捕获 /api/hermes/client/events 请求");
    const runBody = JSON.parse(runRequest.body);
    assert.equal(runBody.sessionId, sessionId, "run 请求必须携带 Hermes sessionId");
    assert.equal(runBody.documentId, target.documentId, "run 请求必须携带 documentId");
    assert(runBody.pageContext, "run 请求必须携带 pageContext");

    await page.reload({ waitUntil: "domcontentloaded", timeout: UI_TIMEOUT_MS });
    await page.getByTestId("wolai-floating-ai").click({ timeout: UI_TIMEOUT_MS });
    await page.waitForFunction(
      () => (document.querySelector('[data-testid="wolai-page-ai-drawer"]')?.textContent || "").includes("Smoke restored from Hermes session"),
      null,
      { timeout: UI_TIMEOUT_MS },
    );
    await page.waitForFunction(
      () => (document.querySelector('[data-testid="wolai-page-ai-drawer"]')?.textContent || "").includes("mnote.page.get"),
      null,
      { timeout: UI_TIMEOUT_MS },
    );
    assert(sessionDetailHits > 0, "刷新后必须从 Hermes session detail 恢复消息，而不是从 mnote 本地消息数组恢复");
    const persisted = await page.evaluate(() => {
      const keys = Object.keys(window.localStorage).filter((key) => key.startsWith("hermes_page_ai_session:"));
      return keys.map((key) => ({ key, value: window.localStorage.getItem(key) }));
    });
    assert(
      persisted.every((entry) => !entry.value || !entry.value.includes("Smoke response")),
      "mnote localStorage 不应保存完整聊天消息内容",
    );

    console.log(
      JSON.stringify(
        {
          ok: true,
          baseUrl: BASE_URL,
          documentId: target.documentId,
          workspaceId: target.workspaceId,
          sessionId,
          runId,
          capturedKinds: captured.map((entry) => entry.kind),
          sessionDetailHits,
        },
        null,
        2,
      ),
    );
  } finally {
    await cleanupDocuments(context.request, createdIds).catch(() => undefined);
    await context.close().catch(() => undefined);
    await browser.close().catch(() => undefined);
  }
}

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