import { defineDocumentType, makeSource } from 'contentlayer/source-files';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import rehypeSlug from 'rehype-slug';

const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000';

export const Post = defineDocumentType(() => ({
  name: 'Post',
  filePathPattern: `posts/*.mdx`,
  contentType: 'mdx',
  fields: {
    title: {
      type: 'string',
      description: 'The title of the post',
      required: true,
    },
    date: {
      type: 'date',
      description: 'The date of the post',
      required: true,
    },
    live: {
      type: 'boolean',
      description: 'Whether the post is live or not',
      required: true,
      default: false,
    },
    image: {
      type: 'string',
      description: 'The path to the cover image',
    },
    description: {
      type: 'string',
      description: 'The description of the post',
    },
  },
  computedFields: {
    url: {
      type: 'string',
      resolve: (post) => `/blog/${getSlug(post._raw.sourceFileName)}`,
    },
    readingTime: {
      type: 'number',
      resolve: (post) => calculateReadingTime(post.body.raw),
    },
    slug: {
      type: 'string',
      resolve: (post) => getSlug(post._raw.sourceFileName),
    },
    structuredData: {
      type: 'object',
      resolve: (doc) => ({
        '@context': 'https://schema.org',
        '@type': 'BlogPosting',
        headline: doc.title,
        datePublished: doc.date,
        dateModified: doc.date,
        description: doc.description,
        image: [siteUrl, doc.image].join(''),
        url: [siteUrl, 'blog', doc._raw.flattenedPath].join('/'),
        author: {
          '@type': 'Organization',
          name: `Makerkit`,
        },
      }),
    },
  },
}));

export const DocumentationPage = defineDocumentType(() => ({
  name: 'DocumentationPage',
  filePathPattern: `docs/**/*.mdx`,
  contentType: 'mdx',
  fields: {
    title: {
      type: 'string',
      description: 'The title of the post',
      required: true,
    },
    label: {
      type: 'string',
      description: 'The label of the page in the sidebar',
      required: true,
    },
    cardCTA: {
      type: 'string',
      description: 'The label of the CTA link on the card',
      required: false,
    },
    description: {
      type: 'string',
      description: 'The description of the post',
    },
    show_child_cards: {
      type: 'boolean',
      default: false,
    },
    collapsible: {
      type: 'boolean',
      required: false,
      default: false,
    },
    collapsed: {
      type: 'boolean',
      required: false,
      default: false,
    },
  },
  computedFields: {
    url: {
      type: 'string',
      resolve: (post) => `/blog/${getSlug(post._raw.sourceFileName)}`,
    },
    readingTime: {
      type: 'number',
      resolve: (post) => calculateReadingTime(post.body.raw),
    },
    slug: {
      type: 'string',
      resolve: (post) => getSlug(post._raw.sourceFileName),
    },
    structuredData: {
      type: 'object',
      resolve: (doc) => ({
        '@context': 'https://schema.org',
        '@type': 'LearningResource',
        headline: doc.title,
        datePublished: doc.date,
        dateModified: doc.date,
        description: doc.description,
        image: [siteUrl, doc.image].join(''),
        url: [siteUrl, 'blog', doc._raw.flattenedPath].join('/'),
        author: {
          '@type': 'Organization',
          name: `Makerkit`,
        },
      }),
    },
    path: {
      type: 'string',
      resolve: (doc) => {
        if (doc._id.startsWith('docs/index.md')) {
          return '/docs';
        }

        return urlFromFilePath(doc);
      },
    },
    pathSegments: {
      type: 'json',
      resolve: (doc) => getPathSegments(doc).map(getMetaFromFolderName),
    },
    resolvedPath: {
      type: 'string',
      resolve: (doc) => {
        return getPathSegments(doc)
          .map(getMetaFromFolderName)
          .map(({ pathName }) => pathName)
          .join('/');
      },
    },
  },
}));

export default makeSource({
  contentDirPath: './content',
  documentTypes: [Post, DocumentationPage],
  mdx: {
    remarkPlugins: [],
    rehypePlugins: [
      rehypeSlug,
      [
        rehypeAutolinkHeadings,
        {
          properties: {
            className: ['anchor'],
          },
        },
      ],
    ],
  },
});

function calculateReadingTime(content) {
  const wordsPerMinute = 235;
  const numberOfWords = content.split(/\s/g).length;
  const minutes = numberOfWords / wordsPerMinute;

  return Math.ceil(minutes);
}

function getSlug(fileName) {
  return fileName.replace('.mdx', '');
}

function urlFromFilePath(doc) {
  let urlPath = doc._raw.flattenedPath.replace(/^app\/?/, '/');

  if (!urlPath.startsWith('/')) {
    urlPath = `/${urlPath}`;
  }

  return urlPath;
}

function getMetaFromFolderName(dirName) {
  const re = /^((\d+)-)?(.*)$/;
  const [, , orderStr, pathName] = dirName.match(re) ?? [];
  const order = orderStr ? parseInt(orderStr) : 0;

  return { order, pathName };
}

function getPathSegments(doc) {
  return (
    urlFromFilePath(doc)
      .split('/')
      // skip `/docs` prefix
      .slice(2)
  );
}
