import {
	INodeType,
	INodeTypeDescription,
	IExecuteFunctions,
	INodeExecutionData,
	NodeConnectionType,
} from 'n8n-workflow';

import * as redis from 'redis';

export class _StorageReader implements INodeType {
	description: INodeTypeDescription = {
		displayName: 'StorageReader',
		name: 'storageReader',
		group: ['transform'],
		version: 1,
		description: 'Получает из Redis ключи Storage и добавляет их в DATA, остальные данные передаёт дальше',
		defaults: {
			name: 'StorageReader',
		},
		inputs: [NodeConnectionType.Main],
		outputs: [NodeConnectionType.Main],
		properties: [
			{
				displayName: 'Redis Storage Keys',
				name: 'redisStorageKeys',
				type: 'string',
				default: 'started_sessions,shift_restart',
				description: 'Через запятую перечислите ключи из Redis для получения Storage',
			},
		],
	};

	async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
		const item = this.getInputData()[0]; // Берём один элемент

		// Получаем ключи из параметров узла
		const redisStorageKeysStr = this.getNodeParameter('redisStorageKeys', 0) as string;
		const redisStorageKeys = redisStorageKeysStr.split(',').map(k => k.trim()).filter(k => k.length > 0);

		// Берём хост и порт из переменных окружения
		const redisHost = process.env.REDIS_HOST || 'redis';
		const redisPort = Number(process.env.REDIS_PORT || '6379');

		const client = redis.createClient({
			socket: { host: redisHost, port: redisPort },
		});

		client.on('error', (err: Error) => this.logger.error('Redis Client Error', { message: err.message, stack: err.stack }));

		await client.connect();

		const storageData: Record<string, any> = {};

		for (const key of redisStorageKeys) {
			try {
				const rawValue = await client.get(key);
				if (rawValue) {
					try {
						storageData[key] = JSON.parse(rawValue);
					} catch {
						storageData[key] = rawValue;
					}
				} else {
					storageData[key] = null;
				}
			} catch (e: unknown) {
				this.logger.warn(`Ошибка при получении ключа "${key}" из Redis: ${(e as Error).message || e}`);
				storageData[key] = null;
			}
		}

		await client.quit();

		// Формируем METADATA заново
		const nodeInfo = this.getNode();
		const workflowName = this.getWorkflow().name;

		const newItem: INodeExecutionData = {
			json: {
				DATA: {
					...(item.json.DATA && typeof item.json.DATA === 'object' ? item.json.DATA : {}),
					Storage: storageData,
				},
				METADATA: {
					from: nodeInfo.name,
					id: nodeInfo.name,
					workflow: workflowName,
					time: Date.now(),
				},
			},
			binary: item.binary,
		};

		return [[newItem]];
	}
}
