'use strict';

const fs = require('fs');
const path = require('path');

const cwd = path.resolve(__dirname, '..');
const docsFilemap = require('../docs/source/index');

const llmsBaseUrl = 'https://mongoosejs.com';
// Publish alongside top level so mongoosejs.com/llms.txt not mongoosejs.com/docs/llms.txt
const llmsTxtPath = path.join(cwd, 'llms.txt');

const llmsSections = [
  {
    title: 'Getting Started',
    files: [
      'docs/index.md',
      'docs/guides.md'
    ]
  },
  {
    title: 'Guides',
    files: [
      'docs/guide.md',
      'docs/schematypes.md',
      'docs/connections.md',
      'docs/models.md',
      'docs/documents.md',
      'docs/subdocs.md',
      'docs/queries.md',
      'docs/validation.md',
      'docs/middleware.md',
      'docs/populate.md',
      'docs/discriminators.md',
      'docs/plugins.md',
      'docs/timestamps.md',
      'docs/transactions.md',
      'docs/typescript.md'
    ]
  },
  {
    title: 'API Reference',
    api: true
  },
  {
    title: 'Reference',
    files: [
      'docs/migrating_to_9.md',
      'docs/compatibility.md',
      'docs/version-support.md',
      'docs/faq.md',
      'docs/further_reading.md'
    ]
  },
  {
    title: 'Community',
    files: [
      'docs/enterprise.md'
    ]
  }
];

const llmsFiles = Object.entries(docsFilemap.fileMap).
  filter(([file]) => file !== 'docs/api.md').
  sort(([, fileA], [, fileB]) => fileA.title.localeCompare(fileB.title));
const llmsFileMap = Object.fromEntries(llmsFiles);

/**
 * Append an llms.txt section if there are entries to list.
 * @param {string[]} lines The full llms.txt output lines
 * @param {string} title The section title
 * @param {string[]} entries Markdown list items for this section
 * @returns {void}
 */
function appendLLMsSection(lines, title, entries) {
  if (entries.length === 0) {
    return;
  }
  lines.push(`## ${title}`);
  lines.push('');
  lines.push(...entries);
  lines.push('');
}

/**
 * Generate llms.txt from the docs file map and parsed API docs.
 * @returns {Promise<void>}
 */
async function generateLLMsTXT() {
  const lines = [
    '# Mongoose',
    '',
    '> Elegant MongoDB object modeling for Node.js.',
    '',
    '**Overview**',
    '',
    'Mongoose provides schema-based modeling, validation, casting, middleware, query building, and API references for building MongoDB applications with Node.js.',
    '',
    '# Home Page',
    '',
    '- Description: Overview of Mongoose documentation, guides, API docs, and community resources.',
    `- URL: ${llmsBaseUrl}/`,
    ''
  ];

  const includedFiles = new Set();
  for (const section of llmsSections) {
    const entries = [];
    if (section.api) {
      const apiFiles = Array.from(docsFilemap.apiDocs.values()).
        sort((fileA, fileB) => fileA.title.localeCompare(fileB.title));

      for (const file of apiFiles) {
        const name = `docs/api/${file.fileName}.md`;
        includedFiles.add(name);
        entries.push(`- [${file.title}](${llmsBaseUrl}/${name})`);
      }

      appendLLMsSection(lines, section.title, entries);
      continue;
    }

    for (const file of section.files) {
      includedFiles.add(file);
      entries.push(`- [${llmsFileMap[file].title}](${llmsBaseUrl}/${file})`);
    }
    appendLLMsSection(lines, section.title, entries);
  }

  const tutorialFiles = llmsFiles.filter(([file]) => file.startsWith('docs/tutorials/') && file.endsWith('.md'));
  const tutorialEntries = [];
  for (const [name, file] of tutorialFiles) {
    includedFiles.add(name);
    tutorialEntries.push(`- [${file.title}](${llmsBaseUrl}/${name})`);
  }
  appendLLMsSection(lines, 'Tutorials', tutorialEntries);

  const typescriptFiles = llmsFiles.filter(([file]) => file.startsWith('docs/typescript/') && file.endsWith('.md'));
  const typescriptEntries = [];
  for (const [name, file] of typescriptFiles) {
    includedFiles.add(name);
    typescriptEntries.push(`- [${file.title}](${llmsBaseUrl}/${name})`);
  }
  appendLLMsSection(lines, 'TypeScript', typescriptEntries);

  const additionalFiles = llmsFiles.filter(([file, doc]) => !includedFiles.has(file) && doc.markdown);
  const additionalEntries = [];
  for (const [name, file] of additionalFiles) {
    additionalEntries.push(`- [${file.title}](${llmsBaseUrl}/${name})`);
  }
  appendLLMsSection(lines, 'Additional Resources', additionalEntries);

  await fs.promises.writeFile(llmsTxtPath, `${lines.join('\n').trim()}\n`);
  console.log('%s : rendered %s', (new Date()).toISOString(), llmsTxtPath);
}

module.exports = generateLLMsTXT;
module.exports.generateLLMsTXT = generateLLMsTXT;

if (require.main === module) {
  generateLLMsTXT();
}