/**
 * Built-in Clipboard Commands
 *
 * Commands for copy/cut/paste operations:
 * - copy: Copy selected nodes to clipboard
 * - cut: Cut selected nodes (copy + prepare for delete)
 * - paste: Paste clipboard content at position
 * - duplicate: Duplicate selected nodes with offset
 */

import type { CommandDefinition } from '../types';
import { registerCommand } from '../registry';

/**
 * Copy selected nodes to clipboard
 */
export const copyCommand: CommandDefinition = {
	name: 'copy',
	description: 'Copy selected nodes to clipboard',
	aliases: ['cp'],
	category: 'selection',
	inputs: [],
	execute: async (_inputs, ctx) => {
		const { copyToClipboardAtom, hasClipboardContentAtom } = await import('../../core/clipboard-store');

		if (ctx.selectedNodeIds.size === 0) {
			throw new Error('No nodes selected to copy');
		}

		ctx.set(copyToClipboardAtom, Array.from(ctx.selectedNodeIds));

		const hasContent = ctx.get(hasClipboardContentAtom);
		if (!hasContent) {
			throw new Error('Failed to copy nodes');
		}
	},
};

/**
 * Cut selected nodes (copy to clipboard)
 * Note: Actual deletion is handled by the app via onDeleteNode
 */
export const cutCommand: CommandDefinition = {
	name: 'cut',
	description: 'Cut selected nodes (copy to clipboard)',
	aliases: ['x'],
	category: 'selection',
	inputs: [],
	execute: async (_inputs, ctx) => {
		const { copyToClipboardAtom, hasClipboardContentAtom } = await import('../../core/clipboard-store');

		if (ctx.selectedNodeIds.size === 0) {
			throw new Error('No nodes selected to cut');
		}

		// Copy to clipboard
		ctx.set(copyToClipboardAtom, Array.from(ctx.selectedNodeIds));

		const hasContent = ctx.get(hasClipboardContentAtom);
		if (!hasContent) {
			throw new Error('Failed to cut nodes');
		}

		// Delete selected nodes via app mutation
		for (const nodeId of ctx.selectedNodeIds) {
			await ctx.mutations.deleteNode(nodeId);
		}
	},
};

/**
 * Paste clipboard content
 */
export const pasteCommand: CommandDefinition = {
	name: 'paste',
	description: 'Paste nodes from clipboard',
	aliases: ['v'],
	category: 'selection',
	inputs: [
		{
			name: 'position',
			type: 'point',
			prompt: 'Click to paste at position (or Enter for default offset)',
			required: false,
		},
	],
	execute: async (inputs, ctx) => {
		const { pasteFromClipboardAtom, clipboardAtom, PASTE_OFFSET } = await import('../../core/clipboard-store');

		const clipboard = ctx.get(clipboardAtom);
		if (!clipboard || clipboard.nodes.length === 0) {
			throw new Error('Clipboard is empty');
		}

		// Calculate offset from clipboard bounds to paste position
		let offset = PASTE_OFFSET;
		if (inputs.position) {
			const pos = inputs.position as { x: number; y: number };
			// Offset from top-left of original bounds to click position
			offset = {
				x: pos.x - clipboard.bounds.minX,
				y: pos.y - clipboard.bounds.minY,
			};
		}

		const newNodeIds = ctx.set(pasteFromClipboardAtom, offset);

		if (!newNodeIds || newNodeIds.length === 0) {
			throw new Error('Failed to paste nodes');
		}
	},
	feedback: (collected, currentInput) => {
		if (currentInput.name === 'position') {
			return { crosshair: true };
		}
		return null;
	},
};

/**
 * Duplicate selected nodes with offset
 */
export const duplicateCommand: CommandDefinition = {
	name: 'duplicate',
	description: 'Duplicate selected nodes',
	aliases: ['d', 'dup'],
	category: 'selection',
	inputs: [],
	execute: async (_inputs, ctx) => {
		const { duplicateSelectionAtom } = await import('../../core/clipboard-store');

		if (ctx.selectedNodeIds.size === 0) {
			throw new Error('No nodes selected to duplicate');
		}

		const newNodeIds = ctx.set(duplicateSelectionAtom);

		if (!newNodeIds || newNodeIds.length === 0) {
			throw new Error('Failed to duplicate nodes');
		}
	},
};

/**
 * Delete selected nodes
 */
export const deleteSelectedCommand: CommandDefinition = {
	name: 'deleteSelected',
	description: 'Delete selected nodes',
	aliases: ['del', 'delete', 'remove'],
	category: 'selection',
	inputs: [],
	execute: async (_inputs, ctx) => {
		if (ctx.selectedNodeIds.size === 0) {
			throw new Error('No nodes selected to delete');
		}

		// Push history for undo
		const { pushHistoryAtom } = await import('../../core');
		ctx.set(pushHistoryAtom, 'Delete nodes');

		// Delete each selected node
		for (const nodeId of ctx.selectedNodeIds) {
			await ctx.mutations.deleteNode(nodeId);
		}
	},
};

/**
 * Register all clipboard commands
 */
export function registerClipboardCommands(): void {
	registerCommand(copyCommand);
	registerCommand(cutCommand);
	registerCommand(pasteCommand);
	registerCommand(duplicateCommand);
	registerCommand(deleteSelectedCommand);
}
