import { execFile } from "node:child_process";
import { mkdir, mkdtemp, rm, symlink, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import { promisify } from "node:util";
import { afterEach, describe, expect, it } from "vitest";

const execute = promisify(execFile);
const temporaryRoots: string[] = [];

describe("legacy project manifest builder", () => {
  afterEach(async () => {
    while (temporaryRoots.length > 0) {
      const root = temporaryRoots.pop();
      if (root !== undefined) await rm(root, { recursive: true, force: true });
    }
  });

  it("stops at a project root and excludes trash projects", async () => {
    const root = await mkdtemp(join(tmpdir(), "cph-legacy-manifest-"));
    temporaryRoots.push(root);
    const projectRoot = join(root, "物理", "legacy__牛顿力学");
    await mkdir(join(projectRoot, "workspace", "nested"), { recursive: true });
    await mkdir(join(projectRoot, "_raw"), { recursive: true });
    await mkdir(join(root, ".trash", "deleted"), { recursive: true });
    await writeFile(join(projectRoot, "project.json"), JSON.stringify({
      id: "legacy",
      name: "牛顿力学",
      folderPath: ["物理"],
    }));
    await writeFile(join(projectRoot, "workspace", "nested", "project.json"), "not metadata");
    await writeFile(join(projectRoot, "_raw", "project.json"), "not metadata");
    await writeFile(join(root, ".trash", "deleted", "project.json"), JSON.stringify({
      id: "deleted",
      name: "Deleted",
    }));

    const { stdout } = await execute(process.execPath, [
      resolve("deploy/build_legacy_project_manifest.mjs"),
      root,
    ]);

    expect(JSON.parse(stdout)).toEqual([{
      legacyId: "legacy",
      name: "牛顿力学",
      folderPath: ["物理"],
      sourceRelativePath: "物理/legacy__牛顿力学",
    }]);
  });

  it("reports untracked symlinked entries instead of silently omitting them", async () => {
    const root = await mkdtemp(join(tmpdir(), "cph-legacy-manifest-link-"));
    temporaryRoots.push(root);
    await symlink("/tmp", join(root, "linked-project"));

    const result = await execute(process.execPath, [
      resolve("deploy/build_legacy_project_manifest.mjs"),
      root,
    ]);
    expect(result.stderr).toContain("skip untracked symbolic link");
    expect(JSON.parse(result.stdout)).toEqual([]);
  });
});
