import fs from "fs";
import path from "path";
import matter from "gray-matter";

const CONTENT_DIR = path.join(process.cwd(), "content", "labs");
const CONTENT_EXTENSIONS = [".md", ".mdx"] as const;

export type LabSummary = {
  slug: string;
  title: string;
  description: string;
  fileName: string;
};

export type LabDocument = LabSummary & {
  content: string;
  data: Record<string, unknown>;
};

function toTitleCaseFromSlug(slug: string) {
  return slug.replace(/-/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
}

function getSlugFromFileName(fileName: string) {
  return fileName.replace(/\.(md|mdx)$/i, "");
}

function hasSupportedExtension(fileName: string) {
  return CONTENT_EXTENSIONS.some((ext) => fileName.toLowerCase().endsWith(ext));
}

export function listLabFiles() {
  if (!fs.existsSync(CONTENT_DIR)) {
    return [];
  }

  return fs
    .readdirSync(CONTENT_DIR)
    .filter((fileName) => hasSupportedExtension(fileName))
    .sort((a, b) => a.localeCompare(b));
}

export function getLabSummaries() {
  return listLabFiles().map((fileName) => {
    const filePath = path.join(CONTENT_DIR, fileName);
    const source = fs.readFileSync(filePath, "utf8");
    const { data } = matter(source);
    const slug = getSlugFromFileName(fileName);

    const title =
      typeof data.title === "string" && data.title.trim().length > 0
        ? data.title
        : toTitleCaseFromSlug(slug);

    const description =
      typeof data.description === "string" && data.description.trim().length > 0
        ? data.description
        : "";

    return {
      slug,
      title,
      description,
      fileName,
    } satisfies LabSummary;
  });
}

export function getLabDocument(slug: string): LabDocument | null {
  const fileName = listLabFiles().find((candidateFileName) => {
    return getSlugFromFileName(candidateFileName) === slug;
  });

  if (!fileName) {
    return null;
  }

  const filePath = path.join(CONTENT_DIR, fileName);
  const source = fs.readFileSync(filePath, "utf8");
  const { content, data } = matter(source);

  const title =
    typeof data.title === "string" && data.title.trim().length > 0
      ? data.title
      : toTitleCaseFromSlug(slug);

  const description =
    typeof data.description === "string" && data.description.trim().length > 0
      ? data.description
      : "";

  return {
    slug,
    title,
    description,
    fileName,
    content,
    data,
  };
}
