import { defineConfig, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';
import { VitePWA, VitePWAOptions } from 'vite-plugin-pwa';
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite';
import { fileURLToPath, URL } from 'node:url';
import path from 'node:path';

const pwaOptions: Partial<VitePWAOptions> = {
  registerType: 'autoUpdate',
  strategies: 'injectManifest',
  srcDir: 'src',
  filename: 'sw.ts',
  devOptions: {
    enabled: true,
    type: 'module',
    navigateFallback: 'index.html',
    suppressWarnings: true,
  },
  manifest: {
    name: 'mitlist',
    short_name: 'mitlist',
    description: 'mitlist pwa',
    theme_color: '#fff8f0',
    background_color: '#f3f3f3',
    display: 'standalone',
    orientation: 'portrait',
    icons: [
      { src: 'icons/icon-128x128.png', sizes: '128x128', type: 'image/png' },
      { src: 'icons/icon-192x192.png', sizes: '192x192', type: 'image/png' },
      { src: 'icons/icon-256x256.png', sizes: '256x256', type: 'image/png' },
      { src: 'icons/icon-384x384.png', sizes: '384x384', type: 'image/png' },
      { src: 'icons/icon-512x512.png', sizes: '512x512', type: 'image/png' },
    ],
  },
  injectManifest: {
    globPatterns: [
      '**/*.{js,css,html,ico,png,svg,woff2}',
      'offline.html',
    ],
    globIgnores: [
      '**/node_modules/**',
      '**/dist/**',
      'sw.js',
      'dev-sw.js',
      'index.html',
    ],
    maximumFileSizeToCacheInBytes: 15 * 1024 * 1024, // 15MB
  },
  workbox: {
    cleanupOutdatedCaches: true,
    sourcemap: true,
  },
};

export default ({ mode }: { mode: string }) => {
  const env = loadEnv(mode, process.cwd(), '');
  const isProduction = mode === 'production';

  return defineConfig({
    plugins: [
      vue(),
      VitePWA(pwaOptions),
      VueI18nPlugin({
        include: [path.resolve(path.dirname(fileURLToPath(import.meta.url)), './src/i18n/**.json')],
        strictMessage: false,
        runtimeOnly: false,
        compositionOnly: false,
      }),
    ],
    resolve: {
      alias: {
        '@': fileURLToPath(new URL('./src', import.meta.url)),
      },
    },
    define: {
      __PWA_FALLBACK_HTML__: JSON.stringify('/index.html'),
      __PWA_SERVICE_WORKER_REGEX__: JSON.stringify('^(sw|workbox)-.*\\.js$'),
      'process.env.MODE': JSON.stringify(process.env.NODE_ENV),
      'process.env.PROD': JSON.stringify(process.env.NODE_ENV === 'production'),
    },
    build: {
      // Advanced code splitting configuration
      rollupOptions: {
        output: {
          // Vendor chunk splitting for better caching
          manualChunks: {
            // Core Vue ecosystem
            'vue-vendor': ['vue', 'vue-router', 'pinia'],

            // UI Framework chunks
            'headlessui': ['@headlessui/vue'],
            'icons': ['@heroicons/vue'],

            // Large utility libraries
            'date-utils': ['date-fns'],
            'http-client': ['axios'],

            // Chart/visualization libraries (if used)
            'charts': ['chart.js', 'vue-chartjs'].filter(dep => {
              try {
                require.resolve(dep);
                return true;
              } catch {
                return false;
              }
            }),

            // Development tools (only in dev)
            ...(isProduction ? {} : {
              'dev-tools': ['@vue/devtools-api']
            })
          },

          // Optimize chunk file names for caching
          chunkFileNames: (chunkInfo) => {
            const facadeModuleId = chunkInfo.facadeModuleId
              ? chunkInfo.facadeModuleId.split('/').pop()?.replace(/\.\w+$/, '') || 'chunk'
              : 'chunk';

            // Route-based chunks get descriptive names
            if (chunkInfo.facadeModuleId?.includes('/pages/')) {
              return `pages/[name]-[hash].js`;
            }
            if (chunkInfo.facadeModuleId?.includes('/components/')) {
              return `components/[name]-[hash].js`;
            }
            if (chunkInfo.facadeModuleId?.includes('/layouts/')) {
              return `layouts/[name]-[hash].js`;
            }

            return `chunks/${facadeModuleId}-[hash].js`;
          },

          // Optimize entry and asset naming
          entryFileNames: `assets/[name]-[hash].js`,
          assetFileNames: (assetInfo) => {
            const info = assetInfo.name?.split('.') || [];
            const _ext = info[info.length - 1];

            // Organize assets by type for better caching strategies
            if (/\.(png|jpe?g|gif|svg|webp|avif)$/i.test(assetInfo.name || '')) {
              return `images/[name]-[hash][extname]`;
            }
            if (/\.(woff2?|eot|ttf|otf)$/i.test(assetInfo.name || '')) {
              return `fonts/[name]-[hash][extname]`;
            }
            if (/\.css$/i.test(assetInfo.name || '')) {
              return `styles/[name]-[hash][extname]`;
            }

            return `assets/[name]-[hash][extname]`;
          }
        },

        // External dependencies that should not be bundled
        external: isProduction ? [] : [
          // In development, externalize heavy dev dependencies
        ]
      },

      // Performance optimizations
      target: 'esnext',
      minify: isProduction ? 'terser' : false,

      // Terser options for production
      ...(isProduction && {
        terserOptions: {
          compress: {
            drop_console: true, // Remove console.log in production
            drop_debugger: true,
            pure_funcs: ['console.log', 'console.info', 'console.debug'] // Remove specific console methods
          },
          mangle: {
            safari10: true // Ensure Safari 10+ compatibility
          },
          format: {
            comments: false // Remove comments
          }
        }
      }),

      // Source map configuration
      sourcemap: isProduction ? false : 'inline',

      // CSS code splitting
      cssCodeSplit: true,

      // Asset size warnings
      chunkSizeWarningLimit: 1000, // 1MB warning threshold

      // Enable/disable asset inlining
      assetsInlineLimit: 4096 // 4KB threshold for base64 inlining
    },

    // Performance optimizations for development
    optimizeDeps: {
      include: [
        'vue',
        'vue-router',
        'pinia',
        '@headlessui/vue',
        '@heroicons/vue/24/outline',
        '@heroicons/vue/24/solid',
        'date-fns'
      ],
      exclude: [
        // Exclude heavy dependencies that should be loaded lazily
      ]
    },

    // Development server configuration
    server: {
      open: true,
      proxy: {
        '/api': {
          target: env.VITE_API_BASE_URL,
          changeOrigin: true,
          // Add caching headers for API responses in development
          configure: (proxy, _options) => {
            proxy.on('proxyRes', (proxyRes, req, _res) => {
              // Add cache headers for static API responses
              if (req.url?.includes('/categories') || req.url?.includes('/users/me')) {
                proxyRes.headers['Cache-Control'] = 'max-age=300'; // 5 minutes
              }
            });
          }
        },
      },
      // Enable gzip compression in dev
      middlewareMode: false,
    },

    // Preview server configuration (for production builds)
    preview: {
      port: 4173,
      strictPort: true,
      open: true
    }
  });
};