import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { spawnSync } from "node:child_process";

import {
  gitSafeEnv,
  initIsolatedGitRepo,
  loadFreshEsm,
  pathWithPrependedBin,
  read,
  writeNodeCommandShim
} from "../helpers.ts";
import type { PlatformSyncModule } from "../helpers.ts";

function write(filePathname: string, content: string) {
  fs.mkdirSync(path.dirname(filePathname), { recursive: true });
  fs.writeFileSync(filePathname, content, "utf8");
}

function writeJson(filePathname: string, value: unknown) {
  write(filePathname, JSON.stringify(value, null, 2));
}

function linkNodeModules(tempRoot: string) {
  const source = path.join(process.cwd(), "node_modules");
  const target = path.join(tempRoot, "node_modules");
  fs.symlinkSync(source, target, process.platform === "win32" ? "junction" : "dir");
}

function writeFakeGh(filePathname: string) {
  const scriptPath = `${filePathname}.cjs`;
  write(scriptPath, read("tests/fixtures/validate-artifact/fake-gh.js"));
  if (process.platform === "win32") {
    writeNodeCommandShim(filePathname, scriptPath);
  } else {
    write(filePathname, `#!/bin/sh\nexec "${process.execPath}" "${scriptPath}" "$@"\n`);
    fs.chmodSync(filePathname, 0o755);
  }
  return {
    AGENT_INFRA_GH_BIN: process.execPath,
    AGENT_INFRA_GH_ARGS_JSON: JSON.stringify([scriptPath])
  };
}

function writeTask(taskDir: string) {
  write(path.join(taskDir, "task.md"), [
    "---",
    "id: TASK-20260328-000001",
    "type: refactor",
    "workflow: refactoring",
    "status: active",
    "created_at: 2026-03-28 00:00:00+00:00",
    "updated_at: 2026-03-28 00:00:00+00:00",
    "current_step: implementation",
    "assigned_to: codex",
    "issue_number: 65",
    "---",
    "",
    "# 任务：Adapter defaults",
    ""
  ].join("\n"));
}

function runValidator(scriptPath: string, taskDir: string, skill: string, env: NodeJS.ProcessEnv) {
  return spawnSync(process.execPath, [scriptPath, "check", "platform-sync", taskDir, "implementation.md", "--skill", skill], {
    cwd: path.dirname(path.dirname(path.dirname(scriptPath))),
    encoding: "utf8",
    env: gitSafeEnv(env)
  });
}

test("platform-sync adapters expose default status labels and markers", async () => {
  for (const relativePath of [
    ".agents/scripts/platform-adapters/platform-sync.js",
    "templates/.agents/scripts/platform-adapters/platform-sync.github.js"
  ]) {
    const { getDefaults } = await loadFreshEsm<PlatformSyncModule>(relativePath);
    const defaults = getDefaults();

    assert.equal(defaults.statusLabels.inProgress, "status: in-progress");
    assert.equal(defaults.statusLabels.pendingDesignWork, "status: pending-design-work");
    assert.equal(defaults.statusLabels.waitingForTriage, "status: waiting-for-triage");
    assert.equal(defaults.markers.task, "<!-- sync-issue:{task-id}:task -->");
    assert.equal(defaults.markers.artifact, "<!-- sync-issue:{task-id}:{artifact-stem} -->");
    assert.equal(defaults.markers.artifactChunk, "<!-- sync-issue:{task-id}:{artifact-stem}:{part}/{total} -->");
    assert.equal(defaults.markers.prSummary, "<!-- sync-pr:{task-id}:summary -->");
  }
});

test("platform-sync stub adapter exposes empty defaults", async () => {
  const { getDefaults } = await loadFreshEsm<PlatformSyncModule>("templates/.agents/scripts/platform-adapters/platform-sync.js");
  assert.deepEqual(getDefaults(), { statusLabels: {}, markers: {} });
});

test("platform-sync verification keys override legacy literal values", () => {
  const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "agent-infra-platform-defaults-"));
  const taskDir = path.join(tempRoot, "TASK-20260328-000001");
  const binDir = path.join(tempRoot, "bin");
  const ghPath = path.join(binDir, "gh");
  const scriptCopy = path.join(tempRoot, ".agents/scripts/validate-artifact.js");
  const adapterCopy = path.join(tempRoot, ".agents/scripts/platform-adapters/platform-sync.js");
  const issuePath = path.join(tempRoot, "issue.json");
  const commentsPath = path.join(tempRoot, "comments.json");

  try {
    initIsolatedGitRepo(tempRoot, { remote: "git@github.com:fitlab-ai/agent-infra.git" });
    write(path.join(tempRoot, "package.json"), JSON.stringify({ type: "module" }));
    linkNodeModules(tempRoot);
    write(scriptCopy, read(".agents/scripts/validate-artifact.js"));
    write(adapterCopy, read(".agents/scripts/platform-adapters/platform-sync.js"));
    const ghEnv = writeFakeGh(ghPath);
    writeTask(taskDir);
    writeJson(issuePath, {
      state: "OPEN",
      labels: [{ name: "status: in-progress" }],
      body: "",
      milestone: null
    });
    writeJson(commentsPath, [
      { body: "<!-- sync-issue:TASK-20260328-000001:implementation -->\n## Implementation" }
    ]);

    writeJson(path.join(tempRoot, ".agents/skills/key-priority/config/verify.json"), {
      checks: {
        "platform-sync": {
          when: "issue_number_exists",
          expected_status_label: "status: blocked",
          expected_status_label_key: "inProgress",
          expected_comment_marker: "<!-- sync-issue:{task-id}:wrong -->",
          expected_comment_marker_key: "artifact"
        }
      }
    });

    const result = runValidator(scriptCopy, taskDir, "key-priority", {
      ...process.env,
      ...ghEnv,
      PATH: pathWithPrependedBin(binDir),
      GH_FAKE_ISSUE_PATH: issuePath,
      GH_FAKE_COMMENTS_PATH: commentsPath,
      GH_FAKE_ISSUE_NUMBER: "65"
    });

    assert.equal(result.status, 0, result.stderr);
  } finally {
    fs.rmSync(tempRoot, { recursive: true, force: true });
  }
});

test("platform-sync verification keeps legacy literal fallback", () => {
  const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "agent-infra-platform-legacy-"));
  const taskDir = path.join(tempRoot, "TASK-20260328-000001");
  const binDir = path.join(tempRoot, "bin");
  const ghPath = path.join(binDir, "gh");
  const scriptCopy = path.join(tempRoot, ".agents/scripts/validate-artifact.js");
  const adapterCopy = path.join(tempRoot, ".agents/scripts/platform-adapters/platform-sync.js");
  const issuePath = path.join(tempRoot, "issue.json");

  try {
    initIsolatedGitRepo(tempRoot, { remote: "git@github.com:fitlab-ai/agent-infra.git" });
    write(path.join(tempRoot, "package.json"), JSON.stringify({ type: "module" }));
    linkNodeModules(tempRoot);
    write(scriptCopy, read(".agents/scripts/validate-artifact.js"));
    write(adapterCopy, read(".agents/scripts/platform-adapters/platform-sync.js"));
    const ghEnv = writeFakeGh(ghPath);
    writeTask(taskDir);
    writeJson(issuePath, {
      state: "OPEN",
      labels: [{ name: "status: in-progress" }],
      body: "",
      milestone: null
    });

    writeJson(path.join(tempRoot, ".agents/skills/legacy/config/verify.json"), {
      checks: {
        "platform-sync": {
          when: "issue_number_exists",
          expected_status_label: "status: in-progress"
        }
      }
    });

    const result = runValidator(scriptCopy, taskDir, "legacy", {
      ...process.env,
      ...ghEnv,
      PATH: pathWithPrependedBin(binDir),
      GH_FAKE_ISSUE_PATH: issuePath
    });

    assert.equal(result.status, 0, result.stderr);
  } finally {
    fs.rmSync(tempRoot, { recursive: true, force: true });
  }
});
