/**
 * Command System Types
 *
 * Type definitions for the command palette system.
 * The command system provides a way to execute commands with
 * sequential input collection and visual feedback.
 */

import type { Getter, Setter } from 'jotai';
import type { UINodeState } from '../core/types';

// Re-export UINodeState for command consumers
export type { UINodeState };

// =============================================================================
// Input Types
// =============================================================================

/**
 * Input types supported by the command system.
 * Each type determines how the input is collected from the user.
 */
export type InputType =
	| 'text' // Free text input
	| 'number' // Numeric input with optional min/max
	| 'point' // Canvas position (click or type x,y)
	| 'node' // Pick a single node from canvas
	| 'nodes' // Pick multiple nodes (shift-click)
	| 'edge' // Pick an edge
	| 'select' // Choose from options with shortcuts
	| 'boolean' // Yes/No toggle
	| 'color'; // Color picker

/**
 * A selectable option for 'select' type inputs.
 */
export type SelectOption = {
	/** Display label for the option */
	label: string;
	/** Value to use when selected */
	value: string;
	/** Single key shortcut (e.g., 'w' for widget) */
	shortcut: string;
	/** Optional description shown on hover */
	description?: string;
};

/**
 * Definition for a single input prompt in a command.
 */
export type InputDefinition = {
	/** Parameter name (used as key in collected inputs) */
	name: string;
	/** Type of input to collect */
	type: InputType;
	/** Displayed prompt text */
	prompt: string;
	/** Whether this input is required (default: true) */
	required?: boolean;
	/** Default value if skipped or not provided */
	default?: unknown;
	/** Options for 'select' type */
	options?: SelectOption[];
	/** Min value for 'number' type */
	min?: number;
	/** Max value for 'number' type */
	max?: number;
	/** Snap to grid for 'point' type */
	snapToGrid?: boolean;
	/** Validation function - returns true or error message */
	validate?: (value: unknown, collected: Record<string, unknown>) => boolean | string;
	/** Filter function for node/edge picking */
	filter?: (item: UINodeState, collected: Record<string, unknown>) => boolean;
};

// =============================================================================
// Command Feedback
// =============================================================================

export type Point = { x: number; y: number };

/**
 * Visual feedback to show on the canvas during input collection.
 */
export type CommandFeedback = {
	/** Node to highlight */
	highlightNodeId?: string;
	/** Preview edge to draw */
	previewEdge?: { from: Point; toCursor: boolean } | { from: Point; to: Point };
	/** Ghost node following cursor */
	ghostNode?: { position: Point; opacity: number };
	/** Show crosshair at cursor */
	crosshair?: boolean;
};

// =============================================================================
// Command Context
// =============================================================================

/**
 * Payload for creating a new node.
 */
export type CreateNodePayload = {
	graph_id: string;
	node_type: string;
	label?: string;
	configuration?: Record<string, unknown>;
	ui_properties?: Record<string, unknown>;
};

/**
 * Payload for creating a new edge.
 */
export type CreateEdgePayload = {
	graph_id: string;
	source_node_id: string;
	target_node_id: string;
	edge_type?: string;
	ui_properties?: Record<string, unknown>;
};

/**
 * Context passed to command execute() function.
 * Provides access to state, mutations, and current graph context.
 */
export type CommandContext = {
	/** Jotai getter for reading atoms */
	get: Getter;
	/** Jotai setter for writing atoms */
	set: Setter;
	/** Current graph ID */
	currentGraphId: string | null;
	/** Set of currently selected node IDs */
	selectedNodeIds: Set<string>;
	/** Current viewport state */
	viewport: {
		zoom: number;
		pan: { x: number; y: number };
	};
	/** Pre-bound mutation functions (provided by app) */
	mutations: {
		createNode: (payload: CreateNodePayload) => Promise<unknown>;
		updateNode: (nodeId: string, updates: Record<string, unknown>) => Promise<void>;
		deleteNode: (nodeId: string) => Promise<void>;
		createEdge: (payload: CreateEdgePayload) => Promise<unknown>;
		deleteEdge: (edgeId: string) => Promise<void>;
	};
	/** Layout functions */
	layout: {
		fitToBounds: (mode: 'graph' | 'selection', padding?: number) => void;
		applyForceLayout: () => Promise<void>;
		applyTreeLayout: (opts?: { direction?: 'top-down' | 'left-right' }) => Promise<void>;
		applyGridLayout: (opts?: { columns?: number }) => Promise<void>;
	};
	/** History functions */
	history: {
		undo: () => void;
		redo: () => void;
	};
};

// =============================================================================
// Command Definition
// =============================================================================

/**
 * Category for organizing commands.
 */
export type CommandCategory = 'nodes' | 'edges' | 'viewport' | 'selection' | 'history' | 'layout' | 'custom';

/**
 * Full command definition.
 */
export type CommandDefinition = {
	/** Unique command name */
	name: string;
	/** Alternative names/shortcuts (e.g., ['cn'] for createNode) */
	aliases?: string[];
	/** Human-readable description */
	description: string;
	/** Category for organization and filtering */
	category: CommandCategory;
	/** Sequential input definitions */
	inputs: InputDefinition[];
	/** Execute the command with collected inputs */
	execute: (inputs: Record<string, unknown>, ctx: CommandContext) => Promise<void>;
	/**
	 * Optional: Generate visual feedback during input collection.
	 * Called after each input is collected.
	 */
	feedback?: (collected: Record<string, unknown>, currentInput: InputDefinition) => CommandFeedback | null;
};

// =============================================================================
// Command Line State
// =============================================================================

/**
 * Input mode - controls how canvas interactions are routed.
 * When not 'normal', canvas clicks are intercepted by the command system.
 */
export type InputMode =
	| { type: 'normal' }
	| { type: 'pickPoint'; prompt: string; snapToGrid?: boolean }
	| { type: 'pickNode'; prompt: string; filter?: (node: UINodeState) => boolean }
	| { type: 'pickNodes'; prompt: string; filter?: (node: UINodeState) => boolean }
	| { type: 'text'; prompt: string }
	| { type: 'select'; prompt: string; options: SelectOption[] };

/**
 * Command line state machine phases.
 */
export type CommandLineState =
	| { phase: 'idle' }
	| { phase: 'searching'; query: string; suggestions: CommandDefinition[] }
	| {
			phase: 'collecting';
			command: CommandDefinition;
			inputIndex: number;
			collected: Record<string, unknown>;
	  }
	| { phase: 'executing'; command: CommandDefinition }
	| { phase: 'error'; message: string };

/**
 * Visual feedback state for the canvas overlay.
 */
export type FeedbackState = {
	hoveredNodeId?: string;
	cursorWorldPos?: Point;
	previewEdge?: { from: Point; to: Point };
	ghostNode?: { position: Point; opacity: number };
	crosshair?: boolean;
} | null;
