/**
 * Type Structure Constants
 *
 * Complete definitions for all n8n NodePropertyTypes.
 * These structures define the expected data format, JavaScript type,
 * validation rules, and examples for each property type.
 *
 * Based on n8n-workflow v2.4.2 NodePropertyTypes
 *
 * @module constants/type-structures
 * @since 2.23.0
 */

import type { NodePropertyTypes } from 'n8n-workflow';
import type { TypeStructure } from '../types/type-structures';

/**
 * Complete type structure definitions for all 23 NodePropertyTypes
 *
 * Each entry defines:
 * - type: Category (primitive/object/collection/special)
 * - jsType: Underlying JavaScript type
 * - description: What this type represents
 * - structure: Expected data shape (for complex types)
 * - example: Working example value
 * - validation: Type-specific validation rules
 *
 * @constant
 */
export const TYPE_STRUCTURES: Record<NodePropertyTypes, TypeStructure> = {
	// ============================================================================
	// PRIMITIVE TYPES - Simple JavaScript values
	// ============================================================================

	string: {
		type: 'primitive',
		jsType: 'string',
		description: 'A text value that can contain any characters',
		example: 'Hello World',
		examples: ['', 'A simple text', '{{ $json.name }}', 'https://example.com'],
		validation: {
			allowEmpty: true,
			allowExpressions: true,
		},
		notes: ['Most common property type', 'Supports n8n expressions'],
	},

	number: {
		type: 'primitive',
		jsType: 'number',
		description: 'A numeric value (integer or decimal)',
		example: 42,
		examples: [0, -10, 3.14, 100],
		validation: {
			allowEmpty: false,
			allowExpressions: true,
		},
		notes: ['Can be constrained with min/max in typeOptions'],
	},

	boolean: {
		type: 'primitive',
		jsType: 'boolean',
		description: 'A true/false toggle value',
		example: true,
		examples: [true, false],
		validation: {
			allowEmpty: false,
			allowExpressions: false,
		},
		notes: ['Rendered as checkbox in n8n UI'],
	},

	dateTime: {
		type: 'primitive',
		jsType: 'string',
		description: 'A date and time value in ISO 8601 format',
		example: '2024-01-20T10:30:00Z',
		examples: [
			'2024-01-20T10:30:00Z',
			'2024-01-20',
			'{{ $now }}',
		],
		validation: {
			allowEmpty: false,
			allowExpressions: true,
			pattern: '^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z?)?$',
		},
		notes: ['Accepts ISO 8601 format', 'Can use n8n date expressions'],
	},

	color: {
		type: 'primitive',
		jsType: 'string',
		description: 'A color value in hex format',
		example: '#FF5733',
		examples: ['#FF5733', '#000000', '#FFFFFF', '{{ $json.color }}'],
		validation: {
			allowEmpty: false,
			allowExpressions: true,
			pattern: '^#[0-9A-Fa-f]{6}$',
		},
		notes: ['Must be 6-digit hex color', 'Rendered with color picker in UI'],
	},

	json: {
		type: 'primitive',
		jsType: 'string',
		description: 'A JSON string that can be parsed into any structure',
		example: '{"key": "value", "nested": {"data": 123}}',
		examples: [
			'{}',
			'{"name": "John", "age": 30}',
			'[1, 2, 3]',
			'{{ $json }}',
		],
		validation: {
			allowEmpty: false,
			allowExpressions: true,
		},
		notes: ['Must be valid JSON when parsed', 'Often used for custom payloads'],
	},

	// ============================================================================
	// OPTION TYPES - Selection from predefined choices
	// ============================================================================

	options: {
		type: 'primitive',
		jsType: 'string',
		description: 'Single selection from a list of predefined options',
		example: 'option1',
		examples: ['GET', 'POST', 'channelMessage', 'update'],
		validation: {
			allowEmpty: false,
			allowExpressions: false,
		},
		notes: [
			'Value must match one of the defined option values',
			'Rendered as dropdown in UI',
			'Options defined in property.options array',
		],
	},

	multiOptions: {
		type: 'array',
		jsType: 'array',
		description: 'Multiple selections from a list of predefined options',
		structure: {
			items: {
				type: 'string',
				description: 'Selected option value',
			},
		},
		example: ['option1', 'option2'],
		examples: [[], ['GET', 'POST'], ['read', 'write', 'delete']],
		validation: {
			allowEmpty: true,
			allowExpressions: false,
		},
		notes: [
			'Array of option values',
			'Each value must exist in property.options',
			'Rendered as multi-select dropdown',
		],
	},

	// ============================================================================
	// COLLECTION TYPES - Complex nested structures
	// ============================================================================

	collection: {
		type: 'collection',
		jsType: 'object',
		description: 'A group of related properties with dynamic values',
		structure: {
			properties: {
				'<propertyName>': {
					type: 'any',
					description: 'Any nested property from the collection definition',
				},
			},
			flexible: true,
		},
		example: {
			name: 'John Doe',
			email: 'john@example.com',
			age: 30,
		},
		examples: [
			{},
			{ key1: 'value1', key2: 123 },
			{ nested: { deep: { value: true } } },
		],
		validation: {
			allowEmpty: true,
			allowExpressions: true,
		},
		notes: [
			'Properties defined in property.values array',
			'Each property can be any type',
			'UI renders as expandable section',
		],
	},

	fixedCollection: {
		type: 'collection',
		jsType: 'object',
		description: 'A collection with predefined groups of properties',
		structure: {
			properties: {
				'<collectionName>': {
					type: 'array',
					description: 'Array of collection items',
					items: {
						type: 'object',
						description: 'Collection item with defined properties',
					},
				},
			},
			required: [],
		},
		example: {
			headers: [
				{ name: 'Content-Type', value: 'application/json' },
				{ name: 'Authorization', value: 'Bearer token' },
			],
		},
		examples: [
			{},
			{ queryParameters: [{ name: 'id', value: '123' }] },
			{
				headers: [{ name: 'Accept', value: '*/*' }],
				queryParameters: [{ name: 'limit', value: '10' }],
			},
		],
		validation: {
			allowEmpty: true,
			allowExpressions: true,
		},
		notes: [
			'Each collection has predefined structure',
			'Often used for headers, parameters, etc.',
			'Supports multiple values per collection',
		],
	},

	// ============================================================================
	// SPECIAL n8n TYPES - Advanced functionality
	// ============================================================================

	resourceLocator: {
		type: 'special',
		jsType: 'object',
		description: 'A flexible way to specify a resource by ID, name, URL, or list',
		structure: {
			properties: {
				mode: {
					type: 'string',
					description: 'How the resource is specified',
					enum: ['id', 'url', 'list'],
					required: true,
				},
				value: {
					type: 'string',
					description: 'The resource identifier',
					required: true,
				},
			},
			required: ['mode', 'value'],
		},
		example: {
			mode: 'id',
			value: 'abc123',
		},
		examples: [
			{ mode: 'url', value: 'https://example.com/resource/123' },
			{ mode: 'list', value: 'item-from-dropdown' },
			{ mode: 'id', value: '{{ $json.resourceId }}' },
		],
		validation: {
			allowEmpty: false,
			allowExpressions: true,
		},
		notes: [
			'Provides flexible resource selection',
			'Mode determines how value is interpreted',
			'UI adapts based on selected mode',
		],
	},

	resourceMapper: {
		type: 'special',
		jsType: 'object',
		description: 'Maps input data fields to resource fields with transformation options',
		structure: {
			properties: {
				mappingMode: {
					type: 'string',
					description: 'How fields are mapped',
					enum: ['defineBelow', 'autoMapInputData'],
				},
				value: {
					type: 'object',
					description: 'Field mappings',
					properties: {
						'<fieldName>': {
							type: 'string',
							description: 'Expression or value for this field',
						},
					},
					flexible: true,
				},
			},
		},
		example: {
			mappingMode: 'defineBelow',
			value: {
				name: '{{ $json.fullName }}',
				email: '{{ $json.emailAddress }}',
				status: 'active',
			},
		},
		examples: [
			{ mappingMode: 'autoMapInputData', value: {} },
			{
				mappingMode: 'defineBelow',
				value: { id: '{{ $json.userId }}', name: '{{ $json.name }}' },
			},
		],
		validation: {
			allowEmpty: false,
			allowExpressions: true,
		},
		notes: [
			'Complex mapping with UI assistance',
			'Can auto-map or manually define',
			'Supports field transformations',
		],
	},

	filter: {
		type: 'special',
		jsType: 'object',
		description: 'Defines conditions for filtering data with boolean logic',
		structure: {
			properties: {
				conditions: {
					type: 'array',
					description: 'Array of filter conditions',
					items: {
						type: 'object',
						properties: {
							id: {
								type: 'string',
								description: 'Unique condition identifier',
								required: true,
							},
							leftValue: {
								type: 'any',
								description: 'Left side of comparison',
							},
							operator: {
								type: 'object',
								description: 'Comparison operator',
								required: true,
								properties: {
									type: {
										type: 'string',
										enum: ['string', 'number', 'boolean', 'dateTime', 'array', 'object'],
										required: true,
									},
									operation: {
										type: 'string',
										description: 'Operation to perform',
										required: true,
									},
								},
							},
							rightValue: {
								type: 'any',
								description: 'Right side of comparison',
							},
						},
					},
					required: true,
				},
				combinator: {
					type: 'string',
					description: 'How to combine conditions',
					enum: ['and', 'or'],
					required: true,
				},
			},
			required: ['conditions', 'combinator'],
		},
		example: {
			conditions: [
				{
					id: 'abc-123',
					leftValue: '{{ $json.status }}',
					operator: { type: 'string', operation: 'equals' },
					rightValue: 'active',
				},
			],
			combinator: 'and',
		},
		validation: {
			allowEmpty: false,
			allowExpressions: true,
		},
		notes: [
			'Advanced filtering UI in n8n',
			'Supports complex boolean logic',
			'Operations vary by data type',
		],
	},

	assignmentCollection: {
		type: 'special',
		jsType: 'object',
		description: 'Defines variable assignments with expressions',
		structure: {
			properties: {
				assignments: {
					type: 'array',
					description: 'Array of variable assignments',
					items: {
						type: 'object',
						properties: {
							id: {
								type: 'string',
								description: 'Unique assignment identifier',
								required: true,
							},
							name: {
								type: 'string',
								description: 'Variable name',
								required: true,
							},
							value: {
								type: 'any',
								description: 'Value to assign',
								required: true,
							},
							type: {
								type: 'string',
								description: 'Data type of the value',
								enum: ['string', 'number', 'boolean', 'array', 'object'],
							},
						},
					},
					required: true,
				},
			},
			required: ['assignments'],
		},
		example: {
			assignments: [
				{
					id: 'abc-123',
					name: 'userName',
					value: '{{ $json.name }}',
					type: 'string',
				},
				{
					id: 'def-456',
					name: 'userAge',
					value: 30,
					type: 'number',
				},
			],
		},
		validation: {
			allowEmpty: false,
			allowExpressions: true,
		},
		notes: [
			'Used in Set node and similar',
			'Each assignment can use expressions',
			'Type helps with validation',
		],
	},

	// ============================================================================
	// CREDENTIAL TYPES - Authentication and credentials
	// ============================================================================

	credentials: {
		type: 'special',
		jsType: 'string',
		description: 'Reference to credential configuration',
		example: 'googleSheetsOAuth2Api',
		examples: ['httpBasicAuth', 'slackOAuth2Api', 'postgresApi'],
		validation: {
			allowEmpty: false,
			allowExpressions: false,
		},
		notes: [
			'References credential type name',
			'Credential must be configured in n8n',
			'Type name matches credential definition',
		],
	},

	credentialsSelect: {
		type: 'special',
		jsType: 'string',
		description: 'Dropdown to select from available credentials',
		example: 'credential-id-123',
		examples: ['cred-abc', 'cred-def', '{{ $credentials.id }}'],
		validation: {
			allowEmpty: false,
			allowExpressions: true,
		},
		notes: [
			'User selects from configured credentials',
			'Returns credential ID',
			'Used when multiple credential instances exist',
		],
	},

	// ============================================================================
	// UI-ONLY TYPES - Display elements without data
	// ============================================================================

	hidden: {
		type: 'special',
		jsType: 'string',
		description: 'Hidden property not shown in UI (used for internal logic)',
		example: '',
		validation: {
			allowEmpty: true,
			allowExpressions: true,
		},
		notes: [
			'Not rendered in UI',
			'Can store metadata or computed values',
			'Often used for version tracking',
		],
	},

	button: {
		type: 'special',
		jsType: 'string',
		description: 'Clickable button that triggers an action',
		example: '',
		validation: {
			allowEmpty: true,
			allowExpressions: false,
		},
		notes: [
			'Triggers action when clicked',
			'Does not store a value',
			'Action defined in routing property',
		],
	},

	callout: {
		type: 'special',
		jsType: 'string',
		description: 'Informational message box (warning, info, success, error)',
		example: '',
		validation: {
			allowEmpty: true,
			allowExpressions: false,
		},
		notes: [
			'Display-only, no value stored',
			'Used for warnings and hints',
			'Style controlled by typeOptions',
		],
	},

	notice: {
		type: 'special',
		jsType: 'string',
		description: 'Notice message displayed to user',
		example: '',
		validation: {
			allowEmpty: true,
			allowExpressions: false,
		},
		notes: ['Similar to callout', 'Display-only element', 'Provides contextual information'],
	},

	// ============================================================================
	// UTILITY TYPES - Special-purpose functionality
	// ============================================================================

	workflowSelector: {
		type: 'special',
		jsType: 'string',
		description: 'Dropdown to select another workflow',
		example: 'workflow-123',
		examples: ['wf-abc', '{{ $json.workflowId }}'],
		validation: {
			allowEmpty: false,
			allowExpressions: true,
		},
		notes: [
			'Selects from available workflows',
			'Returns workflow ID',
			'Used in Execute Workflow node',
		],
	},

	curlImport: {
		type: 'special',
		jsType: 'string',
		description: 'Import configuration from cURL command',
		example: 'curl -X GET https://api.example.com/data',
		validation: {
			allowEmpty: true,
			allowExpressions: false,
		},
		notes: [
			'Parses cURL command to populate fields',
			'Used in HTTP Request node',
			'One-time import feature',
		],
	},

	icon: {
		type: 'primitive',
		jsType: 'string',
		description: 'Icon identifier for visual representation',
		example: 'fa:envelope',
		examples: ['fa:envelope', 'fa:user', 'fa:cog', 'file:slack.svg'],
		validation: {
			allowEmpty: false,
			allowExpressions: false,
		},
		notes: [
			'References icon by name or file path',
			'Supports Font Awesome icons (fa:) and file paths (file:)',
			'Used for visual customization in UI',
		],
	},
};

/**
 * Real-world examples for complex types
 *
 * These examples come from actual n8n workflows and demonstrate
 * correct usage patterns for complex property types.
 *
 * @constant
 */
export const COMPLEX_TYPE_EXAMPLES = {
	collection: {
		basic: {
			name: 'John Doe',
			email: 'john@example.com',
		},
		nested: {
			user: {
				firstName: 'Jane',
				lastName: 'Smith',
			},
			preferences: {
				theme: 'dark',
				notifications: true,
			},
		},
		withExpressions: {
			id: '{{ $json.userId }}',
			timestamp: '{{ $now }}',
			data: '{{ $json.payload }}',
		},
	},

	fixedCollection: {
		httpHeaders: {
			headers: [
				{ name: 'Content-Type', value: 'application/json' },
				{ name: 'Authorization', value: 'Bearer {{ $credentials.token }}' },
			],
		},
		queryParameters: {
			queryParameters: [
				{ name: 'page', value: '1' },
				{ name: 'limit', value: '100' },
			],
		},
		multipleCollections: {
			headers: [{ name: 'Accept', value: 'application/json' }],
			queryParameters: [{ name: 'filter', value: 'active' }],
		},
	},

	filter: {
		simple: {
			conditions: [
				{
					id: '1',
					leftValue: '{{ $json.status }}',
					operator: { type: 'string', operation: 'equals' },
					rightValue: 'active',
				},
			],
			combinator: 'and',
		},
		complex: {
			conditions: [
				{
					id: '1',
					leftValue: '{{ $json.age }}',
					operator: { type: 'number', operation: 'gt' },
					rightValue: 18,
				},
				{
					id: '2',
					leftValue: '{{ $json.country }}',
					operator: { type: 'string', operation: 'equals' },
					rightValue: 'US',
				},
			],
			combinator: 'and',
		},
	},

	resourceMapper: {
		autoMap: {
			mappingMode: 'autoMapInputData',
			value: {},
		},
		manual: {
			mappingMode: 'defineBelow',
			value: {
				firstName: '{{ $json.first_name }}',
				lastName: '{{ $json.last_name }}',
				email: '{{ $json.email_address }}',
				status: 'active',
			},
		},
	},

	assignmentCollection: {
		basic: {
			assignments: [
				{
					id: '1',
					name: 'fullName',
					value: '{{ $json.firstName }} {{ $json.lastName }}',
					type: 'string',
				},
			],
		},
		multiple: {
			assignments: [
				{ id: '1', name: 'userName', value: '{{ $json.name }}', type: 'string' },
				{ id: '2', name: 'userAge', value: '{{ $json.age }}', type: 'number' },
				{ id: '3', name: 'isActive', value: true, type: 'boolean' },
			],
		},
	},
};
