/**
 * Plugin Types
 *
 * Type definitions for the canvas plugin system.
 * A plugin is a declarative manifest that bundles registrations
 * across all canvas subsystems (node types, commands, actions,
 * gesture contexts, edge calculators).
 */

import type { NodeTypeComponent } from './node-type-registry';
import type { ActionDefinition } from './settings-types';
import type { EdgePathCalculator } from '../utils/edge-path-calculators';
import type { MappingContext } from '../gestures/types';
import type { ActionHandler } from '../gestures/types';
import type { CommandDefinition } from '../commands/types';

// =============================================================================
// Plugin Definition
// =============================================================================

/**
 * A canvas plugin bundles registrations across all subsystems.
 *
 * @example
 * ```ts
 * const myPlugin: CanvasPlugin = {
 *   id: 'my-plugin',
 *   name: 'My Plugin',
 *   nodeTypes: { 'custom-node': CustomNodeComponent },
 *   commands: [myCommand],
 *   gestureContexts: [myGestureContext],
 * };
 * ```
 */
export interface CanvasPlugin {
	/** Unique plugin identifier */
	id: string;
	/** Human-readable name */
	name: string;
	/** Semver version string */
	version?: string;
	/** Plugin IDs this plugin depends on (must be registered first) */
	dependencies?: string[];

	// --- Node types ---
	/** Map of node_type string → React component */
	nodeTypes?: Record<string, NodeTypeComponent>;

	// --- Edge path calculators ---
	/** Map of calculator name → EdgePathCalculator function */
	edgePathCalculators?: Record<string, EdgePathCalculator>;

	// --- Gesture system ---
	/** Mapping contexts to push into the gesture pipeline */
	gestureContexts?: MappingContext[];
	/** Action handlers to register in the gesture dispatcher */
	actionHandlers?: Record<string, ActionHandler>;

	// --- Commands ---
	/** Command definitions to register in the command palette */
	commands?: CommandDefinition[];

	// --- Event-action system ---
	/** Action definitions to register in the action registry */
	actions?: ActionDefinition[];

	// --- Lifecycle ---
	/**
	 * Called when the plugin is registered.
	 * Receives a context with store access.
	 * Return a cleanup function for teardown.
	 */
	onRegister?: (ctx: PluginContext) => void | (() => void);
}

// =============================================================================
// Plugin Context
// =============================================================================

/**
 * Context passed to plugin lifecycle hooks.
 */
export interface PluginContext {
	/** The plugin being registered */
	pluginId: string;
	/** Access to the plugin registry for querying other plugins */
	getPlugin: (id: string) => CanvasPlugin | undefined;
	/** Check if a plugin is registered */
	hasPlugin: (id: string) => boolean;
}

// =============================================================================
// Plugin State
// =============================================================================

/** Internal state for a registered plugin */
export interface PluginRegistration {
	plugin: CanvasPlugin;
	/** Cleanup function returned by onRegister */
	cleanup: (() => void) | null;
	/** Timestamp of registration */
	registeredAt: number;
}

// =============================================================================
// Errors
// =============================================================================

export class PluginError extends Error {
	constructor(
		message: string,
		public readonly pluginId: string,
		public readonly code: PluginErrorCode,
	) {
		super(`[Plugin "${pluginId}"] ${message}`);
		this.name = 'PluginError';
	}
}

export type PluginErrorCode =
	| 'ALREADY_REGISTERED'
	| 'NOT_FOUND'
	| 'MISSING_DEPENDENCY'
	| 'CONFLICT'
	| 'LIFECYCLE_ERROR';
