import gulp from 'gulp'
import { deleteAsync } from 'del'
import stylelint from 'gulp-stylelint-esm'
import autoPrefixer from 'gulp-autoprefixer'
import cleanCss from 'gulp-clean-css'
import webpack from 'webpack-stream'
import TerserPlugin from 'terser-webpack-plugin'
import sass from 'gulp-dart-sass'
import plumber from 'gulp-plumber'
import tildeImporter from 'node-sass-tilde-importer'
import eslint from 'gulp-eslint-new'
import entryPlus from 'webpack-entry-plus'
import glob from 'glob'
import path from 'node:path'

const theme = 'disign_theme'
const themePath = `themes/${theme}`
const config = {
  styles: {
    src: 'src/scss/**/*.scss',
    watch: [
      'src/scss/**/*.scss',
      'node_modules/@brandcode/bootstrap-defaults/**/*.scss',
      'node_modules/@brandcode/slideshow/**/*.scss',
    ],
    dest: `${themePath}/css`,
    sass: {
      importer: tildeImporter,
    },
    cleanCss: {
      level: {
        1: { tidySelectors: false },
      },
    },
    autoPrefixer: {
      grid: 'no-autoplace',
    },
  },
  scripts: {
    src: './src/js/[^_]*.js',
    lint: 'src/js/**/*.js',
    watch: [
      'src/js/**/*.js',
      'node_modules/@brandcode/slideshow/**/*.js',
    ],
    dest: `${themePath}/js`,
  },
}

const clean = () => {
  return deleteAsync([config.styles.dest, config.scripts.dest])
}

const sassLint = () => {
  return gulp.src(config.styles.src).pipe(
    stylelint({
      debug: true,
      failAfterError: false,
      reporters: [{ formatter: 'string', console: true }],
    })
  )
}

const stylesDev = () => {
  return gulp
    .src(config.styles.src, { sourcemaps: true })
    .pipe(sass(config.styles.sass).on('error', sass.logError))
    .pipe(autoPrefixer(config.styles.autoPrefixer))
    .pipe(cleanCss(config.styles.cleanCss))
    .pipe(gulp.dest(config.styles.dest, { sourcemaps: true }))
}

const styles = () => {
  return gulp
    .src(config.styles.src)
    .pipe(sass({ ...config.styles.sass, outputStyle: 'compressed' }))
    .pipe(autoPrefixer(config.styles.autoPrefixer))
    .pipe(cleanCss(config.styles.cleanCss))
    .pipe(gulp.dest(config.styles.dest))
}

const scriptsLint = () => {
  return gulp
    .src(config.scripts.lint)
    .pipe(plumber())
    .pipe(
      eslint({
        configType: 'flat',
        overrideConfigFile: 'eslint.config.mjs',
        warnIgnored: true,
      })
    )
    .pipe(eslint.format())
}

const webpackConfig = (mode = 'production') => {
  return {
    mode,
    target: 'web',
    entry: entryPlus([
      {
        entryFiles: glob.sync(config.scripts.src),
        outputName(item) {
          return path.basename(item, '.js')
        },
      },
    ]),
    output: {
      filename: '[name].js',
    },
    devtool: mode === 'production' ? 'source-map' : 'eval',
    optimization: {
      minimize: true,
      minimizer: [
        new TerserPlugin({
          terserOptions: {
            mangle: {
              reserved: ['Drupal'],
            },
          },
        }),
      ],
    },
  }
}

const scriptsDev = () => {
  return gulp
    .src(config.scripts.src, { sourcemaps: true })
    .pipe(plumber())
    .pipe(webpack(webpackConfig('development')))
    .on('error', console.error)
    .pipe(gulp.dest(config.scripts.dest, { sourcemaps: true }))
}

const scripts = () => {
  return gulp
    .src(config.scripts.src)
    .pipe(plumber())
    .pipe(webpack(webpackConfig('production')))
    .pipe(gulp.dest(config.scripts.dest))
}

const watch = done => {
  gulp.watch(config.styles.watch, gulp.series(sassLint, stylesDev))
  gulp.watch(config.scripts.watch, gulp.series(scriptsLint, scriptsDev))

  done()
}

const lint = gulp.parallel(sassLint, scriptsLint)

const dev = gulp.series(
  clean,
  gulp.parallel(gulp.series(sassLint, stylesDev), gulp.series(scriptsLint, scriptsDev)),
  watch
)

const prod = gulp.series(clean, gulp.parallel(styles, scripts))

export {
  clean,
  sassLint,
  stylesDev,
  styles,
  scriptsLint,
  lint,
  scriptsDev,
  scripts,
  watch,
  dev,
  prod,
}

export default prod
