import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { promises as fs } from "node:fs";
import os from "node:os";
import path from "node:path";

let generatedRoot = "";

const JS_ASSET_NAME = "mnote-tree-shell-runtime.js";
const WASM_ASSET_NAME = "mnote-tree-shell-runtime_bg.wasm";

async function writeFixtureFile(relativePath: string, content: string | Uint8Array) {
  const absolutePath = path.join(generatedRoot, relativePath);
  await fs.mkdir(path.dirname(absolutePath), { recursive: true });
  await fs.writeFile(absolutePath, content);
}

describe("/api/tree-shell-runtime/[...asset] route", () => {
  beforeEach(async () => {
    generatedRoot = await fs.mkdtemp(path.join(os.tmpdir(), "mnote-tree-shell-runtime-"));
    process.env.TREE_SHELL_RUNTIME_GENERATED_ROOT = generatedRoot;
  });

  afterEach(async () => {
    delete process.env.TREE_SHELL_RUNTIME_GENERATED_ROOT;
    await fs.rm(generatedRoot, { recursive: true, force: true });
    generatedRoot = "";
  });

  it("返回固定资源名 manifest，并暴露同源 js/wasm 资源路径", async () => {
    await writeFixtureFile(JS_ASSET_NAME, "export function reduceTreeShellRuntime() {}\n");
    await writeFixtureFile(WASM_ASSET_NAME, new Uint8Array([0x00, 0x61, 0x73, 0x6d]));

    const { GET } = await import("./route");
    const response = await GET(new Request("http://127.0.0.1:3000/api/tree-shell-runtime/manifest.json"), {
      params: Promise.resolve({ asset: ["manifest.json"] }),
    });

    expect(response.status).toBe(200);
    expect(response.headers.get("cache-control")).toBe("no-store");
    expect(await response.json()).toEqual({
      jsGlueAssetPath: `/api/tree-shell-runtime/${JS_ASSET_NAME}`,
      wasmAssetPath: `/api/tree-shell-runtime/${WASM_ASSET_NAME}`,
      assetPaths: [
        `/api/tree-shell-runtime/${JS_ASSET_NAME}`,
        `/api/tree-shell-runtime/${WASM_ASSET_NAME}`,
      ],
      generatedRootPath: generatedRoot.split(path.sep).join("/"),
    });
  });

  it("返回具体 wasm/js 资源内容，并拒绝越界路径", async () => {
    await writeFixtureFile(JS_ASSET_NAME, "export const runtimeVersion = 1;\n");
    await writeFixtureFile(WASM_ASSET_NAME, new Uint8Array([0x00, 0x61, 0x73, 0x6d]));

    const { GET } = await import("./route");

    const jsResponse = await GET(
      new Request(`http://127.0.0.1:3000/api/tree-shell-runtime/${JS_ASSET_NAME}`),
      { params: Promise.resolve({ asset: [JS_ASSET_NAME] }) },
    );
    expect(jsResponse.status).toBe(200);
    expect(jsResponse.headers.get("content-type")).toContain("application/javascript");
    expect(await jsResponse.text()).toContain("runtimeVersion");

    const wasmResponse = await GET(
      new Request(`http://127.0.0.1:3000/api/tree-shell-runtime/${WASM_ASSET_NAME}`),
      { params: Promise.resolve({ asset: [WASM_ASSET_NAME] }) },
    );
    expect(wasmResponse.status).toBe(200);
    expect(wasmResponse.headers.get("content-type")).toBe("application/wasm");
    expect(new Uint8Array(await wasmResponse.arrayBuffer())).toEqual(
      new Uint8Array([0x00, 0x61, 0x73, 0x6d]),
    );

    const invalidResponse = await GET(
      new Request("http://127.0.0.1:3000/api/tree-shell-runtime/../../secret.txt"),
      { params: Promise.resolve({ asset: ["..", "..", "secret.txt"] }) },
    );
    expect(invalidResponse.status).toBe(400);
    expect(await invalidResponse.json()).toEqual({
      error: "非法 tree shell runtime 资源路径",
    });
  });
});
