import { afterEach, describe, expect, test } from "bun:test";
import { mkdir, rm, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import {
  contentRss,
  contentSitemap,
  createSearchIndex,
  defineCollection,
  localContentLoader,
  paginateContent,
  parseFrontmatter,
  remoteContentLoader,
  searchContent,
} from "../src/index.ts";
const roots: string[] = [];
afterEach(async () =>
  Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true }))),
);
const schema = {
  parse(input: unknown) {
    const value = input as Record<string, unknown>;
    if (typeof value.title !== "string") throw new Error("title required");
    return {
      title: value.title,
      draft: value.draft === true,
      version: String(value.version ?? "v1"),
    };
  },
};
describe("typed content collections", () => {
  test("loads, validates, renders, filters drafts and supports preview/versioning", async () => {
    const root = join(tmpdir(), `wrn-content-${crypto.randomUUID()}`);
    roots.push(root);
    await mkdir(root);
    await writeFile(
      join(root, "hello.md"),
      "---\ntitle: Hello\nversion: v1\n---\n# Welcome\nUseful documentation.",
    );
    await writeFile(join(root, "draft.mdx"), "---\ntitle: Draft\ndraft: true\n---\nHidden");
    const collection = defineCollection({
      name: "docs",
      schema,
      loader: localContentLoader(root),
      previewToken: "secret",
    });
    expect(await collection.load()).toHaveLength(1);
    const preview = await collection.load({ previewToken: "secret" });
    expect(preview).toHaveLength(2);
    expect(preview[1]!.html).toContain("<h1");
    expect(await collection.get("hello", { version: "v1" })).not.toBeNull();
  });
  test("builds search, pagination, RSS and sitemap outputs", async () => {
    const collection = defineCollection({
      name: "docs",
      schema,
      loader: remoteContentLoader("https://cms.test/docs", {
        fetch: async () =>
          new Response(
            JSON.stringify([
              { id: "guide", content: "---\ntitle: Guide\n---\n# Start\nSearch words" },
            ]),
          ) as any,
      }),
    });
    const entries = await collection.load();
    expect(searchContent(createSearchIndex(entries), "search words")).toHaveLength(1);
    expect(paginateContent(entries, 1, 1)).toMatchObject({ total: 1, totalPages: 1 });
    expect(contentRss(entries, { title: "Docs", baseUrl: "https://example.test/" })).toContain(
      "<rss",
    );
    expect(contentSitemap(entries, "https://example.test/")).toContain(
      "https://example.test/guide",
    );
  });
  test("rejects malformed frontmatter", () => {
    expect(() => parseFrontmatter("---\ntitle nope\n---\nbody")).toThrow("WRN-CONTENT-FRONTMATTER");
  });
});
