/**
 * Public event presentation config: the colour theme and the comments feature flag,
 * served unauthenticated from `GET /api/v1/event`. Loaded once on boot (and refreshed
 * on the `event-updated` SSE) so the theme applies before the user has even joined and
 * the comment UI reflects the instance setting.
 *
 * The resolved theme CSS is cached in localStorage so the boot script in app.html can
 * paint the right colours before the JS bundle loads (no flash of the default palette).
 */
import { writable } from 'svelte/store';
import { api } from './api';
import { buildPaletteCss, applyPaletteCss, type ThemeConfig } from './theme/palette';

export const PALETTE_CACHE_KEY = 'eventsnap_palette_css';

export type EventConfig = {
	name: string;
	slug: string;
	commentsEnabled: boolean;
	theme: ThemeConfig;
};

export const eventConfig = writable<EventConfig | null>(null);
/**
 * Convenience flag for the comment UI. `null` until `/event` answers — deliberately NOT an
 * optimistic `true`.
 *
 * Optimistic-open was wrong in the direction that costs a guest their words. Production pins
 * `COMMENTS_ENABLED=false`, so on every cold open the comment button, the grid tile button and
 * the whole lightbox composer rendered for as long as `/event` took — up to the 20s api timeout
 * on congested venue wifi, and PERMANENTLY if that request failed, because the catch below
 * leaves the last value in place. A guest would type a comment, tap Senden, get a red error,
 * and watch the text be discarded.
 *
 * `null` is falsy, so every `{#if $commentsEnabled}` hides and every `$commentsEnabled ? a : b`
 * picks the comments-off copy until the server has actually said otherwise. The failure mode
 * flips from "offered something that doesn't work" to "revealed a moment late".
 */
export const commentsEnabled = writable<boolean | null>(null);

type PublicEventDto = {
	name: string;
	slug: string;
	comments_enabled?: boolean;
	theme_preset?: string;
	theme_primary?: string;
	theme_accent?: string;
};

/** Fetch /event, apply the theme, and cache the resolved CSS for the next boot. */
export async function loadEventConfig(): Promise<void> {
	try {
		// Through `api` rather than a bare `fetch`: this was the ONE request in the app with
		// no AbortController deadline. On a congested venue WiFi a socket that never answers
		// left the promise pending indefinitely, so the palette never reconciled with the
		// server — and since `event-updated` re-calls this, those zombie requests stack up.
		// `api` aborts at 20s and turns it into an ApiError the catch below already handles.
		const b = await api.get<PublicEventDto>('/event');
		const theme: ThemeConfig = {
			preset: b.theme_preset ?? 'champagne-gold',
			primary: b.theme_primary ?? '#8a6a2b',
			accent: b.theme_accent ?? '#8a6a2b'
		};
		eventConfig.set({
			name: b.name,
			slug: b.slug,
			commentsEnabled: b.comments_enabled ?? true,
			theme
		});
		commentsEnabled.set(b.comments_enabled ?? true);

		const css = buildPaletteCss(theme);
		applyPaletteCss(css);
		try {
			localStorage.setItem(PALETTE_CACHE_KEY, css);
		} catch {
			/* private mode / quota — the theme still applied for this session */
		}
	} catch {
		/* offline / server down — keep whatever the boot script already painted */
	}
}

/** Apply a theme immediately without persisting — used by the admin live preview. */
export function previewTheme(theme: ThemeConfig): void {
	applyPaletteCss(buildPaletteCss(theme));
}
