import { loader, update } from 'fumadocs-core/source';
import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons';
import { docsContentRoute, docsRoute } from './shared';
import { defineDocs } from 'fumadocs-mdx/macro';
import { metaSchema, pageSchema } from 'fumadocs-core/source/schema';
import { z } from 'zod';
import { i18n } from './i18n';

const docs = defineDocs({
  dir: 'content/docs',
  docs: {
    /**
     * `verified` est la date à laquelle quelqu'un a constaté que la page décrit
     * encore l'état réel du système. Une page de configuration devient fausse à
     * la seconde où quelqu'un change un réglage, et rien ne prévient : afficher
     * cette date laisse le lecteur juger lui-même s'il peut s'y fier.
     */
    schema: pageSchema.extend({
      verified: z.string().optional(),

      /**
       * Date de l'événement, pour les traces du journal. Distincte de
       * `verified` : celle-ci dit quand quelque chose s'est produit, l'autre
       * quand quelqu'un a constaté qu'une page décrivait encore la réalité.
       */
      date: z.string().optional(),
    }),
    postprocess: {
      includeProcessedMarkdown: true,
    },
  },
  meta: {
    schema: metaSchema,
  },
});

export type Permission = 'anonymous' | 'member';

/**
 * L'accès est limité à l'entrée du loader, pas au rendu.
 *
 * Pour un anonyme la source ne contient aucune page : l'arbre de navigation,
 * l'index de recherche et les exports llms sont vides par construction, même si
 * un contrôle venait à manquer quelque part. Le contenu n'est pas caché, il
 * n'existe pas.
 *
 * `docs.toFumadocsSource()` est appelé **à l'intérieur** de cette fonction, une
 * fois par permission. C'est indispensable : `update()` mute la source en place
 * (`fumadocs-core/dist/loader-cKlyDdAK.js:95`) et une source partagée entre les
 * deux permissions serait vidée pour tout le monde dès la première construction
 * anonyme. `toFumadocsSource()` rend un objet neuf à chaque appel
 * (`fumadocs-mdx/dist/runtime/server.js:77`), ce qui rend la mutation sûre.
 */
function build(permission: Permission) {
  const filtered = update(docs.toFumadocsSource())
    .files((files) =>
      files.filter((file) => {
        // Les fichiers meta ne portent aucun contenu, ils structurent l'arbre.
        if (file.type === 'meta') return true;

        return permission === 'member';
      }),
    )
    .build();

  return loader({
    baseUrl: docsRoute,
    source: filtered,
    plugins: [lucideIconsPlugin()],
    i18n,
  });
}

// Deux permissions seulement : chaque loader est construit au plus une fois.
const built = new Map<Permission, ReturnType<typeof build>>();

export function getSource(permission: Permission) {
  const cached = built.get(permission);
  if (cached) return cached;

  const source = build(permission);
  built.set(permission, source);
  return source;
}

export type Source = ReturnType<typeof build>;
export type SourcePage = Source['$inferPage'];

export function getPageMarkdownUrl(page: SourcePage) {
  const segments = [...page.slugs, 'content.md'];

  return {
    segments,
    url: '/' + [page.locale, ...docsContentRoute.split('/'), ...segments].filter(Boolean).join('/'),
  };
}

export async function getLLMText(page: SourcePage) {
  const processed = await page.data.getText('processed');

  return `# ${page.data.title} (${page.url})

${processed}`;
}
