/**
 * Logging Utilities
 *
 * Provides error serialization and structured logging utilities to prevent
 * [object Object] logs in production. All functions handle circular references
 * and properly serialize Error objects with their properties.
 *
 * Features:
 * - Error serialization with stack traces
 * - Circular reference detection and handling
 * - Convenient logging wrappers
 * - TypeScript-safe error handling
 */

/**
 * Serializes an error object to a JSON string.
 * Handles both Error instances and plain objects.
 *
 * @param error - Error object or unknown value to serialize
 * @returns JSON string representation of the error
 *
 * @example
 * ```typescript
 * const err = new Error('Something went wrong');
 * const serialized = serializeError(err);
 * // Returns: '{"name": "Error", "message": "Something went wrong", "stack": "..."}'
 * ```
 */
export function serializeError(error: unknown): string {
	if (error instanceof Error) {
		const errorObject: Record<string, any> = {
			name: error.name,
			message: error.message,
			stack: error.stack
		};

		// Add custom properties from the error object
		for (const key of Object.keys(error)) {
			if (!(key in errorObject)) {
				errorObject[key] = (error as any)[key];
			}
		}

		return JSON.stringify(errorObject, null, 2);
	}

	return JSON.stringify(error, null, 2);
}

/**
 * Serializes an object to a JSON string with circular reference handling.
 * Prevents "Converting circular structure to JSON" errors.
 *
 * @param obj - Object to serialize
 * @param maxDepth - Maximum depth for nested objects (default: 10)
 * @returns JSON string representation of the object
 *
 * @example
 * ```typescript
 * const circular: any = { a: 1 };
 * circular.self = circular;
 * const serialized = serializeObject(circular);
 * // Returns: '{"a": 1, "self": "[Circular]"}'
 * ```
 */
export function serializeObject(obj: unknown, maxDepth: number = 10): string {
	const seen = new WeakSet();

	const replacer = (key: string, value: any): any => {
		if (typeof value === 'object' && value !== null) {
			if (seen.has(value)) {
				return '[Circular]';
			}
			seen.add(value);
		}
		return value;
	};

	return JSON.stringify(obj, replacer, 2);
}

/**
 * Logs an error to console.error with proper serialization.
 * Convenience wrapper around serializeError().
 *
 * @param prefix - Log prefix (e.g., '[ComponentName]')
 * @param error - Error object or unknown value to log
 *
 * @example
 * ```typescript
 * try {
 *   // ... some operation
 * } catch (error) {
 *   logError('[QueueProcessor]', error);
 * }
 * ```
 */
export function logError(prefix: string, error: unknown): void {
	if (error instanceof Error) {
		console.error(prefix, error.message);
		if (error.stack) {
			console.error('Stack:', error.stack);
		}
	} else {
		console.error(prefix, serializeError(error));
	}
}

/**
 * Logs an object to console.log with proper serialization.
 * Handles circular references automatically.
 *
 * @param prefix - Log prefix (e.g., '[ComponentName]')
 * @param obj - Object to log
 *
 * @example
 * ```typescript
 * const config = { url: 'https://example.com', timeout: 5000 };
 * logObject('[Config]', config);
 * ```
 */
export function logObject(prefix: string, obj: unknown): void {
	console.log(prefix, serializeObject(obj));
}
