import { createReadStream, existsSync, statSync } from 'node:fs'
import { join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import type { IncomingMessage, ServerResponse } from 'node:http'
import { defineConfig, type Connect, type Plugin } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import wails from '@wailsio/runtime/plugins/vite'

const repoRoot = resolve(fileURLToPath(import.meta.url), '../..')
const assetsDir = resolve(repoRoot, 'assets')

function serveStatic(root: string): Connect.NextHandleFunction {
  return (req, res, next) => {
    const url = (req.url ?? '/').split('?')[0]
    const filePath = resolve(join(root, url))
    if (!filePath.startsWith(root) || !existsSync(filePath)) {
      next()
      return
    }
    const stat = statSync(filePath)
    if (!stat.isFile()) {
      next()
      return
    }
    serveFile(filePath, res)
  }
}

function serveFile(filePath: string, res: ServerResponse<IncomingMessage>): void {
  const ext = filePath.split('.').pop()?.toLowerCase()
  const types: Record<string, string> = {
    json: 'application/json',
    mp3: 'audio/mpeg',
  }
  res.setHeader('Content-Type', types[ext ?? ''] ?? 'application/octet-stream')
  createReadStream(filePath).pipe(res)
}

/** Serve repo-level assets/ at /assets in dev and preview. */
function serveRepoAssets(): Plugin {
  return {
    name: 'serve-repo-assets',
    configureServer(server) {
      server.middlewares.use('/assets', serveStatic(assetsDir))
    },
    configurePreviewServer(server) {
      server.middlewares.use('/assets', serveStatic(assetsDir))
    },
  }
}

export default defineConfig({
  plugins: [svelte(), wails('./bindings'), serveRepoAssets()],
  server: {
    host: '127.0.0.1',
    port: Number(process.env.WAILS_VITE_PORT) || 5173,
    strictPort: true,
    fs: {
      allow: [repoRoot],
    },
  },
})
