/**
 * @copyright NHCarrigan
 * @license Naomi's Public License
 * @author Naomi Carrigan
 */

import { readFile } from "node:fs/promises";
import { readdir } from "node:fs/promises";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import matter from "gray-matter";

interface Project {
    avatar?:     string;
    category:    string;
    description: string;
    name:        string;
    premium:     boolean;
    url?:        string;
    wip:         boolean;
  }
const getProjects = async(): Promise<Array<Project>> => {
  const request = await fetch("https://data.nhcarrigan.com/projects.json");
  const data = await request.json();
  return data as Array<Project>;
};

const projectNameMap: Record<string, string> = {
  "Naomi's Blog": "blog",
  "NHCarrigan Documentation": "docs",
  "Naomi's VSCode Themes": "vscode-themes",
  "Artists4Palestine Bot": "a4p-bot",
  "ESLint Config": "eslint-config",
  "Naomi's Adventure I: An Isekai Story": "naomis-adventure-i",
};

const excludedProjects = new Set<string>([
    "Translation Service",
    "Gitea"
]);

const convertTitleCaseToKebabCase = (string_: string): string => {
  return string_.toLowerCase().replace(/\s+/g, "-").replaceAll(/[:']/g, "");
};

describe("projects documentation", () => {
  it("should include all public projects", {timeout: 10000}, async() => {
    expect.hasAssertions();
    const projects = await getProjects();
    const docs = await readdir(join(__dirname, "..", "src", "content", "docs", "projects"));
    for (const project of projects) {
      if (excludedProjects.has(project.name)) {
        continue;
      }
      const page = docs.find((d) => {
        return project.name in projectNameMap
          ? d.split(".")[0] === projectNameMap[project.name]
          : d.split(".")[0] === convertTitleCaseToKebabCase(project.name);
      });
      expect(page, `Page not found for project ${project.name}`).toBeDefined();
      const content = await readFile(join(__dirname, "..", "src", "content", "docs", "projects", page!), "utf-8");
      const { data } = matter(content);
      expect(data.title, `Title not found for project ${project.name}`).toBeDefined();
      expect(data.title, `Title for project ${project.name} is not correct`).toBe(project.name);
      if (project.wip) {
        continue;
      }
      expect(content).not.toMatch(/:::note\nThis section is coming soon!\n:::/);
    }
  });
});
