import { writable } from 'svelte/store';
import { browser } from '$app/environment';

// mode constants
export const modeLight = 'light';
export const modeDark = 'dark';
const modeNotSet = 'not-set';
const modeKey = 'theme-mode';

/**
 * theme store - either 'light' or 'dark'
 * use it to know which theme is current and subscribe to know when it changes
 */
export const theme = writable(modeLight);

/**
 * toggle the theme mode from light to dark or vice versa
 * @returns {void}
 */
export const toggleMode = () => {
	theme.update((current) => {
		const newMode = current === modeLight ? modeDark : modeLight;
		setModeToLocalStorage(newMode);
		applyThemeToHTML(newMode);
		return newMode;
	});
};

/**
 * setup the theme mode - must be called once during app bootstrapping
 * checks localStorage, then OS preference, defaults to light
 * @returns {string} the mode that was set
 */
export function setupTheme() {
	if (!browser) return modeLight;

	let mode = getModeFromLocalStorage();
	if (mode === modeNotSet) {
		mode = getOSPreferredMode();
		setModeToLocalStorage(mode);
	}

	applyThemeToHTML(mode);
	theme.set(mode);
	return mode;
}

/**
 * get the OS preferred light or dark mode
 * @returns {string} either 'light' or 'dark'
 */
export const getOSPreferredMode = () => {
	if (!browser) return modeLight;

	const darkMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
	return darkMediaQuery.matches ? modeDark : modeLight;
};

/**
 * get the theme mode from localStorage
 * @returns {string} the stored mode or 'not-set'
 */
export const getModeFromLocalStorage = () => {
	if (!browser) return modeNotSet;
	return localStorage.getItem(modeKey) ?? modeNotSet;
};

/**
 * set the theme mode in localStorage
 * @param {string} mode - either 'light' or 'dark'
 */
export const setModeToLocalStorage = (mode) => {
	if (!browser) return;
	localStorage.setItem(modeKey, mode);
};

/**
 * apply the theme to the HTML element by adding/removing the 'dark' class
 * @param {string} mode - either 'light' or 'dark'
 */
const applyThemeToHTML = (mode) => {
	if (!browser) return;

	const html = document.documentElement;
	if (mode === modeDark) {
		html.classList.add('dark');
		html.style.backgroundColor = '#111827';
	} else {
		html.classList.remove('dark');
		html.style.removeProperty('background-color');
	}
};

/**
 * set up theme change listener for OS preference changes
 */
export const setupOSThemeListener = () => {
	if (!browser) return;

	const darkMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
	darkMediaQuery.addEventListener('change', (e) => {
		// only update if user hasn't manually set a preference
		const storedMode = getModeFromLocalStorage();
		if (storedMode === modeNotSet) {
			const newMode = e.matches ? modeDark : modeLight;
			applyThemeToHTML(newMode);
			theme.set(newMode);
		}
	});
};
