import { fileURLToPath, URL } from 'node:url'

import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), '')
  const allowedHosts = parseAllowedHosts(env.VITE_ALLOWED_HOSTS)

  return {
    plugins: [
      vue(),
      AutoImport({
        imports: ['vue', 'vue-router'],
        dts: 'src/auto-imports.d.ts',
        resolvers: [ElementPlusResolver({ importStyle: 'css' })],
      }),
      Components({
        dts: 'src/components.d.ts',
        resolvers: [ElementPlusResolver({ importStyle: 'css' })],
      }),
    ],
    resolve: {
      alias: {
        '@': fileURLToPath(new URL('./src', import.meta.url)),
      },
    },
    server: {
      host: env.VITE_DEV_HOST === 'true',
      allowedHosts: env.VITE_ALLOW_ALL_HOSTS === 'true' ? true : allowedHosts,
      proxy: {
        '/api': {
          target: env.VITE_API_TARGET || 'http://localhost:3000',
          changeOrigin: true,
        },
      },
    },
    build: {
      rollupOptions: {
        output: {
          manualChunks: splitVendorChunk,
        },
      },
    },
  }
})

function parseAllowedHosts(value?: string) {
  const hosts = value
    ?.split(',')
    .map((host) => host.trim())
    .filter(Boolean)

  return hosts && hosts.length > 0 ? hosts : ['localhost', '127.0.0.1']
}

const elementPlusChunkGroups: Array<[string, string[]]> = [
  [
    'element-plus-form',
    [
      '/components/form',
      '/components/input',
      '/components/select',
      '/components/date-picker',
      '/components/checkbox',
      '/components/radio',
      '/components/switch',
      '/components/upload',
    ],
  ],
  [
    'element-plus-data',
    [
      '/components/table',
      '/components/pagination',
      '/components/tag',
      '/components/card',
      '/components/descriptions',
      '/components/empty',
    ],
  ],
  [
    'element-plus-feedback',
    [
      '/components/message',
      '/components/message-box',
      '/components/dialog',
      '/components/popover',
      '/components/tooltip',
      '/components/loading',
    ],
  ],
  [
    'element-plus-navigation',
    ['/components/menu', '/components/tabs', '/components/breadcrumb', '/components/dropdown'],
  ],
  [
    'element-plus-layout',
    [
      '/components/container',
      '/components/row',
      '/components/col',
      '/components/space',
      '/components/divider',
    ],
  ],
]

function splitVendorChunk(id: string) {
  if (!id.includes('/node_modules/')) {
    return
  }

  if (id.includes('/node_modules/@element-plus/icons-vue/')) {
    return 'element-plus-icons'
  }

  if (id.includes('/node_modules/element-plus/')) {
    return splitElementPlusChunk(id)
  }

  if (id.includes('/node_modules/vue/') || id.includes('/node_modules/vue-router/')) {
    return 'vue-vendor'
  }

  if (id.includes('/node_modules/axios/')) {
    return 'axios'
  }

  if (id.includes('/node_modules/qrcode/')) {
    return 'qrcode'
  }

  return 'vendor'
}

function splitElementPlusChunk(id: string) {
  for (const [chunkName, includesList] of elementPlusChunkGroups) {
    if (includesList.some((includePath) => id.includes(includePath))) {
      return chunkName
    }
  }

  return 'element-plus-core'
}
