#!/usr/bin/env node
const assert = require("node:assert/strict");
const fs = require("node:fs");
const path = require("node:path");
const vm = require("node:vm");

const REPO_ROOT = path.resolve(__dirname, "..");
const RUNTIME_PATH = path.join(
  REPO_ROOT,
  "rust/crates/mnote-web/browser/sidebar-filetree-command-runtime.js",
);

function loadRuntimeFactory() {
  const source = fs
    .readFileSync(RUNTIME_PATH, "utf8")
    .replace(
      "export const createSidebarFileTreeCommandRuntime = (dependencies = {}) => {",
      "const createSidebarFileTreeCommandRuntime = (dependencies = {}) => {",
    );
  const context = {
    console,
    CustomEvent: class CustomEvent {
      constructor(type, init) {
        this.type = type;
        this.detail = init && init.detail;
      }
    },
    HTMLElement: class HTMLElement {},
    navigator: {
      clipboard: {
        writeText: async (text) => {
          context.__clipboardText = text;
        },
      },
    },
    document: {
      body: {},
      documentElement: {
        attrs: {},
        setAttribute(name, value) {
          this.attrs[name] = String(value);
        },
      },
      createElement() {
        return {};
      },
      querySelector() {
        return null;
      },
      querySelectorAll() {
        return [];
      },
    },
    window: {
      alert() {},
      confirm() {
        return true;
      },
      dispatchEvent() {},
    },
    URL,
    setTimeout,
    clearTimeout,
  };
  context.globalThis = context;
  vm.createContext(context);
  vm.runInContext(
    `${source}\nglobalThis.__factory = createSidebarFileTreeCommandRuntime;`,
    context,
    { filename: RUNTIME_PATH },
  );
  return context;
}

async function runCopyId(runtime, context, detail) {
  context.__clipboardText = "";
  runtime.handleTreeContextMenuAction("copy-id", detail, null);
  await new Promise((resolve) => setImmediate(resolve));
  return context.__clipboardText;
}

async function main() {
  const context = loadRuntimeFactory();
  const runtime = context.__factory({
    currentRootUri: () => "file:///mnt/Data1T/mnote",
    currentSourceKind: () => "local_folder",
    cssEscape: (value) => String(value).replace(/"/g, '\\"'),
    fileTreeRuntimeFunction: () => null,
    localFilePathFromAssetId: (assetId) =>
      String(assetId || "").replace(/^local-file:/, ""),
    resolveWorkspaceId: () => "local-folder",
    runtimeState: { activeTreeContextMenu: null },
    selectedSidebarFileTreeSelection: { selectedRowIds: new Set(), focusedRowId: null },
  });

  assert.equal(
    await runCopyId(runtime, context, {
      contextKind: "filetree",
      rowKind: "folder",
      documentId: "local-dir:docs",
      rowId: "local:folder:docs",
      title: "docs",
    }),
    "/mnt/Data1T/mnote/docs",
    "复制本地文件夹页面 ID 应得到绝对路径",
  );

  assert.equal(
    await runCopyId(runtime, context, {
      contextKind: "filetree",
      rowKind: "markdown",
      documentId: "local-md:docs~2FPage.md",
      rowId: "local:markdown:docs~2FPage.md",
      title: "Page",
    }),
    "/mnt/Data1T/mnote/docs/Page.md",
    "复制本地 Markdown 页面 ID 应得到绝对路径",
  );

  assert.equal(
    await runCopyId(runtime, context, {
      contextKind: "filetree",
      rowKind: "asset",
      assetId: "local-file:assets~2Freport.pdf",
      rowId: "local:asset:assets~2Freport.pdf",
      title: "report.pdf",
    }),
    "/mnt/Data1T/mnote/assets/report.pdf",
    "复制本地资源 ID 应得到绝对路径",
  );

  console.log(
    JSON.stringify(
      {
        ok: true,
        copied: [
          "/mnt/Data1T/mnote/docs",
          "/mnt/Data1T/mnote/docs/Page.md",
          "/mnt/Data1T/mnote/assets/report.pdf",
        ],
      },
      null,
      2,
    ),
  );
}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});
