import { readdirSync } from 'node:fs';
import { join } from 'node:path';
import { defineConfig } from 'vitepress';
import { withMermaid } from 'vitepress-plugin-mermaid';

/**
 * VitePress configuration for the APF Portal documentation site
 * per ADR-0022.
 *
 * Source tree maps directly to URLs:
 *   docs/index.md                → /
 *   docs/development.md          → /development
 *   docs/architecture.md         → /architecture
 *   docs/decisions/README.md     → /decisions/
 *   docs/decisions/00NN-…md      → /decisions/00NN-…   (auto-listed sidebar)
 *   docs/setup/0N-…md            → /setup/0N-…
 *
 * `docs/README.md` stays as the git-side / IDE-preview index and is
 * therefore excluded from the published site; `decisions/template.md`
 * is an authoring scaffold, also excluded.
 */

const DECISIONS_DIR = join(__dirname, '..', 'decisions');
const ADR_FILE_RE = /^\d{4}-[\w-]+\.md$/;

/**
 * Walks `docs/decisions/` and returns one sidebar entry per accepted
 * ADR (`NNNN-kebab-title.md`), ordered by numeric prefix. Adding a
 * new ADR is then a single-file change — no `config.ts` edit
 * required (the convention spelled out in ADR-0022 §"Sidebar
 * generation").
 *
 * The link text drops the numeric prefix's leading zeroes to read
 * naturally ("ADR-0009 — …") while the underlying URL keeps the
 * full filename for stable routing across renames.
 */
function adrSidebarItems(): { text: string; link: string }[] {
  return readdirSync(DECISIONS_DIR)
    .filter((name) => ADR_FILE_RE.test(name))
    .sort()
    .map((name) => {
      const slug = name.replace(/\.md$/, '');
      const num = slug.slice(0, 4);
      const title = slug.slice(5).replace(/-/g, ' ');
      return {
        text: `ADR-${num} — ${title}`,
        link: `/decisions/${slug}`,
      };
    });
}

export default withMermaid(
  defineConfig({
    title: 'APF Portal Documentation',
    description:
      "Architecture decisions, development guide, and onboarding material for APF France Handicap's web portal.",

    // Root files (`README.md`) and authoring artefacts (`template.md`)
    // never make it to the rendered site — see ADR-0022.
    srcExclude: ['README.md', 'decisions/template.md'],

    // The curated decisions index lives in `decisions/README.md`
    // (git/IDE convention). VitePress expects `index.md` at a
    // folder root for clean URLs, so we rewrite at build time —
    // source layout stays git-friendly, the published URL resolves
    // `/decisions/` to the curated landing.
    rewrites: {
      'decisions/README.md': 'decisions/index.md',
    },

    // ADRs and the development guide carry deliberate references to
    // files that live OUTSIDE `docs/` (CLAUDE.md, apps/**, infra/**,
    // notes/**), localhost URLs that only resolve in a dev session,
    // and the authoring `template.md` we explicitly excluded. All of
    // those are valid from a git/IDE reader's perspective; VitePress
    // is told to skip them rather than fail the build.
    ignoreDeadLinks: [
      /^https?:\/\/localhost/,
      /^\.{1,2}\//,
      /\/template$/,
      /\/README$/,
    ],

    // VitePress emits `.html` files by default; clean URLs hide the
    // extension. Mirrors what readers will see in the browser address
    // bar and what the inline ADR refs in `portal-admin` already use
    // when they target Gitea source-view (forward-compatible the day
    // we flip those refs to point at the docs site).
    cleanUrls: true,

    // The site is internal + read-only; we let crawlers in by
    // default but won't ship a sitemap until the hostname is locked
    // by the future infra ADR.
    lastUpdated: true,

    themeConfig: {
      nav: [
        { text: 'Development', link: '/development' },
        { text: 'Architecture', link: '/architecture' },
        { text: 'Decisions', link: '/decisions/' },
        { text: 'Onboarding', link: '/setup/01-wsl-terminal-setup' },
      ],

      sidebar: {
        '/development': [
          {
            text: 'Daily development',
            items: [{ text: 'Repo layout & commands', link: '/development' }],
          },
        ],
        '/architecture': [
          {
            text: 'Architecture',
            items: [{ text: 'C4 + module boundaries', link: '/architecture' }],
          },
        ],
        '/decisions/': [
          {
            text: 'Decisions',
            items: [
              { text: 'Index by theme', link: '/decisions/' },
              ...adrSidebarItems(),
            ],
          },
        ],
        '/setup/': [
          {
            text: 'Onboarding',
            items: [
              { text: 'WSL terminal setup', link: '/setup/01-wsl-terminal-setup' },
              { text: 'Dev web stack', link: '/setup/02-dev-web-stack' },
              { text: 'Angular + Nx monorepo', link: '/setup/03-angular-nx-monorepo' },
            ],
          },
        ],
      },

      socialLinks: [
        { icon: 'git', link: 'https://git.unespace.com/julien/apf_portal' },
      ],

      search: {
        provider: 'local',
      },

      outline: {
        level: [2, 3],
      },

      footer: {
        message: 'APF Portal — internal documentation',
      },
    },

    // `vitepress-plugin-mermaid` passes its `mermaid` key through to
    // the Mermaid runtime. Theme `default` follows VitePress's
    // light/dark switcher automatically; explicit `securityLevel`
    // tightens the renderer so diagrams can't inject arbitrary HTML
    // from the source markdown.
    mermaid: {
      securityLevel: 'strict',
    },

    // Pre-bundle Mermaid through Vite's dep optimizer. When this was
    // first added (#157) Vite 5's dev server resolved Mermaid's CJS
    // transitives (`dayjs`, `cytoscape`, `debug`, `@braintree/sanitize-url`)
    // eagerly as ESM and the browser threw `does not provide an export
    // named 'default'` on the first navigation. With Vite 6 — to which
    // we're now pinned per ADR-0022's "stable, recognized" bar (#160
    // capped vite below 7 because VitePress 1.x rejects the new
    // rolldown-vite) — the pre-bundler walks Mermaid's transitives
    // automatically once Mermaid itself is in `include`, so the
    // explicit list of children has been collapsed.
    vite: {
      optimizeDeps: {
        include: ['mermaid'],
      },
    },
  }),
);
