/*  eslint-disable */
import { join } from 'path';
import fs from 'fs';
import glob from 'glob';
import {
  Configuration,
  DefinePlugin,
  IgnorePlugin
} from 'webpack';
import {
  CustomWebpackBrowserSchema,
  TargetOptions
} from '@angular-builders/custom-webpack';
import DotenvPlugin from 'dotenv-webpack';
import TerserPlugin from 'terser-webpack-plugin';
import nodeExternals from 'webpack-node-externals';
import { default as PurgeCSSPlugin } from 'purgecss-webpack-plugin';
import ImageMinimizerPlugin from 'image-minimizer-webpack-plugin';

import * as pkg from './package.json';

export default (
  config: Configuration,
  _options: CustomWebpackBrowserSchema,
  targetOptions: TargetOptions
) => {
  config.output!.crossOriginLoading = 'anonymous';

  config.plugins?.push(
    new DotenvPlugin({
      safe: true,
      allowEmptyValues: false,
      systemvars: true
    }),
    new DefinePlugin({
      APP_NAME: pkg.name,
      APP_VERSION: pkg.version
    })
  );

  if (targetOptions.target === 'browser') {
    config.module?.rules?.push(
      {
        test: /\.(eot|svg|ttf|woff2?)$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '/assets/webfonts/[name].[ext]'
          }
        }
      }
    );

    config.externals = {
      react: {}
    }

    config.plugins?.push(
      new IgnorePlugin({
        checkResource(resource) {
          const imports = [
            'react'
          ];

          if (imports.includes(resource)) {
            return false;
          }

          try {
            require.resolve(resource);
          } catch(_e: any) {
            return true;
          }

          return false;
        }
      })
    );

    if (config.mode === 'production') {
      config.plugins?.push(
        new PurgeCSSPlugin({
          paths: glob.sync(`${join(__dirname, 'src')}**/*.html`, {
            nodir: true
          })
        }),
        new ImageMinimizerPlugin({
          test: /\.(jpe?g|png)$/i,
          filter: (source, sourcePath) => {
            return (source.byteLength < 8192) ? false : true;
          },
          minimizerOptions: {
            plugins: [
              ['jpegtran', { progressive: true }],
              ['optipng', { optimization: 6 }]
            ]
          }
        })
      )
    }
  }

  if (targetOptions.target === 'server') {
    config.target = 'node';
    config.externalsPresets = { node: true };
    config.devtool = false;

    config.module!.rules?.push(
      {
        test: /\.node$/,
        loader: 'node-loader'
      }
    );

    config.externals = [
      /node-gyp/,
      /node-pre-gyp/,
      /argon2/,
      /_http_common/
    ];

    config.optimization = {
      minimize: config.mode === 'production',
      minimizer: [
        (compiler: any) => {
          new TerserPlugin({
            terserOptions: {
              mangle: false,
              ecma: 2020,
              keep_classnames: true,
              keep_fnames: true,
              toplevel: true,
              ie8: false,
              module: true,
              compress: {
                defaults: true,
                ecma: 2020,
                keep_fnames: true,
                module: true
              }
            }
          }).apply(compiler);
        }
      ],
      removeAvailableModules: true,
      mergeDuplicateChunks: true,
      mangleExports: false
    }

    config.plugins!.push(
      new IgnorePlugin({
        checkResource: (resource: string) => {
          const lazyImports = [
            '@nestjs/microservices',
            '@nestjs/microservices/microservices-module',
            '@nestjs/websockets/socket-module',
            'apollo-server-fastify',
            'cache-manager',
            'class-validator',
            'class-transformer',
            'ts-morph',
            'supertest',
            'formidable',
            'class-transformer/storage',
            'utf-8-validate',
            'node-gyp',
            'nock',
            'aws-sdk',
            'mock-aws-s3',
            'fsevents',
            'npm',
            '@ts-morph/common'
          ];

          if (!lazyImports.includes(resource)) {
            return false;
          }

          try {
            require.resolve(resource);
          } catch (_err: any) {
            return true;
          }

          return false;
        }
      })
    );
  }

  return config;
};
