const { PHASE_PRODUCTION_BUILD } = require('next/constants')
const { findPagesDir } = require('next/dist/lib/find-pages-dir')
const loadConfig = require('next/dist/server/config').default
const getWebpackConfig = require('next/dist/build/webpack-config').default

const CWD = process.cwd()

async function webpackFinal(config) {
  const nextConfig = await loadConfig(PHASE_PRODUCTION_BUILD, CWD)
  const { pagesDir } = findPagesDir(CWD, !!nextConfig.experimental.appDir)
  const nextWebpackConfig = await getWebpackConfig(CWD, {
    pagesDir,
    entrypoints: {},
    isServer: false,
    target: 'server',
    config: nextConfig,
    buildId: 'storybook',
    rewrites: { beforeFiles: [], afterFiles: [], fallback: [] },
  })

  config.plugins = [...config.plugins, ...nextWebpackConfig.plugins]

  config.resolve = {
    ...config.resolve,
    ...nextWebpackConfig.resolve,
  }

  config.module.rules = [
    ...filterModuleRules(config),
    ...nextWebpackConfig.module.rules.map((rule) => {
      // we need to resolve next-babel-loader since it's not available
      // relative with storybook's config
      if (rule.use && rule.use.loader === 'next-babel-loader') {
        rule.use.loader = require.resolve(
          'next/dist/build/webpack/loaders/next-babel-loader'
        )
      }
      return rule
    }),
  ]

  return config
}

function filterModuleRules(config) {
  return config.module.rules.filter((rule) => {
    // the rules we're filtering use RegExp for the test
    if (!(rule.test instanceof RegExp)) return true
    // use Next.js' built-in CSS
    if (rule.test.test('hello.css')) {
      return false
    }
    // use next-babel-loader instead of storybook's babel-loader
    if (
      rule.test.test('hello.js') &&
      Array.isArray(rule.use) &&
      rule.use[0].loader === 'babel-loader'
    ) {
      return false
    }
    return true
  })
}

module.exports = {
  webpackFinal,
  filterModuleRules,
}
