import { getCollection, type CollectionEntry } from 'astro:content';

export type ContentType = 'article' | 'page' | 'element';

export interface ResolvedEntry {
  type: ContentType;
  path: string;
  entry:
    | CollectionEntry<'pages'>
    | CollectionEntry<'articles'>
    | CollectionEntry<'elements'>;
}

function buildPath(
  slug: string,
  parentSlug: string | null,
  articles: CollectionEntry<'articles'>[],
  visited: Set<string> = new Set(),
): string {
  if (!parentSlug) return slug;
  if (visited.has(parentSlug)) {
    console.warn(`Circular reference detected at ${parentSlug}`);
    return slug;
  }
  visited.add(parentSlug);

  const parent = articles.find((a) => a.slug === parentSlug);
  if (!parent) return slug;

  const parentPath = buildPath(
    parent.slug,
    parent.data.parent ?? null,
    articles,
    visited,
  );

  return `${parentPath}/${slug}`;
}

function resolveArticles(
  articles: CollectionEntry<'articles'>[],
): ResolvedEntry[] {
  return articles
    .filter((entry) => entry.data.status === 'published')
    .map((entry) => ({
      type: 'article' as const,
      path: buildPath(entry.slug, entry.data.parent ?? null, articles),
      entry,
    }));
}

interface GlobEntry {
  id: string;
  data: { status: string; parent?: string | null };
}

function resolveGlobCollection(
  collection: GlobEntry[],
  type: ContentType,
  articles: CollectionEntry<'articles'>[],
): { type: ContentType; path: string; entry: GlobEntry }[] {
  return collection
    .filter((entry) => entry.data.status === 'published')
    .map((entry) => ({
      type,
      path: buildPath(entry.id, entry.data.parent ?? null, articles),
      entry,
    }));
}

export async function resolveAllPaths(): Promise<ResolvedEntry[]> {
  const articles = await getCollection('articles');
  const elements = await getCollection('elements');
  const pages = await getCollection('pages');

  const resolvedPages: ResolvedEntry[] = pages.map((page) => ({
    type: 'page' as const,
    path: `static/${page.slug}`,
    entry: page,
  }));

  return [
    ...resolveArticles(articles),
    ...resolveGlobCollection(elements, 'element', articles),
    ...resolvedPages,
  ] as ResolvedEntry[];
}
