import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { VitePWA } from 'vite-plugin-pwa';
import path from 'path';
import { fileURLToPath } from 'url';
import { createRequire } from 'module';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const require   = createRequire(import.meta.url);
const pkg       = require('./package.json');
const apiPort   = process.env.API_PORT || process.env.PORT || 3000;

export default defineConfig({
  plugins: [
    // React Compiler (React 19): auto-memoizes components/hooks at build time, so
    // manual useMemo/useCallback become largely unnecessary. Safe here because the
    // codebase is rules-of-hooks clean (enforced by eslint-plugin-react-hooks).
    react({
      babel: {
        plugins: [['babel-plugin-react-compiler', {}]],
      },
    }),
    VitePWA({
      registerType: 'autoUpdate',
      includeAssets: ['img/logo.png', 'img/pwa-192.png', 'img/pwa-512.png'],
      manifest: {
        name: 'BillTracker',
        short_name: 'BillTracker',
        description: 'Personal bill planning and tracking',
        theme_color: '#18181b',
        background_color: '#18181b',
        display: 'standalone',
        start_url: '/',
        icons: [
          { src: '/img/pwa-192.png', sizes: '192x192', type: 'image/png' },
          { src: '/img/pwa-512.png', sizes: '512x512', type: 'image/png', purpose: 'any maskable' },
        ],
      },
      workbox: {
        globPatterns: ['**/*.{js,css,html,ico,png,svg,woff2}'],
        runtimeCaching: [
          {
            urlPattern: /^\/api\/(tracker|bills|calendar|summary|analytics|snowball|categories)/,
            handler: 'NetworkFirst',
            options: {
              cacheName: 'api-cache',
              networkTimeoutSeconds: 5,
              expiration: { maxEntries: 30, maxAgeSeconds: 300 },
            },
          },
        ],
      },
    }),
  ],
  publicDir: 'client/public',
  define: {
    // Injected at build time — frontend reads this instead of maintaining a
    // duplicate version string in client/lib/version.js
    __APP_VERSION__: JSON.stringify(pkg.version),
  },
  resolve: {
    alias: { '@': path.resolve(__dirname, './client') },
  },
  server: {
    port: 5173,
    proxy: {
      '/api': { target: `http://localhost:${apiPort}`, changeOrigin: true },
    },
  },
  build: {
    outDir: 'dist',
    emptyOutDir: true,
    rollupOptions: {
      output: {
        // QA-B0-01: split the shared vendor code out of the ~659 kB index chunk
        // so large libs load/cache independently and the main bundle shrinks.
        manualChunks: {
          'vendor-react': ['react', 'react-dom', 'react-router-dom'],
          'vendor-radix': [
            '@radix-ui/react-dialog', '@radix-ui/react-select', '@radix-ui/react-dropdown-menu',
            '@radix-ui/react-tabs', '@radix-ui/react-tooltip', '@radix-ui/react-alert-dialog',
          ],
          'vendor-motion': ['framer-motion'],
          'vendor-query': ['@tanstack/react-query', '@tanstack/react-virtual'],
        },
      },
    },
  },
  // Vitest — client-side unit tests (pure logic in client/lib).
  // Server tests stay on node:test (`npm run test`); client tests run with
  // `npm run test:client`; `npm run test:all` runs both.
  test: {
    environment: 'node', // hook/component tests opt into jsdom via @vitest-environment
    include: ['client/**/*.test.{js,jsx}'],
  },
});
