import { svelte, vitePreprocess } from '@sveltejs/vite-plugin-svelte';
import tailwindcss from '@tailwindcss/vite';
import { viteSingleFile } from 'vite-plugin-singlefile';
import { defineConfig } from 'vite';
import { fileURLToPath } from 'node:url';
import { readFileSync } from 'node:fs';

/** Webfonts the shared theme declares, and where their bytes actually live. */
const FONTS = ['Inter', 'Fraunces'];

/**
 * Inline the webfonts the shared theme CSS references by ABSOLUTE path.
 *
 * `src/tailwind-theme.css` is the design-token source of truth for both the live app and this
 * viewer, and it declares `src: url('/fonts/Inter.woff2')`. That is correct for the app, which
 * serves `static/fonts/` from the site root — but the keepsake is opened from `file://` off a USB
 * stick or a Downloads folder, where `/fonts/...` resolves to the root of the guest's DISK. Both
 * requests 404, silently: `font-display: swap` means the viewer renders in a fallback system font
 * with no error, so nothing on the server side can ever report it. The keepsake is the one artifact
 * the whole event exists to produce, and it was shipping without the typography it was designed in.
 *
 * Fixing it in the shared CSS would break the app (a data URI there would inline ~154 KB into every
 * page load for no reason), and shipping a `fonts/` folder beside `index.html` would give the guest
 * a directory they can break by moving one file. So the substitution belongs HERE, in the build that
 * knows its output has no origin: rewrite the emitted HTML only.
 *
 * Runs in `generateBundle` rather than `transformIndexHtml` because `viteSingleFile` inlines the
 * stylesheet during the latter — the `url()` we need to rewrite does not exist in the HTML until
 * after it has run.
 */
function inlineThemeFonts() {
	return {
		name: 'eventsnap:inline-theme-fonts',
		enforce: 'post',
		generateBundle(_options, bundle) {
			const html = bundle['index.html'];
			if (!html || typeof html.source !== 'string') return;

			for (const family of FONTS) {
				const bytes = readFileSync(
					fileURLToPath(new URL(`../static/fonts/${family}.woff2`, import.meta.url))
				);
				const uri = `data:font/woff2;base64,${bytes.toString('base64')}`;
				const before = html.source;
				html.source = html.source.replaceAll(`/fonts/${family}.woff2`, uri);
				// A silent no-op here is the exact failure this plugin exists to prevent, and it
				// would come back the moment the theme renames a font or switches to a CDN. Fail
				// the build instead of shipping another keepsake in Times New Roman.
				if (html.source === before) {
					this.error(
						`inline-theme-fonts: no reference to /fonts/${family}.woff2 in the built ` +
							`keepsake. The shared theme CSS changed how it loads webfonts — update ` +
							`FONTS in vite.standalone.config.js to match, or the offline viewer will ` +
							`render in a fallback font.`
					);
				}
			}
		}
	};
}

// Builds the keepsake viewer as ONE self-contained index.html (all JS + CSS
// inlined) so it renders when opened via file://. Uses the plain Svelte plugin
// (not SvelteKit) because SvelteKit emits multiple module entry points, which
// cannot be inlined into a single file.
export default defineConfig({
	plugins: [
		tailwindcss(),
		svelte({ configFile: false, preprocess: vitePreprocess(), compilerOptions: { runes: true } }),
		viteSingleFile(),
		inlineThemeFonts()
	],
	resolve: {
		alias: { $lib: fileURLToPath(new URL('./src/lib', import.meta.url)) }
	},
	build: {
		outDir: fileURLToPath(new URL('../../backend/static/export-viewer', import.meta.url)),
		emptyOutDir: true,
		target: 'es2020'
	}
});
