/**
 * Theme presets and the definition of what the editor may change.
 *
 * A preset supplies a full palette for both modes. The editor writes sparse
 * overrides on top, per mode, so customising the dark palette never disturbs
 * the light one.
 */

export type Mode = 'light' | 'dark';

/** CSS custom properties the editor exposes, in the order it shows them. */
export const COLOR_TOKENS = [
	{ key: 'background', label: 'Background', hint: 'Page behind everything' },
	{ key: 'foreground', label: 'Text', hint: 'Default body text' },
	{ key: 'card', label: 'Surface', hint: 'Cards, rows, popovers' },
	{ key: 'primary', label: 'Primary', hint: 'Buttons and active states' },
	{ key: 'muted-foreground', label: 'Muted text', hint: 'Counts, captions, metadata' },
	{ key: 'border', label: 'Border', hint: 'Rules and outlines' },
	{ key: 'sidebar', label: 'Sidebar', hint: 'Sidebar and toolbar ground' },
	{ key: 'success', label: 'Finished', hint: 'Completed reading progress' },
	{ key: 'flag', label: 'Active filter', hint: 'The dot on Filter and Sort' },
	{ key: 'star', label: 'Favourite', hint: 'Stars and selection rings' },
	{ key: 'destructive', label: 'Destructive', hint: 'Delete actions' }
] as const;

export type ColorTokenKey = (typeof COLOR_TOKENS)[number]['key'];

export const FONT_TOKENS = [
	{ key: 'app-font-sans', label: 'Interface' },
	{ key: 'app-font-serif', label: 'Titles' },
	{ key: 'app-font-mono', label: 'Numbers and labels' }
] as const;

export type FontTokenKey = (typeof FONT_TOKENS)[number]['key'];

/** System stacks only — no webfont fetch, so nothing can silently fall back. */
export const FONT_STACKS: { label: string; value: string }[] = [
	{
		label: 'System UI',
		value: "system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
	},
	{ label: 'Georgia', value: "Georgia, 'Iowan Old Style', 'Times New Roman', serif" },
	{ label: 'Times', value: "'Times New Roman', Times, serif" },
	{ label: 'Palatino', value: "'Palatino Linotype', Palatino, 'Book Antiqua', serif" },
	{ label: 'Helvetica', value: "'Helvetica Neue', Helvetica, Arial, sans-serif" },
	{ label: 'Verdana', value: 'Verdana, Geneva, sans-serif' },
	{
		label: 'Monospace',
		value: "ui-monospace, 'SF Mono', 'Cascadia Mono', Menlo, Consolas, monospace"
	}
];

export type Palette = Record<string, string>;

export interface Preset {
	id: string;
	name: string;
	description: string;
	radius: string;
	fonts: Record<FontTokenKey, string>;
	light: Palette;
	dark: Palette;
}

const SANS = FONT_STACKS[0].value;
const SERIF = FONT_STACKS[1].value;
const MONO = FONT_STACKS[6].value;

export const READING_ROOM: Preset = {
	id: 'reading-room',
	name: 'Reading Room',
	description: 'Cool grey paper, one teal accent, serif titles.',
	radius: '0.625rem',
	fonts: { 'app-font-sans': SANS, 'app-font-serif': SERIF, 'app-font-mono': MONO },
	light: {
		background: '#e9ebee',
		foreground: '#1b1f24',
		card: '#fbfbfc',
		'card-foreground': '#1b1f24',
		popover: '#fbfbfc',
		'popover-foreground': '#1b1f24',
		primary: '#1f5f5b',
		'primary-foreground': '#f2f7f6',
		secondary: '#dfe3e8',
		'secondary-foreground': '#1b1f24',
		muted: '#e2e5e9',
		'muted-foreground': '#7d858f',
		accent: '#d7e5e3',
		'accent-foreground': '#164743',
		destructive: '#a6402f',
		border: '#d2d6dc',
		input: '#d2d6dc',
		ring: '#1f5f5b',
		success: '#2f7d4f',
		'success-foreground': '#f2f7f6',
		flag: '#b08a1e',
		star: '#c79a25',
		sidebar: '#e2e5e9',
		'sidebar-foreground': '#1b1f24',
		'sidebar-primary': '#1f5f5b',
		'sidebar-primary-foreground': '#f2f7f6',
		'sidebar-accent': '#d7e5e3',
		'sidebar-accent-foreground': '#164743',
		'sidebar-border': '#d2d6dc',
		'sidebar-ring': '#1f5f5b'
	},
	dark: {
		background: '#15191b',
		foreground: '#e6eae9',
		card: '#1d2226',
		'card-foreground': '#e6eae9',
		popover: '#1d2226',
		'popover-foreground': '#e6eae9',
		primary: '#6fbab0',
		'primary-foreground': '#0e1a19',
		secondary: '#232a2d',
		'secondary-foreground': '#e6eae9',
		muted: '#232a2d',
		'muted-foreground': '#78868a',
		accent: '#1b3330',
		'accent-foreground': '#9fd8d0',
		destructive: '#e0796b',
		border: '#2a3034',
		input: '#2a3034',
		ring: '#6fbab0',
		success: '#4fa97a',
		'success-foreground': '#0e1a19',
		flag: '#d4a63a',
		star: '#e5b84b',
		sidebar: '#111517',
		'sidebar-foreground': '#e6eae9',
		'sidebar-primary': '#6fbab0',
		'sidebar-primary-foreground': '#0e1a19',
		'sidebar-accent': '#1b3330',
		'sidebar-accent-foreground': '#9fd8d0',
		'sidebar-border': '#2a3034',
		'sidebar-ring': '#6fbab0'
	}
};

export const STACKS: Preset = {
	id: 'stacks',
	name: 'Stacks',
	description: 'Warm near-black with brass. Covers do the talking.',
	radius: '0.25rem',
	fonts: { 'app-font-sans': SANS, 'app-font-serif': SERIF, 'app-font-mono': MONO },
	light: {
		...READING_ROOM.light,
		background: '#f2efe9',
		foreground: '#221e1a',
		card: '#fbf9f5',
		'card-foreground': '#221e1a',
		popover: '#fbf9f5',
		'popover-foreground': '#221e1a',
		primary: '#8a6a15',
		'primary-foreground': '#fbf9f5',
		secondary: '#e7e1d6',
		'secondary-foreground': '#221e1a',
		muted: '#e7e1d6',
		'muted-foreground': '#7d7266',
		accent: '#efe6d2',
		'accent-foreground': '#5c4708',
		border: '#ddd5c7',
		input: '#ddd5c7',
		ring: '#8a6a15',
		flag: '#8a6a15',
		star: '#a8801d',
		sidebar: '#ebe6dc',
		'sidebar-foreground': '#221e1a',
		'sidebar-primary': '#8a6a15',
		'sidebar-primary-foreground': '#fbf9f5',
		'sidebar-accent': '#efe6d2',
		'sidebar-accent-foreground': '#5c4708',
		'sidebar-border': '#ddd5c7',
		'sidebar-ring': '#8a6a15'
	},
	dark: {
		...READING_ROOM.dark,
		background: '#141210',
		foreground: '#ede7de',
		card: '#221e1a',
		'card-foreground': '#ede7de',
		popover: '#221e1a',
		'popover-foreground': '#ede7de',
		primary: '#c9a227',
		'primary-foreground': '#17130a',
		secondary: '#2c2621',
		'secondary-foreground': '#ede7de',
		muted: '#2c2621',
		'muted-foreground': '#7d7266',
		accent: '#352c14',
		'accent-foreground': '#e6c452',
		border: '#2c2621',
		input: '#2c2621',
		ring: '#c9a227',
		flag: '#c9a227',
		star: '#e6c452',
		sidebar: '#100e0c',
		'sidebar-foreground': '#ede7de',
		'sidebar-primary': '#c9a227',
		'sidebar-primary-foreground': '#17130a',
		'sidebar-accent': '#352c14',
		'sidebar-accent-foreground': '#e6c452',
		'sidebar-border': '#2c2621',
		'sidebar-ring': '#c9a227'
	}
};

export const SLATE: Preset = {
	id: 'slate',
	name: 'Slate',
	description: 'The original shadcn palette, kept for comparison.',
	radius: '0.625rem',
	fonts: { 'app-font-sans': SANS, 'app-font-serif': SANS, 'app-font-mono': MONO },
	light: {
		...READING_ROOM.light,
		background: '#ffffff',
		foreground: '#020617',
		card: '#ffffff',
		'card-foreground': '#020617',
		popover: '#ffffff',
		'popover-foreground': '#020617',
		primary: '#1e293b',
		'primary-foreground': '#f8fafc',
		secondary: '#f1f5f9',
		'secondary-foreground': '#1e293b',
		muted: '#f1f5f9',
		'muted-foreground': '#64748b',
		accent: '#f1f5f9',
		'accent-foreground': '#1e293b',
		destructive: '#dc2626',
		border: '#e2e8f0',
		input: '#e2e8f0',
		ring: '#94a3b8',
		success: '#16a34a',
		flag: '#eab308',
		star: '#fde047',
		sidebar: '#f8fafc',
		'sidebar-foreground': '#020617',
		'sidebar-primary': '#1e293b',
		'sidebar-primary-foreground': '#f8fafc',
		'sidebar-accent': '#f1f5f9',
		'sidebar-accent-foreground': '#1e293b',
		'sidebar-border': '#e2e8f0',
		'sidebar-ring': '#94a3b8'
	},
	dark: {
		...READING_ROOM.dark,
		background: '#020617',
		foreground: '#f8fafc',
		card: '#1e293b',
		'card-foreground': '#f8fafc',
		popover: '#1e293b',
		'popover-foreground': '#f8fafc',
		primary: '#e2e8f0',
		'primary-foreground': '#1e293b',
		secondary: '#334155',
		'secondary-foreground': '#f8fafc',
		muted: '#334155',
		'muted-foreground': '#94a3b8',
		accent: '#334155',
		'accent-foreground': '#f8fafc',
		destructive: '#f87171',
		border: '#334155',
		input: '#334155',
		ring: '#64748b',
		success: '#4ade80',
		flag: '#eab308',
		star: '#fde047',
		sidebar: '#1e293b',
		'sidebar-foreground': '#f8fafc',
		'sidebar-primary': '#60a5fa',
		'sidebar-primary-foreground': '#f8fafc',
		'sidebar-accent': '#334155',
		'sidebar-accent-foreground': '#f8fafc',
		'sidebar-border': '#334155',
		'sidebar-ring': '#64748b'
	}
};

export const PRESETS: Preset[] = [READING_ROOM, STACKS, SLATE];

export const DEFAULT_PRESET_ID = READING_ROOM.id;

export function getPreset(id: string | undefined): Preset {
	return PRESETS.find((p) => p.id === id) ?? READING_ROOM;
}

/** What we persist in the cookie. Sparse by design — presets carry the rest. */
export interface ThemeConfig {
	preset: string;
	radius?: string;
	fonts?: Partial<Record<FontTokenKey, string>>;
	light?: Palette;
	dark?: Palette;
}

export const THEME_COOKIE = 'chitai-theme';

export function parseThemeCookie(raw: string | undefined | null): ThemeConfig {
	if (!raw) return { preset: DEFAULT_PRESET_ID };
	try {
		const parsed = JSON.parse(decodeURIComponent(raw));
		if (!parsed || typeof parsed !== 'object') return { preset: DEFAULT_PRESET_ID };
		return {
			...parsed,
			preset: typeof parsed.preset === 'string' ? parsed.preset : DEFAULT_PRESET_ID
		};
	} catch {
		return { preset: DEFAULT_PRESET_ID };
	}
}

/** Merge a config over its preset to get the palette actually in force. */
export function resolvePalette(config: ThemeConfig, mode: Mode): Palette {
	const preset = getPreset(config.preset);
	return { ...preset[mode], ...(config[mode] ?? {}) };
}

export function resolveRadius(config: ThemeConfig): string {
	return config.radius ?? getPreset(config.preset).radius;
}

export function resolveFonts(config: ThemeConfig): Record<FontTokenKey, string> {
	return { ...getPreset(config.preset).fonts, ...(config.fonts ?? {}) };
}

/**
 * Render a theme as CSS. Used on the server to inline the theme into the
 * document head, so the first paint is already correct.
 *
 * The doubled `:root:root` is deliberate. app.css declares the same custom
 * properties on plain `:root`, which has identical specificity, so whichever
 * stylesheet comes last would win — and in dev Vite appends app.css to the end
 * of <head>, after this tag. Doubling the selector raises specificity to
 * (0,2,0) so the stored theme wins on merit rather than on load order.
 */
export function themeToCss(config: ThemeConfig): string {
	const decl = (palette: Palette) =>
		Object.entries(palette)
			.map(([k, v]) => `--${k}:${v};`)
			.join('');

	const fonts = Object.entries(resolveFonts(config))
		.map(([k, v]) => `--${k}:${v};`)
		.join('');

	return (
		`:root:root{--radius:${resolveRadius(config)};${fonts}${decl(resolvePalette(config, 'light'))}}` +
		`:root:root.dark{${decl(resolvePalette(config, 'dark'))}}`
	);
}
