import { useEffect, useState } from "react";

export interface UserSettings {
	aiEnabled: boolean;
	skipAiReview: boolean;
}

export const USER_SETTINGS_STORAGE_KEY = "localcal:user-settings";

const DEFAULT_USER_SETTINGS: UserSettings = {
	aiEnabled: true,
	skipAiReview: false,
};

export const getDefaultUserSettings = (): UserSettings => ({
	...DEFAULT_USER_SETTINGS,
});

type UserSettingsStorage = Pick<Storage, "getItem" | "setItem">;

const isRecord = (value: unknown): value is Record<string, unknown> =>
	typeof value === "object" && value !== null;

const parseUserSettings = (value: unknown): UserSettings => {
	if (!isRecord(value)) {
		return getDefaultUserSettings();
	}

	return {
		aiEnabled:
			typeof value.aiEnabled === "boolean"
				? value.aiEnabled
				: DEFAULT_USER_SETTINGS.aiEnabled,
		skipAiReview:
			typeof value.skipAiReview === "boolean"
				? value.skipAiReview
				: DEFAULT_USER_SETTINGS.skipAiReview,
	};
};

export const loadUserSettings = (
	storage?: UserSettingsStorage,
): UserSettings => {
	if (!storage) {
		return getDefaultUserSettings();
	}

	try {
		const storedValue = storage.getItem(USER_SETTINGS_STORAGE_KEY);
		if (!storedValue) {
			return getDefaultUserSettings();
		}

		return parseUserSettings(JSON.parse(storedValue));
	} catch {
		return getDefaultUserSettings();
	}
};

export const saveUserSettings = (
	settings: UserSettings,
	storage?: UserSettingsStorage,
): UserSettings => {
	if (!storage) {
		return settings;
	}

	try {
		storage.setItem(USER_SETTINGS_STORAGE_KEY, JSON.stringify(settings));
	} catch {
		return settings;
	}

	return settings;
};

const getBrowserStorage = (): UserSettingsStorage | undefined => {
	if (typeof window === "undefined") {
		return undefined;
	}

	try {
		return window.localStorage;
	} catch {
		return undefined;
	}
};

export const useUserSettings = () => {
	const [settings, setSettings] = useState<UserSettings>(
		getDefaultUserSettings,
	);
	const [hasLoadedSettings, setHasLoadedSettings] = useState(false);

	useEffect(() => {
		setSettings(loadUserSettings(getBrowserStorage()));
		setHasLoadedSettings(true);
	}, []);

	const updateSettings = (changes: Partial<UserSettings>) => {
		setSettings((currentSettings) => {
			const nextSettings = {
				...currentSettings,
				...changes,
			};

			saveUserSettings(nextSettings, getBrowserStorage());

			return nextSettings;
		});
	};

	return {
		hasLoadedSettings,
		settings,
		updateSettings,
	};
};
