import fs from 'node:fs'
import path from 'path'
import { defineConfig, type Plugin } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'

/**
 * Копирует wasm-рантайм MediaPipe (`@mediapipe/tasks-vision`) в `public/mediapipe/wasm/`,
 * откуда его забирает замена фона (`lib/virtualBackground.ts`).
 *
 * Зачем вообще: библиотека `@livekit/track-processors` по умолчанию тянет и
 * wasm, и модель сегментации с ВНЕШНИХ CDN (jsdelivr + storage.googleapis.com).
 * VidConf ставят в закрытых контурах, где внешнего интернета нет, — там фича
 * молча не заработала бы. Поэтому все ассеты отдаются со своего домена.
 *
 * Зачем копировать, а не коммитить: два варианта рантайма (simd/nosimd) весят
 * ~19 МБ — в репозитории им не место, а версия обязана совпадать с
 * установленной в `node_modules` (иначе рантайм и `vision_bundle.mjs`
 * разъедутся). Копия делается и в dev (`vite`), и в сборке (`vite build`,
 * который потом переносит весь `public/` в `dist/`), каталог назначения
 * gitignored. Модель сегментации (`selfie_segmenter.tflite`, ~244 КБ) npm-пакетом
 * не поставляется — она лежит в репозитории рядом, см. `public/mediapipe/NOTICE.txt`.
 */
function mediapipeWasm(): Plugin {
  const source = path.resolve(__dirname, 'node_modules/@mediapipe/tasks-vision/wasm')
  const target = path.resolve(__dirname, 'public/mediapipe/wasm')
  return {
    name: 'vidconf-mediapipe-wasm',
    buildStart() {
      if (!fs.existsSync(source)) {
        // Пакет не установлен — падать сборкой не за что: замена фона просто
        // не сможет инициализироваться, остальное приложение работает.
        this.warn(`не найден wasm-рантайм MediaPipe: ${source}`)
        return
      }
      fs.mkdirSync(target, { recursive: true })
      for (const name of fs.readdirSync(source)) {
        const from = path.join(source, name)
        const to = path.join(target, name)
        // Пропускаем уже скопированное с тем же размером — иначе каждый
        // перезапуск dev-сервера переписывал бы 19 МБ.
        const src = fs.statSync(from)
        const dst = fs.existsSync(to) ? fs.statSync(to) : null
        if (dst && dst.size === src.size) continue
        fs.copyFileSync(from, to)
      }
    },
  }
}

// https://vite.dev/config/
export default defineConfig({
  plugins: [react(), tailwindcss(), mediapipeWasm()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:8000',
        changeOrigin: true,
        // WS-чат конференции ходит через тот же префикс /api
        ws: true,
      },
      // Загруженные файлы (аватары, картинки фона). На проде их раздаёт nginx
      // напрямую из тома (`location /media/`), минуя backend; в dev такого
      // слоя нет, и без этого прокси все `/media/...` упирались бы в SPA
      // и отдавали index.html вместо картинки.
      //
      // ⚠️ Ключ обязан быть со СЛЭШЕМ на конце. Vite матчит префиксом, и
      // ключ `/media` перехватывал заодно `/mediapipe/...` — ассеты замены
      // фона уходили на backend и получали 404, из-за чего фон молча не
      // включался. У nginx та же семантика: там `location /media/` тоже
      // со слэшем, поэтому прод этим не задет.
      '/media/': {
        target: 'http://localhost:8000',
        changeOrigin: true,
      },
    },
  },
})
