/**
 * useInputSystem — Consumer hook for the shared input pipeline
 *
 * Provides a stable API for:
 * - Pushing / removing MappingContexts at runtime
 * - Reading the current mapping index
 * - Configuring palm rejection
 *
 * All context state is managed via useState.
 * Context sync belongs in hooks (Design Decision 5), not effectful atoms.
 */

import { useState } from 'react';
import { buildMappingIndex, type MappingIndex } from './mapper';
import {
	ACTIVE_INTERACTION_CONTEXT,
	DEFAULT_CONTEXT,
	KEYBOARD_MANIPULATE_CONTEXT,
	KEYBOARD_NAVIGATE_CONTEXT,
	PALM_REJECTION_CONTEXT,
	SEARCH_CONTEXT,
} from './contexts';
import type { HeldKeysState, MappingContext } from './types';
import { NO_HELD_KEYS } from './types';

export interface InputSystemConfig {
	/** Additional static contexts (merged once) */
	contexts?: MappingContext[];
	/** Enable palm rejection context (default: true) */
	palmRejection?: boolean;
}

export interface InputSystemAPI {
	/** Pre-built mapping index, ready for resolve() calls */
	mappingIndex: MappingIndex;
	/** Push a mapping context onto the stack */
	pushContext: (ctx: MappingContext) => void;
	/** Remove a mapping context by ID */
	removeContext: (id: string) => void;
	/** Enable/disable a context by ID */
	setContextEnabled: (id: string, enabled: boolean) => void;
	/** Whether palm rejection is active */
	palmRejection: boolean;
	/** Toggle palm rejection */
	setPalmRejection: (enabled: boolean) => void;
	/** Snapshot of currently held keyboard keys */
	heldKeys: HeldKeysState;
	/** Replace held key state */
	setHeldKeys: (next: HeldKeysState) => void;
	/** Clear all held keys */
	clearHeldKeys: () => void;
}

export function useInputSystem(config: InputSystemConfig = {}): InputSystemAPI {
	const { contexts: staticContexts, palmRejection: initialPR = true } = config;

	const [dynamicContexts, setDynamicContexts] = useState<MappingContext[]>([]);
	const [palmRejection, setPalmRejection] = useState(initialPR);
	const [heldKeys, setHeldKeys] = useState<HeldKeysState>(NO_HELD_KEYS);

	const all: MappingContext[] = [];
	if (palmRejection) all.push(PALM_REJECTION_CONTEXT);
	all.push(ACTIVE_INTERACTION_CONTEXT, SEARCH_CONTEXT, KEYBOARD_MANIPULATE_CONTEXT, KEYBOARD_NAVIGATE_CONTEXT);
	if (staticContexts) all.push(...staticContexts);
	all.push(...dynamicContexts);
	all.push(DEFAULT_CONTEXT);
	const mappingIndex = buildMappingIndex(all);

	const pushContext = (ctx: MappingContext) => {
		setDynamicContexts((prev) => {
			// Replace if same ID exists
			const filtered = prev.filter((c) => c.id !== ctx.id);
			return [...filtered, ctx];
		});
	};

	const removeContext = (id: string) => {
		setDynamicContexts((prev) => prev.filter((c) => c.id !== id));
	};

	const setContextEnabled = (id: string, enabled: boolean) => {
		setDynamicContexts((prev) =>
			prev.map((c) => (c.id === id ? { ...c, enabled } : c)),
		);
	};

	const clearHeldKeys = () => {
		setHeldKeys(NO_HELD_KEYS);
	};

	return {
		mappingIndex,
		pushContext,
		removeContext,
		setContextEnabled,
		palmRejection,
		setPalmRejection,
		heldKeys,
		setHeldKeys,
		clearHeldKeys,
	};
}

export type GestureSystemConfig = InputSystemConfig;
export type GestureSystemAPI = InputSystemAPI;
export const useGestureSystem = useInputSystem;
