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

function getValueByPath(obj: any, path: string): any {
	return path.split('.').reduce((acc, key) => (acc && typeof acc === 'object' ? acc[key] : undefined), obj);
}

export class _StorageWriter implements INodeType {
	description: INodeTypeDescription = {
		displayName: 'StorageWriter',
		name: 'storageWriter',
		group: ['transform'],
		version: 1,
		description: 'Сохраняет данные в Redis по ключу',
		defaults: {
			name: 'StorageWriter',
		},
		inputs: [NodeConnectionType.Main],
		outputs: [NodeConnectionType.Main],
		properties: [
			{
				displayName: 'Redis Key',
				name: 'redisKey',
				type: 'string',
				default: '',
				required: true,
				description: 'Ключ в Redis, под которым сохраняется значение',
			},
			{
				displayName: 'Path to Value (например, DATA.Storage.shift_restart)',
				name: 'valuePath',
				type: 'string',
				default: '',
				required: false,
				description: 'Путь к значению внутри JSON. Если пусто — сохраняется весь DATA',
			},
		],
	};

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

		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();

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

		json.METADATA = {
			from: nodeInfo.name,
			id: nodeInfo.name,
			workflow: workflowName,
			time: Date.now(),
		};

		const key = this.getNodeParameter('redisKey', 0, '') as string;
		const valuePath = this.getNodeParameter('valuePath', 0, '') as string;

		const valueToStore = valuePath ? getValueByPath(json, valuePath) : json.DATA;

		try {
			await client.set(key, JSON.stringify(valueToStore));
			this.logger.info(`Сохранено в Redis: [${key}] =`, valueToStore);
		} catch (e: unknown) {
			this.logger.error(`Ошибка записи ключа "${key}" в Redis`, { error: e });
		}

		await client.quit();

		return [[item]];
	}
}
