import { describe, it, expect } from 'vitest';
import { createStore } from 'jotai';
import {
	inputModeAtom,
	keyboardInteractionModeAtom,
	interactionFeedbackAtom,
	pendingInputResolverAtom,
	resetInputModeAtom,
	resetKeyboardInteractionModeAtom,
	setKeyboardInteractionModeAtom,
	startPickNodeAtom,
	startPickNodesAtom,
	startPickPointAtom,
	provideInputAtom,
	updateInteractionFeedbackAtom,
	isPickingModeAtom,
	isPickNodeModeAtom,
} from '../core/interaction-store';

describe('interaction-store', () => {
	describe('inputModeAtom', () => {
		it('defaults to normal', () => {
			const store = createStore();
			expect(store.get(inputModeAtom)).toEqual({ type: 'normal' });
		});
	});

	describe('keyboardInteractionModeAtom', () => {
		it('defaults to navigate', () => {
			const store = createStore();
			expect(store.get(keyboardInteractionModeAtom)).toBe('navigate');
		});

		it('setKeyboardInteractionModeAtom changes mode', () => {
			const store = createStore();
			store.set(setKeyboardInteractionModeAtom, 'manipulate');
			expect(store.get(keyboardInteractionModeAtom)).toBe('manipulate');
		});

		it('resetKeyboardInteractionModeAtom returns to navigate', () => {
			const store = createStore();
			store.set(setKeyboardInteractionModeAtom, 'manipulate');
			store.set(resetKeyboardInteractionModeAtom);
			expect(store.get(keyboardInteractionModeAtom)).toBe('navigate');
		});
	});

	describe('pick mode atoms', () => {
		it('startPickNodeAtom sets pickNode mode', () => {
			const store = createStore();
			store.set(startPickNodeAtom, { prompt: 'Pick a node' });
			const mode = store.get(inputModeAtom);
			expect(mode.type).toBe('pickNode');
			if (mode.type === 'pickNode') {
				expect(mode.prompt).toBe('Pick a node');
			}
		});

		it('startPickNodesAtom sets pickNodes mode', () => {
			const store = createStore();
			store.set(startPickNodesAtom, { prompt: 'Pick nodes' });
			expect(store.get(inputModeAtom).type).toBe('pickNodes');
		});

		it('startPickPointAtom sets pickPoint mode', () => {
			const store = createStore();
			store.set(startPickPointAtom, { prompt: 'Pick point', snapToGrid: true });
			const mode = store.get(inputModeAtom);
			expect(mode.type).toBe('pickPoint');
			if (mode.type === 'pickPoint') {
				expect(mode.snapToGrid).toBe(true);
			}
		});
	});

	describe('resetInputModeAtom', () => {
		it('resets mode, feedback, and resolver', () => {
			const store = createStore();
			store.set(startPickNodeAtom, { prompt: 'test' });
			store.set(updateInteractionFeedbackAtom, { hoveredNodeId: 'n1' });
			store.set(provideInputAtom, 'some-value');

			store.set(resetInputModeAtom);
			expect(store.get(inputModeAtom)).toEqual({ type: 'normal' });
			expect(store.get(interactionFeedbackAtom)).toBeNull();
			expect(store.get(pendingInputResolverAtom)).toBeNull();
		});
	});

	describe('derived atoms', () => {
		it('isPickingModeAtom is false in normal mode', () => {
			const store = createStore();
			expect(store.get(isPickingModeAtom)).toBe(false);
		});

		it('isPickingModeAtom is true in pickNode mode', () => {
			const store = createStore();
			store.set(startPickNodeAtom, { prompt: 'test' });
			expect(store.get(isPickingModeAtom)).toBe(true);
		});

		it('isPickNodeModeAtom is true for pickNode and pickNodes', () => {
			const store = createStore();
			store.set(startPickNodeAtom, { prompt: 'test' });
			expect(store.get(isPickNodeModeAtom)).toBe(true);
			store.set(startPickNodesAtom, { prompt: 'test' });
			expect(store.get(isPickNodeModeAtom)).toBe(true);
		});

		it('isPickNodeModeAtom is false for pickPoint', () => {
			const store = createStore();
			store.set(startPickPointAtom, { prompt: 'test' });
			expect(store.get(isPickNodeModeAtom)).toBe(false);
		});
	});

	describe('feedback', () => {
		it('updateInteractionFeedbackAtom merges with current', () => {
			const store = createStore();
			store.set(updateInteractionFeedbackAtom, { hoveredNodeId: 'n1' });
			store.set(updateInteractionFeedbackAtom, { crosshair: true });
			const feedback = store.get(interactionFeedbackAtom);
			expect(feedback?.hoveredNodeId).toBe('n1');
			expect(feedback?.crosshair).toBe(true);
		});
	});
});
