import { createContext, createSignal, useContext, type Component, type JSX } from 'solid-js';

const APPVIEW_URL_KEY = 'untangled.settings.appviewUrl';
const ROUTE_KNOT_REQUESTS_THROUGH_APPVIEW_KEY = 'untangled.settings.routeKnotRequestsThroughAppview';
const FORCE_PDS_KEY = 'untangled.settings.forcePds';

export const DEFAULT_TANGLED_APPVIEW_SERVICE =
	import.meta.env.VITE_TANGLED_APPVIEW_SERVICE || 'https://bobbin.klbr.net';

export const normalizeAppviewUrl = (input: string): string => {
	const trimmed = input.trim();
	const withScheme = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
	const url = new URL(withScheme);

	if (url.protocol !== 'https:' && url.protocol !== 'http:') {
		throw new Error('Appview URL must use http or https');
	}

	url.hash = '';
	url.search = '';
	return url.toString().replace(/\/$/, '');
};

const readStoredAppviewUrl = (): string => {
	if (typeof localStorage === 'undefined') {
		return normalizeAppviewUrl(DEFAULT_TANGLED_APPVIEW_SERVICE);
	}

	const stored = localStorage.getItem(APPVIEW_URL_KEY);
	if (!stored) {
		return normalizeAppviewUrl(DEFAULT_TANGLED_APPVIEW_SERVICE);
	}

	try {
		return normalizeAppviewUrl(stored);
	} catch {
		localStorage.removeItem(APPVIEW_URL_KEY);
		return normalizeAppviewUrl(DEFAULT_TANGLED_APPVIEW_SERVICE);
	}
};

const readStoredRouteKnotRequestsThroughAppview = (): boolean => {
	if (typeof localStorage === 'undefined') {
		return false;
	}

	return localStorage.getItem(ROUTE_KNOT_REQUESTS_THROUGH_APPVIEW_KEY) === 'true';
};

const readStoredForcePds = (): boolean => {
	if (typeof localStorage === 'undefined') {
		return false;
	}

	return localStorage.getItem(FORCE_PDS_KEY) === 'true';
};

let currentAppviewUrl = readStoredAppviewUrl();
let currentRouteKnotRequestsThroughAppview = readStoredRouteKnotRequestsThroughAppview();
let currentForcePds = readStoredForcePds();

export const getTangledAppviewService = (): string => currentAppviewUrl;
export const getRouteKnotRequestsThroughAppview = (): boolean => currentRouteKnotRequestsThroughAppview;
export const getForcePds = (): boolean => currentForcePds;

interface AppSettingsContextValue {
	appviewUrl: () => string;
	routeKnotRequestsThroughAppview: () => boolean;
	forcePds: () => boolean;
	defaultAppviewUrl: string;
	setAppviewUrl: (url: string) => void;
	setRouteKnotRequestsThroughAppview: (enabled: boolean) => void;
	setForcePds: (enabled: boolean) => void;
	resetAppviewUrl: () => void;
	resetAppviewSettings: () => void;
}

const AppSettingsContext = createContext<AppSettingsContextValue>();

export const AppSettingsProvider: Component<{ children: JSX.Element }> = (props) => {
	const [appviewUrl, setAppviewUrlSignal] = createSignal(currentAppviewUrl);
	const [routeKnotRequestsThroughAppview, setRouteKnotRequestsThroughAppviewSignal] = createSignal(
		currentRouteKnotRequestsThroughAppview,
	);
	const [forcePds, setForcePdsSignal] = createSignal(currentForcePds);
	const defaultAppviewUrl = normalizeAppviewUrl(DEFAULT_TANGLED_APPVIEW_SERVICE);

	const setAppviewUrl = (url: string) => {
		const normalized = normalizeAppviewUrl(url);
		currentAppviewUrl = normalized;
		localStorage.setItem(APPVIEW_URL_KEY, normalized);
		setAppviewUrlSignal(normalized);
	};

	const setRouteKnotRequestsThroughAppview = (enabled: boolean) => {
		currentRouteKnotRequestsThroughAppview = enabled;
		localStorage.setItem(ROUTE_KNOT_REQUESTS_THROUGH_APPVIEW_KEY, String(enabled));
		setRouteKnotRequestsThroughAppviewSignal(enabled);
	};

	const setForcePds = (enabled: boolean) => {
		currentForcePds = enabled;
		localStorage.setItem(FORCE_PDS_KEY, String(enabled));
		setForcePdsSignal(enabled);
	};

	const resetAppviewUrl = () => {
		currentAppviewUrl = defaultAppviewUrl;
		localStorage.removeItem(APPVIEW_URL_KEY);
		setAppviewUrlSignal(defaultAppviewUrl);
	};

	const resetAppviewSettings = () => {
		resetAppviewUrl();
		currentRouteKnotRequestsThroughAppview = false;
		localStorage.removeItem(ROUTE_KNOT_REQUESTS_THROUGH_APPVIEW_KEY);
		setRouteKnotRequestsThroughAppviewSignal(false);
		currentForcePds = false;
		localStorage.removeItem(FORCE_PDS_KEY);
		setForcePdsSignal(false);
	};

	return (
		<AppSettingsContext.Provider
			value={{
				appviewUrl,
				routeKnotRequestsThroughAppview,
				forcePds,
				defaultAppviewUrl,
				setAppviewUrl,
				setRouteKnotRequestsThroughAppview,
				setForcePds,
				resetAppviewUrl,
				resetAppviewSettings,
			}}
		>
			{props.children}
		</AppSettingsContext.Provider>
	);
};

export const useAppSettings = (): AppSettingsContextValue => {
	const context = useContext(AppSettingsContext);
	if (!context) {
		throw new Error('useAppSettings must be used inside AppSettingsProvider');
	}

	return context;
};
