import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { runUpdate } from "./update";

describe("runUpdate", () => {
  let tmpDir: string;

  beforeEach(() => {
    tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "update-test-"));
  });

  afterEach(() => {
    fs.rmSync(tmpDir, { recursive: true, force: true });
  });

  it("updates skills and workflows by default", () => {
    const exitCode = runUpdate(tmpDir, []);
    expect(exitCode).toBe(0);

    const skillPath = path.join(
      tmpDir,
      ".agents",
      "skills",
      "erp-kit-module-1-requirements",
      "SKILL.md",
    );
    expect(fs.existsSync(skillPath)).toBe(true);

    const wfPath = path.join(tmpDir, ".github", "workflows", "erp-kit-check.yml");
    expect(fs.existsSync(wfPath)).toBe(true);
  });

  it("updates only skills when specified", () => {
    const exitCode = runUpdate(tmpDir, ["skills"]);
    expect(exitCode).toBe(0);

    const skillPath = path.join(
      tmpDir,
      ".agents",
      "skills",
      "erp-kit-module-1-requirements",
      "SKILL.md",
    );
    expect(fs.existsSync(skillPath)).toBe(true);

    const wfPath = path.join(tmpDir, ".github", "workflows", "erp-kit-check.yml");
    expect(fs.existsSync(wfPath)).toBe(false);
  });

  it("updates only workflows when specified", () => {
    const exitCode = runUpdate(tmpDir, ["workflows"]);
    expect(exitCode).toBe(0);

    const skillsDest = path.join(tmpDir, ".agents", "skills");
    expect(fs.existsSync(skillsDest)).toBe(false);

    const wfPath = path.join(tmpDir, ".github", "workflows", "erp-kit-check.yml");
    expect(fs.existsSync(wfPath)).toBe(true);
  });

  it("removes stale skills and replaces with current", () => {
    const staleDir = path.join(tmpDir, ".agents", "skills", "erp-kit-old-skill");
    fs.mkdirSync(staleDir, { recursive: true });
    fs.writeFileSync(path.join(staleDir, "SKILL.md"), "# Stale");
    runUpdate(tmpDir, ["skills"]);
    expect(fs.existsSync(staleDir)).toBe(false);
  });

  it("overwrites existing workflows", () => {
    const wfDir = path.join(tmpDir, ".github", "workflows");
    fs.mkdirSync(wfDir, { recursive: true });
    fs.writeFileSync(path.join(wfDir, "erp-kit-check.yml"), "# Old");
    runUpdate(tmpDir, ["workflows"]);
    const content = fs.readFileSync(path.join(wfDir, "erp-kit-check.yml"), "utf-8");
    expect(content).toContain("erp-kit Check");
  });

  it("refreshes .claude/skills when it is a copied directory (not a symlink)", () => {
    // Simulate a prior "copied" fallback: .claude/skills is a real directory with stale content
    const claudeSkills = path.join(tmpDir, ".claude", "skills");
    fs.mkdirSync(path.join(claudeSkills, "erp-kit-old"), { recursive: true });
    fs.writeFileSync(path.join(claudeSkills, "erp-kit-old", "SKILL.md"), "# Old");

    runUpdate(tmpDir, ["skills"]);

    // Stale skill should be gone from .claude/skills
    expect(fs.existsSync(path.join(claudeSkills, "erp-kit-old"))).toBe(false);
    // Current skills should be present
    expect(
      fs.existsSync(path.join(claudeSkills, "erp-kit-module-1-requirements", "SKILL.md")),
    ).toBe(true);
  });

  it("never touches config files", () => {
    const configPath = path.join(tmpDir, "license.config.json");
    fs.writeFileSync(configPath, '{"groups": ["notice"]}');
    runUpdate(tmpDir, []);
    const config = JSON.parse(fs.readFileSync(configPath, "utf-8")) as { groups: string[] };
    expect(config.groups).toEqual(["notice"]);
  });
});
