import { describe, test, expect } from "bun:test";
import { slugify, buildBranchName, buildBranchPrefix } from "@/utils/slug.js";

// NOTE: src/utils/slug.ts hard-codes "fix/" in buildBranchName rather than
// importing BRANCH_PREFIX from src/core/constants.ts. The tests below pin the
// literal behavior of the function. If the source is later refactored to use
// the constant, update these assertions accordingly.

describe("slugify", () => {
  test("lowercases and hyphenates words", () => {
    expect(slugify("Hello World")).toBe("hello-world");
  });

  test("collapses multiple whitespace and trims", () => {
    expect(slugify("  Multiple   spaces  ")).toBe("multiple-spaces");
  });

  test("drops diacritics and non-ASCII characters (no transliteration)", () => {
    // The implementation replaces anything outside [a-z0-9] with hyphens,
    // so accented chars like á and ñ are removed entirely rather than
    // transliterated to their ASCII equivalents.
    expect(slugify("Áccents & Ñiñes")).toBe("ccents-i-es");
  });

  test("converts path separators to hyphens", () => {
    expect(slugify("a/b\\c")).toBe("a-b-c");
  });

  test("returns empty string for empty input", () => {
    expect(slugify("")).toBe("");
  });
});

describe("buildBranchName", () => {
  test("returns the expected format using BRANCH_PREFIX, issue key, and slugified summary", () => {
    const result = buildBranchName("SQDP-123", "Fix the thing");
    expect(result).toBe("fix/SQDP-123-fix-the-thing");
  });

  test("slug portion is capped at 48 characters (full branch name may exceed 48)", () => {
    const longSummary =
      "This is a very long summary that should be truncated to fit within the maximum length";
    const result = buildBranchName("SQDP-123", longSummary);

    // The slug itself is capped at MAX_SLUG_LENGTH (48), but the full branch
    // name includes the prefix and issue key so it exceeds 48.
    const slugPortion = result.slice("fix/SQDP-123-".length);
    expect(slugPortion.length).toBeLessThanOrEqual(48);
    expect(result).toBe("fix/SQDP-123-this-is-a-very-long-summary-that-should-be-trunc");
  });

  test("output contains no whitespace and no uppercase outside the issue key", () => {
    const result = buildBranchName("PROJ-999", "Some Feature With CAPS");
    expect(result).not.toMatch(/\s/);
    // Everything after the issue key prefix should be lowercase
    const afterKey = result.slice("fix/PROJ-999-".length);
    expect(afterKey).toBe(afterKey.toLowerCase());
  });
});

describe("buildBranchPrefix", () => {
  test("is the summary-independent prefix of every branch for an issue", () => {
    const prefix = buildBranchPrefix("SQDP-1");
    expect(prefix).toBe("fix/SQDP-1-");
    // Branches built from different summaries all share the prefix.
    expect(buildBranchName("SQDP-1", "fix login bug").startsWith(prefix)).toBe(true);
    expect(buildBranchName("SQDP-1", "BACKEND | fix login bug").startsWith(prefix)).toBe(true);
  });

  test("trailing dash disambiguates keys that share a leading substring", () => {
    // fix/SQDP-1- must NOT be a prefix of a SQDP-10 branch.
    expect(buildBranchName("SQDP-10", "x").startsWith(buildBranchPrefix("SQDP-1"))).toBe(false);
  });
});
