import { execSync } from 'node:child_process'
import { readFileSync } from 'node:fs'
import { fileURLToPath, URL } from 'node:url'
import { defineConfig, type Plugin } from 'vite'
import vue from '@vitejs/plugin-vue'
import react from '@vitejs/plugin-react'
import dts from 'vite-plugin-dts'

function resolveReleaseDate(): string {
  try {
    const pkg = JSON.parse(
      readFileSync(fileURLToPath(new URL('./package.json', import.meta.url)), 'utf-8')
    ) as { version: string }
    const tagged = execSync(`git log -1 --format=%cs v${pkg.version}`, {
      encoding: 'utf-8',
      stdio: ['ignore', 'pipe', 'ignore'],
    }).trim()
    if (tagged) return tagged
  } catch {
    /* fall through */
  }
  return new Date().toISOString().slice(0, 10)
}

function docsReleaseDatePlugin(): Plugin {
  const releaseDate = resolveReleaseDate()
  const id = 'virtual:docs-release-date'
  const resolved = '\0' + id
  return {
    name: 'docs-release-date',
    resolveId(source) {
      if (source === id) return resolved
    },
    load(loadId) {
      if (loadId === resolved) {
        return `export const releaseDate = ${JSON.stringify(releaseDate)}\n`
      }
    },
  }
}

export default defineConfig(({ command }) => ({
  plugins: [
    vue(),
    // React only needed by the docs-site framework-toggle islands (react-pilot
    // demos, loaded via @demos) in the dev-serve playground. The `build` path of
    // this config is the Vue library build (no .tsx), so scope react() to serve
    // to avoid touching the lib build. (INFRA-F46 backfill: playground BUILD
    // config had this; root DEV serve config was missing it → React toggle
    // failed to resolve @tvu/wc under `pnpm dev`.)
    ...(command === 'serve' ? [react()] : []),
    docsReleaseDatePlugin(),
    ...(command === 'build'
      ? [dts({ include: ['src'], insertTypesEntry: true })]
      : []),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('.', import.meta.url)),
      '@demos': fileURLToPath(new URL('./react-pilot/src/demos', import.meta.url)),
      '@tvu/wc': fileURLToPath(new URL('./dist-wc/tvu-web-components.js', import.meta.url)),
    },
  },
  root: command === 'serve' ? 'playground' : undefined,
  server: {
    host: '0.0.0.0',
    allowedHosts: true,
  },
  preview: {
    host: '0.0.0.0',
    allowedHosts: true,
  },
  ...(command === 'build' && {
    build: {
      // NOTE (INFRA-F65): lib bundle ships UNMINIFIED (~2.08MB, echarts inline
      // dominates). Minify is intentionally NOT set here — investigated and both
      // Vite minifiers misbehave in this lib+dts+multi-format+code-split setup:
      // `minify: 'esbuild'` is a byte-for-byte no-op; `minify: 'terser'` INFLATES
      // the ESM bundle (~2.08→2.77MB) and ignores terserOptions. Manual `esbuild
      // --minify` on the artifact works (~-15%/-7% gzip) but a post-build script
      // importing esbuild would fail `audit:scripts-stdlib`. Consumers re-minify
      // the lib when they bundle their app, so the shipped-unminified state has
      // low real-world impact. Revisit if a clean in-pipeline minifier appears.
      lib: {
        entry: fileURLToPath(new URL('src/index.ts', import.meta.url)),
        name: 'TvuDesignSystem',
        fileName: 'tvu-design-system',
      },
      rollupOptions: {
        // echarts 有意 inline 打包（Chart.vue 从 echarts/core tree-shaken import）——不 external。
        // chart.js/vue-chartjs 是 2026-07-01 ECharts 迁移前的旧库、已非依赖 → 原 external 是死配置，删（INFRA-F65）。
        external: ['vue'],
        output: {
          globals: { vue: 'Vue' },
          exports: 'named',
        },
      },
      cssCodeSplit: false,
    },
  }),
  test: {
    environment: 'jsdom',
    globals: true,
    root: '.',
    include: ['tests/**/*.{test,spec}.{ts,mts}'],
  },
}))
