import { fileURLToPath, URL } from 'node:url'
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import viteImagemin from 'vite-plugin-imagemin'
import { VitePWA } from 'vite-plugin-pwa'
import legacy from '@vitejs/plugin-legacy'
import tailwindcss from 'tailwindcss'
import autoprefixer from 'autoprefixer'
import archiver from 'archiver'
import fs from 'fs'
import OSS from 'ali-oss'
import { format } from 'date-fns'
import { Buffer } from 'node:buffer'

// https://vitejs.dev/config/
export default defineConfig(({ command, mode }) => {
    process.env = { ...process.env, ...loadEnv(mode, process.cwd()) }
    const plugins = [
        {
            name: 'build-index',
            async buildStart(options) {
                if (mode !== 'app') return
                const meta = JSON.parse(fs.readFileSync('./src/plugins/updater_meta.json'))
                meta.version++
                fs.writeFileSync('./src/plugins/updater_meta.json', JSON.stringify(meta))
            },
            async closeBundle(options) {
                if (mode !== 'app') return
                const meta = JSON.parse(fs.readFileSync('./src/plugins/updater_meta.json'))

                const sourceDir = 'dist'
                const outputFilePath = 'dist.zip'

                await new Promise((resolve, reject) => {
                    const output = fs.createWriteStream(outputFilePath)
                    output.on('close', function () {
                        resolve()
                    })
                    const archive = archiver('zip')
                    archive.pipe(output)
                    archive.directory(sourceDir, false)
                    archive.finalize()
                }).catch(e => {
                    console.log(e)
                })

                let client = new OSS({
                    accessKeyId: 'PXzJyah5rZfWHIIH',
                    accessKeySecret: 'e1MS6j0wypXJrw8CM0hObZu8qKbfah',
                    region: 'oss-cn-hangzhou',
                    bucket: 'zm-shorts'
                })
                let { url } = await client.put(`packages/${format(new Date(), 'yyyyMMddHHmmss')}.zip`, outputFilePath, {
                    headers: {
                        'x-oss-object-acl': 'public-read'
                    }
                })
                url = url.replace('http://', 'https://')
                console.log('package uploaded: %s', url.replace('http://', 'https://'))
                await client.put('packages/meta.json', Buffer.from(JSON.stringify({ url, version: meta.version })), {
                    headers: { 'x-oss-object-acl': 'public-read' }
                })
            }
        },
        vue(),
        viteImagemin({
            gifsicle: {
                optimizationLevel: 7,
                interlaced: false
            },
            optipng: false,
            mozjpeg: {
                quality: 80
            },
            pngquant: {
                quality: [0.5, 0.9],
                speed: 1
            },
            svgo: {
                plugins: [
                    {
                        name: 'removeViewBox'
                    },
                    {
                        name: 'removeEmptyAttrs',
                        active: false
                    }
                ]
            },
            webp: false
        }),
        // For production build environments only
        legacy({
            targets: ['chrome >= 64', 'edge >= 79', 'safari >= 11.1', 'firefox >= 67'],
            ignoreBrowserslistConfig: true,
            renderLegacyChunks: false,
            /**
             * Polyfills required by modern browsers
             *
             * Since some low-version modern browsers do not support the new syntax
             * You need to load polyfills corresponding to the syntax to be compatible
             * At build, all required polyfills are packaged according to the target browser version range
             * But when the page is accessed, only the required part is loaded depending on the browser version
             *
             * Two configuration methods:
             *
             * 1. true
             *  - Automatically load all required polyfills based on the target browser version range
             *  - Demerit: will introduce polyfills that are not needed by modern browsers in higher versions,
             *    as well as more aggressive polyfills.
             *
             * 2、string[]
             *  - Add low-version browser polyfills as needed
             *  - Demerit: It needs to be added manually, which is inflexible;
             *    it will be discovered after the production is deployed, resulting in production failure! ! !
             */
            modernPolyfills: ['es/global-this']
            //  or
            // modernPolyfills: true,
        })
    ]
    return {
        base: process.env.VITE_BASE_URL,
        server: {
            host: '0.0.0.0',
            port: 3000,
            fs: {
                strict: false
            }
        },
        plugins,
        resolve: {
            alias: {
                '@': fileURLToPath(new URL('./src', import.meta.url))
            }
        },
        css: {
            postcss: {
                plugins: [tailwindcss, autoprefixer]
            },
            preprocessorOptions: {
                less: {
                    javascriptEnabled: true,
                    additionalData: '@import "@/styles/common.less";'
                }
            }
        },
        logLevel: mode === 'app' || mode === 'test' ? 'error' : 'info'
    }
})
