// Copyright (c) 2026 Sidero Labs, Inc.
//
// Use of this software is governed by the Business Source License
// included in the LICENSE file.
import { fileURLToPath, URL } from 'node:url'

import { faker } from '@faker-js/faker'
import tailwindcss from '@tailwindcss/vite'
import Vue from '@vitejs/plugin-vue'
import dotenv from 'dotenv'
import { defineConfig, type UserConfig } from 'vite'
import vueDevTools from 'vite-plugin-vue-devtools'
import { configDefaults } from 'vitest/config'
import VueRouter from 'vue-router/vite'

dotenv.config({ quiet: true })

// https://vitejs.dev/config/
export default defineConfig(({ command }) => {
  const isTest = process.env.NODE_ENV === 'test' || process.env.VITEST

  const config: UserConfig = {
    plugins: [VueRouter(), Vue(), tailwindcss()],
    build: {
      rolldownOptions: {
        output: {
          // Go's //go:embed skips files starting with '_'.
          // Rolldown chunks may begin with '_'.
          // Prefix those names to avoid the embed exclusion.
          chunkFileNames: 'o[name]-[hash].js',
          assetFileNames: 'assets/o[name]-[hash][extname]',
          entryFileNames: 'o[name].js',
        },
      },
    },
    resolve: {
      alias: {
        '@': fileURLToPath(new URL('./src', import.meta.url)),
        // The lightweight package can't get resolved in tests
        ...(isTest && { 'openpgp/lightweight': 'openpgp' }),
      },
    },
    test: {
      setupFiles: ['vitest.setup.ts'],
      environment: 'jsdom',
      exclude: [...configDefaults.exclude, 'e2e/**'],
      root: fileURLToPath(new URL('./', import.meta.url)),
      alias: {
        '@msw': fileURLToPath(new URL('./msw', import.meta.url)),
      },
    },
    server: {
      port: 8121,
      host: '127.0.0.1',
      forwardConsole: true,
      // See customizing the dev server in the readme for allowedHosts
    },
  }

  if (process.env.ENABLE_DEVTOOLS) {
    config.plugins?.push(vueDevTools())
  }

  if (command === 'serve') {
    const cspNonce = faker.string.alphanumeric(14)

    // Inject CSP for dev server for testing.
    // Actual CSP in production is set in ../internal/frontend/handler.go
    // Ideally these sources should match.
    config.server ||= {}
    config.server.headers ||= {}
    config.server.headers['content-security-policy'] = [
      'upgrade-insecure-requests',
      "default-src 'self'",
      `script-src 'self' 'nonce-${cspNonce}' https://*.userpilot.io`,
      "media-src 'self' https://js.userpilot.io",
      'img-src * data:',
      "connect-src 'self' https://factory.staging.talos.dev https://factory.talos.dev https://*.auth0.com https://*.userpilot.io wss://*.userpilot.io",
      "font-src 'self' data: https://fonts.googleapis.com https://fonts.gstatic.com https://fonts.userpilot.io",
      "style-src 'self' 'unsafe-inline' data: https://fonts.googleapis.com",
      'frame-src https://www.youtube.com/embed/ https://*.auth0.com',
    ].join(';')

    // Adds nonce for dev server inline scripts.
    // Note that it also adds an extra meta tag,
    // but we should only rely on the one present in index.html
    // as it is the only one present in production.
    config.html ||= {}
    config.html.cspNonce = cspNonce

    config.plugins ||= []
    config.plugins.push({
      // Injects nonce into the placeholder as the backend handler usually would.
      name: 'transformIndexHtml',
      transformIndexHtml: (html) => html.replaceAll(/{{.Nonce}}/g, cspNonce),
    })
  }

  return config
})
