'use strict'

const { URL } = require('url')
const path = require('path')

const {
  isEmbedIndexable
} = require('./src/components/pages/embed-url/indexable')

const { serializeBlogFeed } = require('./src/helpers/feed')

// Drop embed-url provider pages we deliberately keep out of the index
// (noindex, follow) so the sitemap never sends Google a conflicting signal.
// The hub (/tools/embed-url) and any non-provider page pass through untouched.
const EMBED_PROVIDER_PATH = /^\/tools\/embed-url\/([^/]+)\/?$/
const isSitemapAllowed = pagePath => {
  const match = pagePath.match(EMBED_PROVIDER_PATH)
  if (!match) return true
  return isEmbedIndexable(match[1])
}

const isDev = (process.env.NODE_ENV || 'development') === 'development'

const log = (...args) => {
  if (process.env.DEBUG) {
    console.log(...args)
  }
}

const {
  STRIPE_KEY,
  PAYMENT_API_KEY,
  PAYMENT_ENDPOINT,
  SITE_URL,
  CANONICAL_URL,
  CDN_URL,
  OG_IMAGE_BASE
} = require('./env')

module.exports = {
  trailingSlash: 'never',
  flags: {
    DEV_SSR: process.env.DEV_SSR === 'true',
    FAST_DEV: true,
    PARALLEL_SOURCING: true,
    PRESERVE_FILE_DOWNLOAD_CACHE: true
  },
  siteMetadata: {
    // Basic
    name: 'Microlink',
    author: 'Microlink HQ',
    headline: 'Microlink | The web, transformed',
    description:
      'A single API for turning any URL into data. Built for apps, agents, and AI. Powered by real browsers. Try it, no signup.',
    siteUrl: SITE_URL,
    canonicalUrl: CANONICAL_URL,
    ogImageBase: OG_IMAGE_BASE,
    twitter: '@microlinkhq',
    image: new URL('logo/banner.jpeg', CDN_URL).toString(),
    logo: new URL('logo/logo.png', CDN_URL).toString(),
    // Slack previsualization
    dataLabel1: 'API',
    dataLabel2: 'Documentation',
    dataValue1: 'api.microlink.io',
    dataValue2: 'microlink.io/docs',

    // additional
    paymentApiKey: PAYMENT_API_KEY,
    paymentEndpoint: PAYMENT_ENDPOINT,
    stripeKey: STRIPE_KEY,
    cdnUrl: CDN_URL
  },
  plugins: [
    'gatsby-plugin-styled-components',
    'gatsby-plugin-catch-links',
    {
      resolve: 'gatsby-plugin-sass',
      options: {
        sassOptions: {
          precision: 8
        },
        postCssPlugins: require('./postcss.config').plugins
      }
    },
    'gatsby-transformer-json',
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        name: 'data',
        path: path.join(__dirname, 'data')
      }
    },
    !isDev && {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: path.join(__dirname, 'src/pages'),
        name: 'pages'
      }
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: path.join(__dirname, 'src/content'),
        name: 'content'
      }
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        path: path.join(__dirname, 'data/skills-content'),
        name: 'skills-content'
      }
    },
    {
      resolve: 'gatsby-plugin-canonical-urls',
      options: {
        siteUrl: CANONICAL_URL
      }
    },
    {
      resolve: 'gatsby-plugin-mdx',
      options: {
        extensions: ['.mdx', '.md'],
        mdxOptions: {
          remarkPlugins: [require('remark-gfm').default],
          rehypePlugins: [require('./src/plugins/rehype-slug-trim')]
        }
      }
    },
    'gatsby-transformer-yaml',
    {
      resolve: 'gatsby-plugin-sitemap',
      /* activate fields { slug, lastmod } once we find a workaround for Vercel git history */
      options: {
        excludes: [
          '/404',
          '/404.html',
          '/dev-404-page',
          '/offline-plugin-app-shell-fallback',
          '/payment',
          '/payment/update'
        ],
        query: `
        {
          site {
            siteMetadata {
              siteUrl
            }
          }
          allSitePage {
            nodes {
              path
            }
          }
          allMdx {
            edges {
              node {
                fields {
                  slug
                  lastmod
                }
                frontmatter {
                  date
                }
              }
            }
          }
          allFile(filter: { sourceInstanceName: { eq: "pages" } }) {
            nodes {
              absolutePath
              relativePath
              relativeDirectory
              name
              mtime
              fields {
                lastmod
              }
            }
          }
        }
      `,
        resolvePages: ({
          allSitePage: { nodes: allPages },
          allMdx: { edges: mdxPages },
          allFile: { nodes: pageFiles }
        }) => {
          const mdxMap = {}
          if (mdxPages && Array.isArray(mdxPages)) {
            mdxPages.forEach(({ node }) => {
              const slug = node.fields?.slug
              const lastmod = node.fields?.lastmod || node.frontmatter?.date

              if (slug && lastmod) {
                const normalizedSlug =
                  slug.endsWith('/') && slug.length > 1
                    ? slug.slice(0, -1)
                    : slug
                mdxMap[normalizedSlug] = lastmod
              }
            })
          }

          const pagesMap = {}
          if (pageFiles && Array.isArray(pageFiles)) {
            pageFiles.forEach(file => {
              let pagePath = null
              if (file.relativeDirectory === '') {
                if (file.name === 'index') {
                  pagePath = '/'
                } else {
                  pagePath = `/${file.name}`
                }
              } else {
                const dirPath = file.relativeDirectory.replace(/\\/g, '/')
                if (file.name === 'index') {
                  pagePath = `/${dirPath}`
                } else {
                  pagePath = `/${dirPath}/${file.name}`
                }
              }

              if (pagePath) {
                const lastmod = file.fields?.lastmod || file.mtime
                if (lastmod) {
                  pagesMap[pagePath] = lastmod
                }
              }
            })
          }

          if (!allPages || !Array.isArray(allPages)) {
            return []
          }

          return allPages.flatMap(page => {
            if (!isSitemapAllowed(page.path)) return []
            const lastmod = mdxMap[page.path] || pagesMap[page.path] || null
            return { ...page, lastmod }
          })
        },
        serialize: ({ path: url, lastmod }) => {
          if (!lastmod) {
            log('not lastmod found', { url, lastmod })
            if (!url.startsWith('/recipes')) {
              throw new Error(`not lastmod found for '${url}'`)
            }
          }
          return { url, lastmod }
        }
      }
    },
    {
      resolve: 'gatsby-plugin-feed',
      options: {
        query: `
        {
          site {
            siteMetadata {
              siteUrl
            }
          }
        }
        `,
        feeds: [
          {
            setup: ({ query: { site }, ...rest }) => ({
              ...rest,
              site_url: site.siteMetadata.siteUrl,
              feed_url: `${site.siteMetadata.siteUrl}/rss.xml`
            }),
            serialize: ({ query: { site, allMdx } }) =>
              serializeBlogFeed({
                siteUrl: site.siteMetadata.siteUrl,
                nodes: allMdx.nodes
              }),
            query: `
            {
              allMdx(
                filter: { fields: { slug: { regex: "/^\\/blog\\//" } } }
                sort: { frontmatter: { date: DESC } }
                limit: 25
              ) {
                nodes {
                  excerpt(pruneLength: 240)
                  fields {
                    slug
                  }
                  frontmatter {
                    title
                    description
                    date
                  }
                }
              }
            }
            `,
            output: '/rss.xml',
            title: 'Microlink Blog',
            description: 'Engineering details through Microlink.',
            language: 'en',
            custom_namespaces: {
              sy: 'http://purl.org/rss/1.0/modules/syndication/'
            },
            custom_elements: [
              { 'sy:updatePeriod': 'weekly' },
              { 'sy:updateFrequency': 1 }
            ]
          }
        ]
      }
    }
  ].filter(Boolean)
}
