import { mkdir, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { mkdtemp, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { describe, it } from "node:test";
import assert from "node:assert/strict";

import {
  buildPmAdminRejectReworkPromptBlock,
  extractPmAdminRejectTodoSection,
  extractTaskIdPrefixesFromText,
  isTaskHotPathBody,
  resolveAdminRejectExecutionMode,
  PM_ADMIN_REJECT_TODO_HEADING,
  shouldEscalatePmChatToAdminRejectColdPath,
  shouldEscalatePmChatToAdminRejectHotPath,
} from "../pmAdminRejectPrompt.ts";

async function withTempProject(
  fn: (root: string) => Promise<void>,
): Promise<void> {
  const root = await mkdtemp(join(tmpdir(), "pm-admin-reject-"));
  try {
    await fn(root);
  } finally {
    await rm(root, { recursive: true, force: true });
  }
}

describe("pmAdminRejectPrompt", () => {
  it("extractPmAdminRejectTodoSection returns body when heading present", async () => {
    await withTempProject(async (root) => {
      const viewsDir = join(root, "fcop", "ledger", "views");
      await mkdir(viewsDir, { recursive: true });
      await writeFile(
        join(viewsDir, "PM.todo.md"),
        `# PM todo\n\n${PM_ADMIN_REJECT_TODO_HEADING}\n\n- TASK-20260606-007 file=fcop/_lifecycle/review/TASK-20260606-007-ADMIN-to-PM.md\n\n## Other\n`,
        "utf-8",
      );
      const body = extractPmAdminRejectTodoSection(root);
      assert.ok(body);
      assert.match(body, /TASK-20260606-007/);
    });
  });

  it("buildPmAdminRejectReworkPromptBlock includes Cold Path instructions", async () => {
    await withTempProject(async (root) => {
      const viewsDir = join(root, "fcop", "ledger", "views");
      await mkdir(viewsDir, { recursive: true });
      await writeFile(
        join(viewsDir, "PM.todo.md"),
        `${PM_ADMIN_REJECT_TODO_HEADING}\n\n- TASK-20260606-007\n`,
        "utf-8",
      );
      const block = buildPmAdminRejectReworkPromptBlock(root);
      assert.ok(block);
      assert.match(block, /Cold Path/);
      assert.match(block, /write_task/);
      assert.match(block, /references/);
      assert.match(block, /禁止.*YAML/);
      assert.match(block, /禁止.*write_report/);
      assert.doesNotMatch(block, /body.*parent:/);
      assert.match(block, /GoogleGenAiAdapter|Google 工具运行时|Adapter 六层/);
      assert.doesNotMatch(block, /Google 工具箱.*=.*read_file/);
      assert.doesNotMatch(block, /Gemini SDK 默认工具/);
    });
  });

  it("returns null when no admin reject section", async () => {
    await withTempProject(async (root) => {
      const viewsDir = join(root, "fcop", "ledger", "views");
      await mkdir(viewsDir, { recursive: true });
      await writeFile(join(viewsDir, "PM.todo.md"), "# PM todo\n", "utf-8");
      assert.equal(extractPmAdminRejectTodoSection(root), null);
      assert.equal(buildPmAdminRejectReworkPromptBlock(root), null);
    });
  });

  it("shouldEscalatePmChatToAdminRejectColdPath when message cites task in section", () => {
    const section = "- TASK-20260606-007 file=fcop/_lifecycle/review/TASK-20260606-007-ADMIN-to-PM.md";
    assert.equal(
      shouldEscalatePmChatToAdminRejectColdPath({
        message: "请处理 TASK-20260606-007 打回",
        adminRejectSection: section,
      }),
      true,
    );
    assert.equal(
      shouldEscalatePmChatToAdminRejectColdPath({
        message: "又是死循环！",
        adminRejectSection: section,
      }),
      true,
    );
    assert.equal(
      shouldEscalatePmChatToAdminRejectColdPath({
        message: "今天天气怎么样",
        adminRejectSection: section,
      }),
      false,
    );
  });

  it("buildPmAdminRejectReworkPromptBlock skips read when taskBodyPreloaded", async () => {
    await withTempProject(async (root) => {
      const viewsDir = join(root, "fcop", "ledger", "views");
      await mkdir(viewsDir, { recursive: true });
      await writeFile(
        join(viewsDir, "PM.todo.md"),
        `${PM_ADMIN_REJECT_TODO_HEADING}\n\n- TASK-20260606-007\n`,
        "utf-8",
      );
      const block = buildPmAdminRejectReworkPromptBlock(root, {
        taskBodyPreloaded: true,
      });
      assert.ok(block);
      assert.match(block, /跳过 read/);
      assert.doesNotMatch(block, /read_file.*file=/);
    });
  });

  it("extractTaskIdPrefixesFromText finds TASK ids", () => {
    const ids = extractTaskIdPrefixesFromText(
      "重做 TASK-20260606-007 并派 DEV",
    );
    assert.deepEqual(ids, ["TASK-20260606-007"]);
  });

  it("isTaskHotPathBody detects Hot Path from task markdown", () => {
    const body = [
      "## 背景",
      "本任务为 **Hot Path**：PM 亲自执行，**不得**向下游派发 DEV/QA/OPS。",
    ].join("\n");
    assert.equal(isTaskHotPathBody(body), true);
  });

  it("resolveAdminRejectExecutionMode returns hot when task on disk is Hot Path", async () => {
    await withTempProject(async (root) => {
      const viewsDir = join(root, "fcop", "ledger", "views");
      const activeDir = join(root, "fcop", "_lifecycle", "active");
      await mkdir(viewsDir, { recursive: true });
      await mkdir(activeDir, { recursive: true });
      await writeFile(
        join(viewsDir, "PM.todo.md"),
        `${PM_ADMIN_REJECT_TODO_HEADING}\n\n- TASK-20260607-017\n`,
        "utf-8",
      );
      await writeFile(
        join(activeDir, "TASK-20260607-017-ADMIN-to-PM-google-gemini-smoke.md"),
        `---\nprotocol: fcop\n---\n\nHot Path：PM 亲自执行，不得向下游派发。\n`,
        "utf-8",
      );
      assert.equal(
        resolveAdminRejectExecutionMode({ projectRoot: root }),
        "hot",
      );
    });
  });

  it("buildPmAdminRejectReworkPromptBlock uses Hot Path when task declares PM 亲自执行", async () => {
    await withTempProject(async (root) => {
      const viewsDir = join(root, "fcop", "ledger", "views");
      const activeDir = join(root, "fcop", "_lifecycle", "active");
      await mkdir(viewsDir, { recursive: true });
      await mkdir(activeDir, { recursive: true });
      await writeFile(
        join(viewsDir, "PM.todo.md"),
        `${PM_ADMIN_REJECT_TODO_HEADING}\n\n- TASK-20260607-017\n`,
        "utf-8",
      );
      await writeFile(
        join(activeDir, "TASK-20260607-017-ADMIN-to-PM.md"),
        `---\n---\n\n**Hot Path**：PM 亲自执行，**不得**向下游派发。\n`,
        "utf-8",
      );
      const block = buildPmAdminRejectReworkPromptBlock(root);
      assert.ok(block);
      assert.match(block, /Hot Path/);
      assert.match(block, /fcop_check/);
      assert.match(block, /write_report\(status=done\)/);
      assert.match(block, /不代表可修改产品代码/);
      assert.match(block, /禁止.*edit 产品代码/);
      assert.match(block, /必须.*write_task.*派发/);
      assert.doesNotMatch(block, /禁止 write_task 向 DEV \/ QA \/ OPS 派发子任务/);
    });
  });

  it("isTaskHotPathBody detects Google PM 最小闭环 smoke (TASK-029 style, no Cold Path)", () => {
    const body = [
      "# 开启 Google PM 最小闭环冒烟测试。",
      "测试范围：",
      "- PM 不派发下游",
      "禁止：",
      "- 不调用 write_task",
      "- 不派 DEV / OPS / QA",
      "PM REPORT 必须说明：",
      "1. 本次是 Google PM 最小闭环冒烟。",
    ].join("\n");
    assert.equal(isTaskHotPathBody(body), true);
  });

  it("shouldEscalatePmChatToAdminRejectHotPath when Hot Path task on disk", async () => {
    await withTempProject(async (root) => {
      const viewsDir = join(root, "fcop", "ledger", "views");
      const activeDir = join(root, "fcop", "_lifecycle", "active");
      await mkdir(viewsDir, { recursive: true });
      await mkdir(activeDir, { recursive: true });
      const section = "- TASK-20260607-017 file=fcop/_lifecycle/active/TASK-20260607-017-ADMIN-to-PM.md";
      await writeFile(
        join(viewsDir, "PM.todo.md"),
        `${PM_ADMIN_REJECT_TODO_HEADING}\n\n${section}\n`,
        "utf-8",
      );
      await writeFile(
        join(activeDir, "TASK-20260607-017-ADMIN-to-PM-google-gemini-smoke.md"),
        `---\n---\n\nHot Path：PM 亲自执行，不得向下游派发。\n`,
        "utf-8",
      );
      assert.equal(
        shouldEscalatePmChatToAdminRejectHotPath({
          message: "重新做 TASK-20260607-017",
          adminRejectSection: section,
          projectRoot: root,
        }),
        true,
      );
      assert.equal(
        shouldEscalatePmChatToAdminRejectColdPath({
          message: "重新做 TASK-20260607-017",
          adminRejectSection: section,
          projectRoot: root,
        }),
        false,
      );
    });
  });
});
