/* eslint-disable no-unused-vars */
import {
	IExecuteFunctions,
	INodeExecutionData,
	INodeType,
	INodeTypeDescription,
	IDataObject,
	GenericValue,
} from 'n8n-workflow';

interface KeitaroError extends Error {
	config?: {
		url?: string;
	};
	response?: {
		status?: number;
		statusText?: string;
		data?: unknown;
	};
}

interface KeitaroResponse {
	status?: string | number;
	error?: string;
	message?: string;
	data?: unknown;
	response?: unknown;
	result?: unknown;
	body?: unknown;
	statusCode?: number;
	statusMessage?: string;
}

// Базовый интерфейс для всех сущностей Keitaro
interface KeitaroEntity {
	id: number;
	created_at?: string;
	updated_at?: string;
}

// Интерфейс для кампании
interface KeitaroCampaign extends KeitaroEntity {
	alias: string;
	name: string;
	type: string;
	uniqueness_method: string;
	cookies_ttl: number;
	position: number;
	state: string;
	cost_type: string;
	cost_value: number;
	cost_currency: string;
	group_id: number;
	bind_visitors: string;
	traffic_source_id: number;
	token: string;
	cost_auto: boolean;
	domain_id: number;
	notes: string;
	parameters: Record<string, {
		name: string;
		placeholder: string;
		alias?: string;
	}>;
	uniqueness_use_cookies: boolean;
	traffic_loss: number;
	domain: string;
	postbacks: unknown[];
	group: string;
}

// Интерфейс для потока
interface KeitaroStream extends KeitaroEntity {
	name: string;
	campaign_id: number;
	position: number;
	state: string;
	weight: number;
	offers: unknown[];
	landings: unknown[];
	filters: unknown[];
	action_options: unknown;
	schema: string;
	type: string;
	comments?: string;
}

// Интерфейс для лендинга
interface KeitaroLanding extends KeitaroEntity {
	name: string;
	url: string;
	state: string;
	group_id: number;
	archived: boolean;
	notes?: string;
}

// Интерфейс для оффера
interface KeitaroOffer extends KeitaroEntity {
	name: string;
	url: string;
	state: string;
	group_id: number;
	payout: number;
	payout_auto: boolean;
	payout_type: string;
	payout_currency: string;
	archived: boolean;
	notes?: string;
}

// Интерфейс для трафика
interface KeitaroTraffic extends KeitaroEntity {
	ip: string;
	user_agent: string;
	referrer?: string;
	language?: string;
	country?: string;
	region?: string;
	city?: string;
	browser_name?: string;
	browser_version?: string;
	os_name?: string;
	os_version?: string;
	device_type?: string;
	device_brand?: string;
	device_model?: string;
}

// Интерфейс для пользователя
interface KeitaroUser extends KeitaroEntity {
	login: string;
	email: string;
	password?: string;
	name: string;
	status: string;
	role: string;
	receive_reports: boolean;
}

// Интерфейс для записи в блэклисте
interface KeitaroBlacklist extends KeitaroEntity {
	value: string;
	type: string;
	comment?: string;
}

// Интерфейс для бота
interface KeitaroBot extends KeitaroEntity {
	name: string;
	criteria: unknown[];
	comment?: string;
}

// Интерфейс для постбэка
interface KeitaroPostback extends KeitaroEntity {
	name: string;
	url: string;
	status: string;
	trigger: string;
	campaigns: number[];
	networks: number[];
	countries: string[];
	sending_status?: string;
	sending_errors?: string[];
	last_sent_at?: string;
	// Новые поля для поддержки всех параметров постбека
	postback_key?: string;
	lead_status?: string[];
	sale_status?: string[];
	rejected_status?: string[];
	reg_status?: string[];   // Поддержка новых статусов для Keitaro 10.3+
	dep_status?: string[];   // Поддержка новых статусов для Keitaro 10.3+
	currency?: string;
	parameters?: {
		subid?: string;
		status?: string;
		payout?: number;
		currency?: string;
		click_id?: string;
		transaction_id?: string;
		cost?: number;      // Стоимость конверсии
		tid?: string;       // ID транзакции для upsell/rebill
		ignore_status?: string[]; // Статусы, которые нужно игнорировать
		return?: string;    // Сообщение об успехе
		[key: string]: unknown;
	};
	headers?: Record<string, string>;
	method?: 'GET' | 'POST';
	timeout?: number;
	retry_count?: number;
	retry_delay?: number;
}

// Интерфейс для источника
interface KeitaroSource extends KeitaroEntity {
	name: string;
	postback_url?: string;
	template?: string;
	parameters?: Record<string, unknown>;
}

// Интерфейс для конверсии
interface KeitaroConversion extends KeitaroEntity {
	click_id: string;
	session_id?: number;
	action_id?: number;
	stream_id?: number;
	campaign_id?: number;
	landing_id?: number;
	offer_id?: number;
	revenue?: number;
	cost?: number;
	currency?: string;
	status?: string;
	conversion_status?: string;
	declined_reason?: string;
	sub_id_1?: string;
	sub_id_2?: string;
	sub_id_3?: string;
	sub_id_4?: string;
	sub_id_5?: string;
	transaction_id?: string;
	comment?: string;
}

// Интерфейс для домена
interface KeitaroDomain extends KeitaroEntity {
	name: string;
	campaign_ids: number[];
	ssl: boolean;
	redirect_type: string;
	comments?: string;
}

// Интерфейс для клика
interface KeitaroClick extends KeitaroEntity {
	// Базовые поля клика
	campaign_id: number;
	stream_id: number;
	landing_id?: number;
	offer_id?: number;
	
	// Информация о стоимости и доходе
	cost?: number;
	revenue?: number;
	currency?: string;
	
	// Параметры трафика
	keyword?: string;
	source?: string;
	sub_id_1?: string;
	sub_id_2?: string;
	sub_id_3?: string;
	sub_id_4?: string;
	sub_id_5?: string;
	sub_id_6?: string;
	sub_id_7?: string;
	sub_id_8?: string;
	sub_id_9?: string;
	sub_id_10?: string;
	sub_id_11?: string;
	
	// Технические параметры
	is_bot?: boolean;
	is_unique?: boolean;
	is_conversion?: boolean;
	conversion_status?: string;
	conversions_count?: number;
	
	// Информация о посетителе
	ip?: string;
	user_agent?: string;
	language?: string;
	referrer?: string;
	
	// Гео-данные
	country?: string;
	region?: string;
	city?: string;
	
	// Информация об устройстве
	browser_name?: string;
	browser_version?: string;
	os_name?: string;
	os_version?: string;
	device_type?: string;
	device_brand?: string;
	device_model?: string;
	is_mobile?: boolean;
	is_tablet?: boolean;
	is_desktop?: boolean;
	
	// Сетевая информация
	isp?: string;
	connection_type?: string;
	ip_type?: string;
	
	// Ссылки и перенаправления
	original_url?: string;
	landing_url?: string;
	offer_url?: string;
	
	// Прочие поля
	browser?: string;
	os?: string;
	comment?: string;
	session_id?: string;
}

// Интерфейс для фильтра
interface KeitaroFilter extends KeitaroEntity {
	name: string;
	state: string;
	conditions: unknown[];
	mode: string;
}

// Интерфейс для настроек
interface KeitaroSettings extends KeitaroEntity {
	key: string;
	value: unknown;
}

// Интерфейс для лога
interface KeitaroLog extends KeitaroEntity {
	type: string;
	message: string;
	details?: unknown;
}

// Интерфейс для статистики
interface KeitaroStats {
	date: string;
	clicks: number;
	unique_clicks: number;
	leads: number;
	conversions: number;
	revenue: number;
	cost: number;
	profit: number;
	cr: number;
	roi: number;
	epc: number;
	cpc: number;
	impressions?: number;
	ctr?: number;
}

// Интерфейс для группы
interface KeitaroGroup extends KeitaroEntity {
	name: string;
	type: string;
}

// Функция для определения типа данных на основе ресурса
function getTypedResponse(resource: string, data: unknown): unknown {
	switch (resource) {
		case 'campaign':
			return data as KeitaroCampaign;
		case 'stream':
			return data as KeitaroStream;
		case 'landing':
			return data as KeitaroLanding;
		case 'offer':
			return data as KeitaroOffer;
		case 'traffic':
			return data as KeitaroTraffic;
		case 'user':
			return data as KeitaroUser;
		case 'blacklist':
			return data as KeitaroBlacklist;
		case 'bot':
			return data as KeitaroBot;
		case 'postback':
			return data as KeitaroPostback;
		case 'source':
			return data as KeitaroSource;
		case 'conversion':
			return data as KeitaroConversion;
		case 'domain':
			return data as KeitaroDomain;
		case 'click':
			return data as KeitaroClick;
		case 'filter':
			return data as KeitaroFilter;
		case 'settings':
			return data as KeitaroSettings;
		case 'log':
			return data as KeitaroLog;
		case 'stats':
			return data as KeitaroStats;
		case 'group':
			return data as KeitaroGroup;
		default:
			return data;
	}
}

// Функция для определения типа ответа
function getResponseData(response: KeitaroResponse): unknown {
	// Проверяем разные форматы ответа API Keitaro
	if (response && typeof response === 'object') {
		// Проверяем поле status для определения успешности запроса
		if ('status' in response) {
			// Если статус не "success", выбрасываем ошибку
			if (response.status !== 'success' && response.status !== 200) {
				const errorMessage = response.error || response.message || 'Неизвестная ошибка API';
				throw new Error(`Ошибка API: ${errorMessage}`);
			}
		}
		
		if ('data' in response && response.data !== undefined) {
			return response.data;
		} else if ('response' in response && response.response !== undefined) {
			return response.response;
		} else if ('result' in response && response.result !== undefined) {
			return response.result;
		} else if ('body' in response && response.body !== undefined) {
			return response.body;
		}
	}
	
	// Если не удалось найти данные в известных полях, возвращаем весь ответ
	return response;
}

// Функция для безопасного логирования объектов
function safeStringify(obj: unknown): string {
	try {
		return JSON.stringify(obj, (key, value) => {
			// Исключаем циклические ссылки
			if (key === 'socket' || key === '_httpMessage' || key === 'req' || key === 'res') {
				return '[Circular]';
			}
			return value;
		}, 2);
	} catch (error) {
		return `[Не удалось сериализовать объект: ${error instanceof Error ? error.message : String(error)}]`;
	}
}

// Хелпер для создания пути API
function getApiPath(resourceMap: Record<string, string>, resource: string, resourceId?: string, operation?: string): string {
	// Специальная обработка для клика с операцией getAll - используем /clicks/log
	if (resource === 'click' && operation === 'getAll') {
		return '/admin_api/v1/clicks/log';
	}
	
	// Специальная обработка для конверсий с операцией getAll - используем /conversions/log
	if (resource === 'conversion' && operation === 'getAll') {
		return '/admin_api/v1/conversions/log';
	}
	
	// Специальная обработка для статистики
	if (resource === 'stats' && operation === 'getAll') {
		return '/admin_api/v1/report/build';
	}
	
	// Специальная обработка для конверсий
	if (resource === 'conversion') {
		return `/admin_api/v1/conversions${resourceId ? `/${resourceId}` : ''}`;
	}
	
	const resourcePath = resourceMap[resource];
	if (!resourcePath) {
		throw new Error(`Неизвестный ресурс: ${resource}`);
	}
	
	return `/admin_api/v1/${resourcePath}${resourceId ? `/${resourceId}` : ''}`;
}

// Хелпер для форматирования URL API
function formatBaseUrl(domain: string): string {
	let baseUrl = domain.trim();
	// Удаляем завершающий слеш, если он есть
	if (baseUrl.endsWith('/')) {
		baseUrl = baseUrl.slice(0, -1);
	}
	// Добавляем протокол, если его нет
	if (!baseUrl.startsWith('http://') && !baseUrl.startsWith('https://')) {
		baseUrl = `https://${baseUrl}`;
	}
	return baseUrl;
}

export class Keitaro implements INodeType {
	description: INodeTypeDescription = {
		displayName: 'Keitaro',
		name: 'keitaro',
		icon: 'file:keitaro.svg',
		group: ['transform'],
		version: 1,
		subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
		description: 'Работа с API Keitaro',
		defaults: {
			name: 'Keitaro',
		},
		inputs: ['main'],
		outputs: ['main'],
		credentials: [
			{
				name: 'keitaroApi',
				required: true,
			},
		],
		requestDefaults: {
			baseURL: '={{$credentials.domain}}',
			headers: {
				'Accept': 'application/json',
				'Content-Type': 'application/json',
			},
		},
		properties: [
			{
				displayName: 'Ресурс',
				name: 'resource',
				type: 'options',
				noDataExpression: true,
				required: true,
				options: [
					{
						name: 'Кампания',
						value: 'campaign',
					},
					{
						name: 'Поток',
						value: 'stream',
					},
					{
						name: 'Лендинг',
						value: 'landing',
					},
					{
						name: 'Оффер',
						value: 'offer',
					},
					{
						name: 'Трафик',
						value: 'traffic',
					},
					{
						name: 'Пользователь',
						value: 'user',
					},
					{
						name: 'Блэклист',
						value: 'blacklist',
					},
					{
						name: 'Бот',
						value: 'bot',
					},
					{
						name: 'Постбэк',
						value: 'postback',
					},
					{
						name: 'Источник',
						value: 'source',
					},
					{
						name: 'Конверсия',
						value: 'conversion',
					},
					{
						name: 'Домен',
						value: 'domain',
					},
					{
						name: 'Клик',
						value: 'click',
					},
					{
						name: 'Фильтр',
						value: 'filter',
					},
					{
						name: 'Настройки',
						value: 'settings',
					},
					{
						name: 'Лог',
						value: 'log',
					},
					{
						name: 'Статистика',
						value: 'stats',
					},
					{
						name: 'Группа',
						value: 'group',
					},
				],
				default: 'campaign',
				description: 'Тип ресурса для работы',
			},
			{
				displayName: 'Операция',
				name: 'operation',
				type: 'options',
				noDataExpression: true,
				required: true,
				displayOptions: {
					show: {
						resource: [
							'campaign',
							'stream',
							'landing',
							'offer',
							'traffic',
							'user',
							'blacklist',
							'bot',
							'postback',
							'source',
							'conversion',
							'domain',
							'click',
							'filter',
							'settings',
							'log',
							'stats',
							'group',
						],
					},
				},
				options: [
					{
						name: 'Получить',
						value: 'get',
						description: 'Получить информацию',
						action: 'Получить информацию',
					},
					{
						name: 'Получить Все',
						value: 'getAll',
						description: 'Получить список всех записей',
						action: 'Получить список всех записей',
					},
					{
						name: 'Создать',
						value: 'create',
						description: 'Создать новую запись',
						action: 'Создать новую запись',
					},
					{
						name: 'Обновить',
						value: 'update',
						description: 'Обновить существующую запись',
						action: 'Обновить существующую запись',
					},
					{
						name: 'Удалить',
						value: 'delete',
						description: 'Удалить запись',
						action: 'Удалить запись',
					},
					{
						name: 'Тестировать',
						value: 'test',
						description: 'Тестировать постбэк (отправить тестовую конверсию)',
						action: 'Тестировать постбэк',
						displayOptions: {
							show: {
								resource: [
									'postback',
								],
							},
						},
					},
				],
				default: 'get',
			},
			{
				displayName: 'ID Кампании',
				name: 'campaignId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['campaign'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID кампании',
			},
			{
				displayName: 'Данные Кампании',
				name: 'campaignData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['campaign'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные кампании в формате JSON',
			},
			{
				displayName: 'ID Потока',
				name: 'streamId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['stream'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID потока',
			},
			{
				displayName: 'Данные Потока',
				name: 'streamData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['stream'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные потока в формате JSON',
			},
			{
				displayName: 'ID Лендинга',
				name: 'landingId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['landing'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID лендинга',
			},
			{
				displayName: 'Данные Лендинга',
				name: 'landingData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['landing'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные лендинга в формате JSON',
			},
			{
				displayName: 'ID Оффера',
				name: 'offerId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['offer'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID оффера',
			},
			{
				displayName: 'Данные Оффера',
				name: 'offerData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['offer'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные оффера в формате JSON',
			},
			{
				displayName: 'ID Пользователя',
				name: 'userId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['user'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID пользователя',
			},
			{
				displayName: 'Данные Пользователя',
				name: 'userData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['user'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные пользователя в формате JSON',
			},
			{
				displayName: 'ID Блэклиста',
				name: 'blacklistId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['blacklist'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID записи в блэклисте',
			},
			{
				displayName: 'Данные Блэклиста',
				name: 'blacklistData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['blacklist'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные записи в блэклисте в формате JSON',
			},
			{
				displayName: 'ID Бота',
				name: 'botId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['bot'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID бота',
			},
			{
				displayName: 'Данные Бота',
				name: 'botData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['bot'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные бота в формате JSON',
			},
			{
				displayName: 'ID Постбэка',
				name: 'postbackId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID постбэка',
			},
			{
				displayName: 'Название постбэка',
				name: 'postbackName',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
					},
				},
				default: '',
				description: 'Название постбэка',
			},
			{
				displayName: 'URL постбэка',
				name: 'postbackUrl',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
					},
				},
				default: '',
				placeholder: 'https://example.com/postback?clickid={sub_id_1}&status={status}',
				description: 'URL для отправки постбэка. Можно использовать макросы: {sub_id_1}, {status}, {revenue}, и т.д.',
			},
			{
				displayName: 'Статус',
				name: 'postbackStatus',
				type: 'options',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
					},
				},
				options: [
					{
						name: 'Активный',
						value: 'active',
					},
					{
						name: 'Неактивный',
						value: 'inactive',
					},
				],
				default: 'active',
				description: 'Статус постбэка',
			},
			{
				displayName: 'Триггер',
				name: 'postbackTrigger',
				type: 'options',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
					},
				},
				options: [
					{
						name: 'Конверсия',
						value: 'conversion',
						description: 'Срабатывает при любой конверсии',
					},
					{
						name: 'Лид',
						value: 'lead',
						description: 'Срабатывает только при получении лида',
					},
					{
						name: 'Продажа',
						value: 'sale',
						description: 'Срабатывает только при продаже',
					},
				],
				default: 'conversion',
				description: 'Когда отправлять постбэк',
			},
			{
				displayName: 'HTTP метод',
				name: 'postbackMethod',
				type: 'options',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
					},
				},
				options: [
					{
						name: 'GET',
						value: 'GET',
					},
					{
						name: 'POST',
						value: 'POST',
					},
				],
				default: 'GET',
				description: 'HTTP метод для отправки постбэка',
			},
			{
				displayName: 'Статусы лидов',
				name: 'leadStatus',
				type: 'string',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
					},
				},
				default: 'lead,registration,new',
				description: 'Статусы для лидов, перечисленные через запятую. Если партнерская сеть отправит один из этих статусов, Keitaro запишет его как "Лид".',
			},
			{
				displayName: 'Статусы продаж',
				name: 'saleStatus',
				type: 'string',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
					},
				},
				default: 'sale,paid,billed,completed',
				description: 'Статусы для продаж, перечисленные через запятую. Если партнерская сеть отправит один из этих статусов, Keitaro запишет его как "Продажа".',
			},
			{
				displayName: 'Отклоненные статусы',
				name: 'rejectedStatus',
				type: 'string',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
					},
				},
				default: 'rejected,canceled,fake,fraud',
				description: 'Статусы для отклоненных конверсий, перечисленные через запятую. Если партнерская сеть отправит один из этих статусов, Keitaro запишет его как "Отклонено".',
			},
			{
				displayName: 'Дополнительные настройки',
				name: 'postbackAdvanced',
				type: 'boolean',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
					},
				},
				default: false,
				description: 'Показать дополнительные настройки постбэка',
			},
			{
				displayName: 'Ключ постбэка',
				name: 'postbackKey',
				type: 'string',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
						postbackAdvanced: [true],
					},
				},
				default: '',
				description: 'Ключ для аутентификации постбэка. Обеспечивает дополнительную безопасность.',
			},
			{
				displayName: 'Валюта',
				name: 'postbackCurrency',
				type: 'string',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
						postbackAdvanced: [true],
					},
				},
				default: 'USD',
				description: 'Валюта, используемая по умолчанию для конверсий.',
			},
			{
				displayName: 'Таймаут (сек)',
				name: 'postbackTimeout',
				type: 'number',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
						postbackAdvanced: [true],
					},
				},
				default: 30,
				description: 'Таймаут отправки постбэка в секундах.',
			},
			{
				displayName: 'Количество повторных попыток',
				name: 'postbackRetryCount',
				type: 'number',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
						postbackAdvanced: [true],
					},
				},
				default: 3,
				description: 'Сколько раз пытаться повторно отправить постбэк в случае ошибки.',
			},
			{
				displayName: 'Задержка между попытками (сек)',
				name: 'postbackRetryDelay',
				type: 'number',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
						postbackAdvanced: [true],
					},
				},
				default: 60,
				description: 'Задержка между повторными попытками в секундах.',
			},
			{
				displayName: 'Кампании',
				name: 'postbackCampaigns',
				type: 'string',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
						postbackAdvanced: [true],
					},
				},
				default: '',
				description: 'ID кампаний через запятую, для которых будет отправляться постбэк. Оставьте пустым для всех кампаний.',
			},
			{
				displayName: 'Страны',
				name: 'postbackCountries',
				type: 'string',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
						postbackAdvanced: [true],
					},
				},
				default: '',
				description: 'Коды стран через запятую, для которых будет отправляться постбэк. Оставьте пустым для всех стран.',
			},
			{
				displayName: 'ID Источника',
				name: 'sourceId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['source'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID источника',
			},
			{
				displayName: 'Данные Источника',
				name: 'sourceData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['source'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные источника в формате JSON',
			},
			{
				displayName: 'ID Конверсии',
				name: 'conversionId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['conversion'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID конверсии',
			},
			{
				displayName: 'Данные Конверсии',
				name: 'conversionData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['conversion'],
						operation: ['create', 'update'],
					},
				},
				default: '{"click_id":"CLICK_ID_HERE","status":"lead","revenue":0}',
				description: 'Данные конверсии в формате JSON. Обязательно укажите click_id.',
			},
			{
				displayName: 'Упрощенное создание конверсии',
				name: 'conversionSimple',
				type: 'fixedCollection',
				typeOptions: {
					multipleValues: false,
				},
				displayOptions: {
					show: {
						resource: ['conversion'],
						operation: ['create'],
					},
				},
				default: {},
				placeholder: 'Добавить параметры конверсии',
				options: [
					{
						name: 'values',
						displayName: 'Параметры конверсии',
						values: [
							{
								displayName: 'ID клика (click_id)',
								name: 'click_id',
								type: 'string',
								required: true,
								default: '',
								description: 'ID клика, для которого регистрируется конверсия',
							},
							{
								displayName: 'Статус',
								name: 'status',
								type: 'options',
								options: [
									{
										name: 'Лид',
										value: 'lead',
									},
									{
										name: 'Продажа',
										value: 'sale',
									},
									{
										name: 'Отклонено',
										value: 'rejected',
									},
									{
										name: 'Регистрация',
										value: 'reg',
									},
									{
										name: 'Депозит',
										value: 'dep',
									},
								],
								default: 'lead',
								description: 'Статус конверсии',
							},
							{
								displayName: 'Сумма дохода',
								name: 'revenue',
								type: 'number',
								default: 0,
								description: 'Сумма дохода от конверсии',
							},
							{
								displayName: 'Валюта',
								name: 'currency',
								type: 'string',
								default: 'USD',
								description: 'Валюта дохода',
							},
							{
								displayName: 'ID транзакции',
								name: 'transaction_id',
								type: 'string',
								default: '',
								description: 'ID транзакции (для повторных продаж/upsell)',
							},
							{
								displayName: 'Комментарий',
								name: 'comment',
								type: 'string',
								default: '',
								description: 'Комментарий к конверсии',
							},
						],
					},
				],
				description: 'Упрощенный способ создания конверсии',
			},
			{
				displayName: 'ID Домена',
				name: 'domainId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['domain'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID домена',
			},
			{
				displayName: 'Данные Домена',
				name: 'domainData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['domain'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные домена в формате JSON',
			},
			{
				displayName: 'ID Клика',
				name: 'clickId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['click'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID клика',
			},
			{
				displayName: 'Данные Клика',
				name: 'clickData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['click'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные клика в формате JSON',
			},
			{
				displayName: 'ID Фильтра',
				name: 'filterId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['filter'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID фильтра',
			},
			{
				displayName: 'Данные Фильтра',
				name: 'filterData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['filter'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные фильтра в формате JSON',
			},
			{
				displayName: 'ID Настроек',
				name: 'settingsId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['settings'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID настроек',
			},
			{
				displayName: 'Данные Настроек',
				name: 'settingsData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['settings'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные настроек в формате JSON',
			},
			{
				displayName: 'ID Лога',
				name: 'logId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['log'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID лога',
			},
			{
				displayName: 'Данные Лога',
				name: 'logData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['log'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные лога в формате JSON',
			},
			{
				displayName: 'ID Статистики',
				name: 'statsId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['stats'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID статистики',
			},
			{
				displayName: 'Данные Статистики',
				name: 'statsData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['stats'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные статистики в формате JSON',
			},
			{
				displayName: 'ID Группы',
				name: 'groupId',
				type: 'string',
				required: true,
				displayOptions: {
					show: {
						resource: ['group'],
						operation: ['get', 'update', 'delete'],
					},
				},
				default: '',
				description: 'ID группы',
			},
			{
				displayName: 'Данные Группы',
				name: 'groupData',
				type: 'json',
				required: true,
				displayOptions: {
					show: {
						resource: ['group'],
						operation: ['create', 'update'],
					},
				},
				default: '{}',
				description: 'Данные группы в формате JSON',
			},
			// Параметры для получения кликов
			{
				displayName: 'Параметры Фильтрации Кликов',
				name: 'clickParameters',
				type: 'fixedCollection',
				placeholder: 'Добавить параметр',
				default: {},
				displayOptions: {
					show: {
						resource: [
							'click',
						],
						operation: [
							'getAll',
						],
					},
				},
				typeOptions: {
					multipleValues: false,
				},
				description: 'Параметры для получения кликов',
				options: [
					{
						name: 'range',
						displayName: 'Диапазон дат',
						values: [
							{
								displayName: 'Начальная дата',
								name: 'from',
								type: 'string',
								default: '',
								description: 'Начальная дата в формате YYYY-MM-DD',
							},
							{
								displayName: 'Конечная Дата',
								name: 'to',
								type: 'string',
								default: '',
								description: 'Конечная дата в формате YYYY-MM-DD',
							},
							{
								displayName: 'Часовой пояс',
								name: 'timezone',
								type: 'string',
								default: '',
								description: 'Часовой пояс, например Europe/Moscow',
							},
						]
					},
					{
						name: 'interval',
						displayName: 'Интервал',
						values: [
							{
								displayName: 'Интервал',
								name: 'interval',
								type: 'options',
								options: [
									{
										name: 'Сегодня',
										value: 'today',
									},
									{
										name: 'Вчера',
										value: 'yesterday',
									},
									{
										name: '7 дней назад',
										value: '7_days_ago',
									},
									{
										name: 'Первый день этой недели',
										value: 'first_day_of_this_week',
									},
									{
										name: '1 месяц назад',
										value: '1_month_ago',
									},
									{
										name: 'Первый день этого месяца',
										value: 'first_day_of_this_month',
									},
									{
										name: '1 год назад',
										value: '1_year_ago',
									},
									{
										name: 'Первый день этого года',
										value: 'first_day_of_this_year',
									},
									{
										name: 'За все время',
										value: 'all_time',
									},
								],
								default: '',
								description: 'Предустановленный интервал времени',
							},
						],
					},
					{
						name: 'mainFilters',
						displayName: 'Основные фильтры',
						values: [
							{
								displayName: 'ID Кампании',
								name: 'campaign_id',
								type: 'string',
								default: '',
								description: 'Фильтрация по ID кампании',
							},
							{
								displayName: 'ID Потока',
								name: 'stream_id',
								type: 'string',
								default: '',
								description: 'Фильтрация по ID потока',
							},
							{
								displayName: 'ID Лендинга',
								name: 'landing_id',
								type: 'string',
								default: '',
								description: 'Фильтрация по ID лендинга',
							},
							{
								displayName: 'ID Оффера',
								name: 'offer_id',
								type: 'string',
								default: '',
								description: 'Фильтрация по ID оффера',
							},
						]
					},
					{
						name: 'additionalFilters',
						displayName: 'Дополнительные фильтры',
						values: [
							{
								displayName: 'Страна',
								name: 'country',
								type: 'string',
								default: '',
								description: 'Фильтрация по коду страны (2 буквы, например RU)',
							},
							{
								displayName: 'IP',
								name: 'ip',
								type: 'string',
								default: '',
								description: 'Фильтрация по IP-адресу',
							},
							{
								displayName: 'Бот',
								name: 'is_bot',
								type: 'boolean',
								default: false,
								description: 'Фильтрация по ботам',
							},
							{
								displayName: 'Уникальный клик',
								name: 'is_unique',
								type: 'boolean',
								default: false,
								description: 'Фильтрация по уникальным кликам',
							},
							{
								displayName: 'Конверсия',
								name: 'is_conversion',
								type: 'boolean',
								default: false,
								description: 'Фильтрация по кликам с конверсиями',
							},
							{
								displayName: 'Sub ID 1',
								name: 'sub_id_1',
								type: 'string',
								default: '',
								description: 'Фильтрация по Sub ID 1',
							},
							{
								displayName: 'Sub ID 2',
								name: 'sub_id_2',
								type: 'string',
								default: '',
								description: 'Фильтрация по Sub ID 2',
							},
							{
								displayName: 'Sub ID 3',
								name: 'sub_id_3',
								type: 'string',
								default: '',
								description: 'Фильтрация по Sub ID 3',
							},
							{
								displayName: 'Sub ID 4',
								name: 'sub_id_4',
								type: 'string',
								default: '',
								description: 'Фильтрация по Sub ID 4',
							},
							{
								displayName: 'Sub ID 5',
								name: 'sub_id_5',
								type: 'string',
								default: '',
								description: 'Фильтрация по Sub ID 5',
							},
						]
					},
					{
						name: 'pagination',
						displayName: 'Пагинация и сортировка',
						values: [
							{
								displayName: 'Лимит',
								name: 'limit',
								type: 'number',
								default: 100,
								description: 'Максимальное количество кликов для возврата (обязательно, если не указан диапазон дат)',
							},
							{
								displayName: 'Смещение',
								name: 'offset',
								type: 'number',
								default: 0,
								description: 'Смещение для пагинации',
							},
							{
								displayName: 'Сортировка',
								name: 'sort',
								type: 'options',
								options: [
									{
										name: 'По ID (возрастание)',
										value: 'id',
									},
									{
										name: 'По ID (убывание)',
										value: '-id',
									},
									{
										name: 'По времени (возрастание)',
										value: 'created_at',
									},
									{
										name: 'По времени (убывание)',
										value: '-created_at',
									},
								],
								default: '-created_at',
								description: 'Поле и направление сортировки',
							},
						]
					}
				],
			},
			// Параметры для получения статистики
			{
				displayName: 'Параметры для Статистики',
				name: 'statsParameters',
				type: 'fixedCollection',
				placeholder: 'Добавить параметр',
				default: {},
				displayOptions: {
					show: {
						resource: [
							'stats',
						],
						operation: [
							'getAll',
						],
					},
				},
				typeOptions: {
					multipleValues: false,
				},
				options: [
					{
						name: 'dateRange',
						displayName: 'Диапазон дат',
						values: [
							{
								displayName: 'Начальная Дата',
								name: 'range_from',
								type: 'string',
								default: '',
								description: 'Начальная дата в формате YYYY-MM-DD',
								required: false,
							},
							{
								displayName: 'Конечная Дата',
								name: 'range_to',
								type: 'string',
								default: '',
								description: 'Конечная дата в формате YYYY-MM-DD',
								required: false,
							},
						],
					},
					{
						name: 'filterOptions',
						displayName: 'Фильтры и группировка',
						values: [
							{
								displayName: 'Группировка',
								name: 'group',
								type: 'multiOptions',
								options: [
									{
										name: 'По дням',
										value: 'day',
									},
									{
										name: 'По часам',
										value: 'hour',
									},
									{
										name: 'По ID кампании',
										value: 'campaign_id',
									},
									{
										name: 'По ID потока',
										value: 'stream_id',
									},
									{
										name: 'По стране',
										value: 'country',
									},
									{
										name: 'По устройству',
										value: 'device_type',
									},
									{
										name: 'По браузеру',
										value: 'browser_name',
									},
									{
										name: 'По ОС',
										value: 'os_name',
									},
									{
										name: 'По ключевому слову',
										value: 'keyword',
									},
									{
										name: 'По Sub ID 1',
										value: 'sub_id_1',
									},
									{
										name: 'По Sub ID 2',
										value: 'sub_id_2',
									},
									{
										name: 'По Sub ID 3',
										value: 'sub_id_3',
									},
									{
										name: 'По Sub ID 4',
										value: 'sub_id_4',
									},
									{
										name: 'По Sub ID 5',
										value: 'sub_id_5',
									},
								],
								default: ['day'],
								description: 'Группировка данных статистики',
							},
							{
								displayName: 'Фильтр по ID кампании',
								name: 'campaign',
								type: 'string',
								default: '',
								description: 'ID кампании для фильтрации',
							},
							{
								displayName: 'Фильтр по ID потока',
								name: 'stream',
								type: 'string',
								default: '',
								description: 'ID потока для фильтрации',
							},
							{
								displayName: 'Фильтр по стране',
								name: 'country',
								type: 'string',
								default: '',
								description: 'Код страны для фильтрации (2 буквы, например RU)',
							},
							{
								displayName: 'Фильтр по типу устройства',
								name: 'device_type',
								type: 'options',
								options: [
									{
										name: 'Мобильные',
										value: 'mobile',
									},
									{
										name: 'Десктоп',
										value: 'desktop',
									},
									{
										name: 'Планшеты',
										value: 'tablet',
									},
								],
								default: '',
								description: 'Тип устройства для фильтрации',
							},
						],
					},
					{
						name: 'additionalFilters',
						displayName: 'Дополнительные фильтры',
						values: [
							{
								displayName: 'Фильтр по Sub ID 1',
								name: 'sub_id_1',
								type: 'string',
								default: '',
								description: 'Фильтрация по Sub ID 1',
							},
							{
								displayName: 'Фильтр по Sub ID 2',
								name: 'sub_id_2',
								type: 'string',
								default: '',
								description: 'Фильтрация по Sub ID 2',
							},
							{
								displayName: 'Фильтр по Sub ID 3',
								name: 'sub_id_3',
								type: 'string',
								default: '',
								description: 'Фильтрация по Sub ID 3',
							},
							{
								displayName: 'Фильтр по Sub ID 4',
								name: 'sub_id_4',
								type: 'string',
								default: '',
								description: 'Фильтрация по Sub ID 4',
							},
							{
								displayName: 'Фильтр по Sub ID 5',
								name: 'sub_id_5',
								type: 'string',
								default: '',
								description: 'Фильтрация по Sub ID 5',
							},
						],
					},
					{
						name: 'metrics',
						displayName: 'Метрики',
						values: [
							{
								displayName: 'Включать ROI',
								name: 'roi',
								type: 'boolean',
								default: true,
								description: 'Включать ROI в результаты',
							},
							{
								displayName: 'Включать CR',
								name: 'cr',
								type: 'boolean',
								default: true,
								description: 'Включать коэффициент конверсии (CR) в результаты',
							},
							{
								displayName: 'Включать EPC',
								name: 'epc',
								type: 'boolean',
								default: true,
								description: 'Включать доход на клик (EPC) в результаты',
							},
							{
								displayName: 'Включать CPC',
								name: 'cpc',
								type: 'boolean',
								default: true,
								description: 'Включать стоимость клика (CPC) в результаты',
							},
						],
					},
					{
						name: 'interval',
						displayName: 'Интервал',
						values: [
							{
								displayName: 'Интервал',
								name: 'interval',
								type: 'options',
								options: [
									{
										name: 'Сегодня',
										value: 'today',
									},
									{
										name: 'Вчера',
										value: 'yesterday',
									},
									{
										name: '7 дней назад',
										value: '7_days_ago',
									},
									{
										name: 'Первый день этой недели',
										value: 'first_day_of_this_week',
									},
									{
										name: '1 месяц назад',
										value: '1_month_ago',
									},
									{
										name: 'Первый день этого месяца',
										value: 'first_day_of_this_month',
									},
									{
										name: '1 год назад',
										value: '1_year_ago',
									},
									{
										name: 'Первый день этого года',
										value: 'first_day_of_this_year',
									},
									{
										name: 'За все время',
										value: 'all_time',
									},
								],
								default: '',
								description: 'Предустановленный интервал времени',
							},
						],
					},
				],
			},
			{
				displayName: 'Тестирование постбэка',
				name: 'testPostbackData',
				type: 'fixedCollection',
				typeOptions: {
					multipleValues: false,
				},
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['test'],
					},
				},
				default: {},
				placeholder: 'Добавить тестовые данные',
				options: [
					{
						name: 'testData',
						displayName: 'Тестовые данные',
						values: [
							{
								displayName: 'ID клика (SubID)',
								name: 'click_id',
								type: 'string',
								required: true,
								default: '',
								description: 'ID клика для тестирования постбэка',
							},
							{
								displayName: 'Статус',
								name: 'status',
								type: 'options',
								options: [
									{
										name: 'Лид',
										value: 'lead',
									},
									{
										name: 'Продажа',
										value: 'sale',
									},
									{
										name: 'Отклонено',
										value: 'rejected',
									},
									{
										name: 'Регистрация',
										value: 'reg',
									},
									{
										name: 'Депозит',
										value: 'dep',
									},
								],
								default: 'lead',
								description: 'Статус конверсии',
							},
							{
								displayName: 'Сумма выплаты',
								name: 'payout',
								type: 'number',
								default: 10,
								description: 'Сумма выплаты за конверсию',
							},
							{
								displayName: 'Стоимость',
								name: 'cost',
								type: 'number',
								default: 0,
								description: 'Стоимость за конверсию (для CPA и RevShare)',
							},
							{
								displayName: 'Валюта',
								name: 'currency',
								type: 'string',
								default: 'USD',
								description: 'Валюта выплаты',
							},
							{
								displayName: 'ID транзакции',
								name: 'transaction_id',
								type: 'string',
								default: '',
								description: 'ID транзакции (для повторных продаж/upsell)',
							},
							{
								displayName: 'Sub ID 1',
								name: 'sub_id_1',
								type: 'string',
								default: '',
								description: 'Значение Sub ID 1 для обновления параметров клика',
							},
						],
					},
				],
				description: 'Данные для тестирования постбэка',
			},
			{
				displayName: 'Настройка HTTP заголовков',
				name: 'postbackConfigureHeaders',
				type: 'boolean',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
						postbackAdvanced: [true],
					},
				},
				default: false,
				description: 'Настройка HTTP заголовков для отправки постбека',
			},
			{
				displayName: 'HTTP заголовки',
				name: 'postbackHeaders',
				type: 'fixedCollection',
				typeOptions: {
					multipleValues: true,
				},
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
						postbackAdvanced: [true],
						postbackConfigureHeaders: [true],
					},
				},
				default: {},
				placeholder: 'Добавить HTTP заголовок',
				options: [
					{
						name: 'header',
						displayName: 'Заголовок',
						values: [
							{
								displayName: 'Имя',
								name: 'name',
								type: 'string',
								default: '',
								description: 'Имя HTTP заголовка',
								placeholder: 'Content-Type',
							},
							{
								displayName: 'Значение',
								name: 'value',
								type: 'string',
								default: '',
								description: 'Значение HTTP заголовка',
								placeholder: 'application/json',
							},
						],
					},
				],
				description: 'HTTP заголовки для отправки с постбеком',
			},

			{
				displayName: 'Параметры постбека',
				name: 'postbackParameters',
				type: 'fixedCollection',
				typeOptions: {
					multipleValues: true,
				},
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
						postbackAdvanced: [true],
					},
				},
				default: {},
				placeholder: 'Добавить параметр',
				options: [
					{
						name: 'parameter',
						displayName: 'Параметр',
						values: [
							{
								displayName: 'Имя',
								name: 'name',
								type: 'string',
								default: '',
								description: 'Имя параметра',
								placeholder: 'subid, status, payout и т.д.',
							},
							{
								displayName: 'Значение',
								name: 'value',
								type: 'string',
								default: '',
								description: 'Значение параметра или макрос {sub_id_1}, {status}, и т.д.',
								placeholder: '{sub_id_1}',
							},
						],
					},
				],
				description: 'Дополнительные параметры для постбека',
			},

			{
				displayName: 'Статусы для отслеживания регистраций',
				name: 'regStatus',
				type: 'string',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
						postbackAdvanced: [true],
					},
				},
				default: 'reg,registration',
				description: 'Статусы для регистраций, перечисленные через запятую. Для Keitaro 10.3+.',
			},

			{
				displayName: 'Статусы для отслеживания депозитов',
				name: 'depStatus',
				type: 'string',
				displayOptions: {
					show: {
						resource: ['postback'],
						operation: ['create', 'update'],
						postbackAdvanced: [true],
					},
				},
				default: 'dep,deposit',
				description: 'Статусы для депозитов, перечисленные через запятую. Для Keitaro 10.3+.',
			},
			{
				displayName: 'Параметры Фильтрации Конверсий',
				name: 'conversionParameters',
				type: 'fixedCollection',
				placeholder: 'Добавить параметр',
				default: {},
				displayOptions: {
					show: {
						resource: [
							'conversion',
						],
						operation: [
							'getAll',
						],
					},
				},
				typeOptions: {
					multipleValues: false,
				},
				description: 'Параметры для получения конверсий',
				options: [
					{
						name: 'range',
						displayName: 'Диапазон дат',
						values: [
							{
								displayName: 'Начальная дата',
								name: 'from',
								type: 'string',
								default: '',
								description: 'Начальная дата в формате YYYY-MM-DD',
							},
							{
								displayName: 'Конечная Дата',
								name: 'to',
								type: 'string',
								default: '',
								description: 'Конечная дата в формате YYYY-MM-DD',
							},
							{
								displayName: 'Часовой пояс',
								name: 'timezone',
								type: 'string',
								default: '',
								description: 'Часовой пояс, например Europe/Moscow',
							},
						]
					},
					{
						name: 'interval',
						displayName: 'Интервал',
						values: [
							{
								displayName: 'Интервал',
								name: 'interval',
								type: 'options',
								options: [
									{
										name: 'Сегодня',
										value: 'today',
									},
									{
										name: 'Вчера',
										value: 'yesterday',
									},
									{
										name: '7 дней назад',
										value: '7_days_ago',
									},
									{
										name: 'Первый день этой недели',
										value: 'first_day_of_this_week',
									},
									{
										name: '1 месяц назад',
										value: '1_month_ago',
									},
									{
										name: 'Первый день этого месяца',
										value: 'first_day_of_this_month',
									},
									{
										name: '1 год назад',
										value: '1_year_ago',
									},
									{
										name: 'Первый день этого года',
										value: 'first_day_of_this_year',
									},
									{
										name: 'За все время',
										value: 'all_time',
									},
								],
								default: '',
								description: 'Предустановленный интервал времени',
							},
						],
					},
					{
						name: 'additionalFilters',
						displayName: 'Дополнительные фильтры',
						values: [
							{
								displayName: 'Статус',
								name: 'status',
								type: 'options',
								options: [
									{
										name: 'Лид',
										value: 'lead',
									},
									{
										name: 'Продажа',
										value: 'sale',
									},
									{
										name: 'Отклонено',
										value: 'rejected',
									},
									{
										name: 'Регистрация',
										value: 'reg',
									},
									{
										name: 'Депозит',
										value: 'dep',
									},
								],
								default: '',
								description: 'Фильтрация по статусу конверсии',
							},
							{
								displayName: 'ID Клика',
								name: 'click_id',
								type: 'string',
								default: '',
								description: 'Фильтрация по ID клика',
							},
							{
								displayName: 'ID Транзакции',
								name: 'transaction_id',
								type: 'string',
								default: '',
								description: 'Фильтрация по ID транзакции',
							},
							{
								displayName: 'Страна',
								name: 'country',
								type: 'string',
								default: '',
								description: 'Фильтрация по коду страны (2 буквы, например RU)',
							},
						]
					},
					{
						name: 'pagination',
						displayName: 'Пагинация и сортировка',
						values: [
							{
								displayName: 'Лимит',
								name: 'limit',
								type: 'number',
								default: 100,
								description: 'Максимальное количество конверсий для возврата (обязательно, если не указан диапазон дат)',
							},
							{
								displayName: 'Смещение',
								name: 'offset',
								type: 'number',
								default: 0,
								description: 'Смещение для пагинации',
							},
							{
								displayName: 'Сортировка',
								name: 'sort',
								type: 'options',
								options: [
									{
										name: 'По ID (возрастание)',
										value: 'id',
									},
									{
										name: 'По ID (убывание)',
										value: '-id',
									},
									{
										name: 'По времени (возрастание)',
										value: 'created_at',
									},
									{
										name: 'По времени (убывание)',
										value: '-created_at',
									},
								],
								default: '-created_at',
								description: 'Поле и направление сортировки',
							},
						]
					}
				],
			},
		],
	};

	async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
		const items = this.getInputData();
		const returnData: INodeExecutionData[] = [];
		const resource = this.getNodeParameter('resource', 0) as string;
		const operation = this.getNodeParameter('operation', 0) as string;

		console.log(`🚀 Выполняется запрос к Keitaro API для ресурса "${resource}" с операцией "${operation}"`);

		// Проверка валидности операций для ресурса stats
		if (resource === 'stats' && operation !== 'getAll') {
			throw new Error(`Для ресурса "stats" поддерживается только операция "getAll". Выбрана операция "${operation}".`);
		}

		// Карта соответствия ресурсов и их путей в API
		const resourceMap: { [key: string]: string } = {
			campaign: 'campaigns',
			stream: 'streams',
			landing: 'landings',
			offer: 'offers',
			traffic: 'traffic',
			user: 'users',
			blacklist: 'blacklist',
			bot: 'bots',
			postback: 'postbacks',
			source: 'sources',
			conversion: 'conversions',
			domain: 'domains',
			click: 'clicks',
			filter: 'filters',
			settings: 'settings',
			log: 'logs',
			stats: 'stats',
			group: 'groups',
		};

		for (let i = 0; i < items.length; i++) {
			try {
				// Получаем ID ресурса, если он есть
				let resourceId = '';
				
				// Проверка наличия ID для операций, требующих его
				if (operation === 'get' || operation === 'update' || operation === 'delete') {
					// Для статистики ID не нужен
					if (resource !== 'stats') {
						try {
							resourceId = this.getNodeParameter(`${resource}Id`, i) as string;
							if (!resourceId && resource !== 'stats') {
								throw new Error(`ID для ресурса "${resource}" необходим для операции "${operation}".`);
							}
						} catch (error) {
							console.error(error);
							throw new Error(`Не удалось получить ID для ресурса "${resource}". Убедитесь, что ID указан для операции "${operation}".`);
						}
					}
				}
				
				// Получаем данные для создания или обновления
				let resourceData = {};
				if (operation === 'create' || operation === 'update') {
					try {
						if (resource === 'postback') {
							// Обработка новой структуры данных постбэка
							// Инициализируем объект для данных постбэка
							const formattedPostbackData: IDataObject = {};
							
							// Получаем данные из учетных записей
							const credentials = await this.getCredentials('keitaroApi') as IDataObject;
							const useCredentialsSettings = credentials.postbackSettings as boolean;
							
							// Получаем базовые поля
							formattedPostbackData.name = this.getNodeParameter('postbackName', i) as string;
							formattedPostbackData.url = this.getNodeParameter('postbackUrl', i) as string;
							formattedPostbackData.status = this.getNodeParameter('postbackStatus', i) as string;
							formattedPostbackData.trigger = this.getNodeParameter('postbackTrigger', i) as string;
							formattedPostbackData.method = this.getNodeParameter('postbackMethod', i) as string;
							
							// Установка параметров из настроек учетной записи, если они не переопределены
							if (useCredentialsSettings && credentials.postbackKey) {
								formattedPostbackData.postback_key = credentials.postbackKey as string;
							}
							
							// Обрабатываем статусы - сначала проверяем, есть ли они в настройках учетной записи
							if (useCredentialsSettings && credentials.statusTransformation) {
								// Используем статусы из глобальных настроек, если не переопределены в ноде
								const leadStatus = this.getNodeParameter('leadStatus', i, credentials.leadStatuses || '') as string;
								if (leadStatus) {
									formattedPostbackData.lead_status = leadStatus
										.split(',')
										.map(status => status.trim())
										.filter(status => status.length > 0);
								}
								
								const saleStatus = this.getNodeParameter('saleStatus', i, credentials.saleStatuses || '') as string;
								if (saleStatus) {
									formattedPostbackData.sale_status = saleStatus
										.split(',')
										.map(status => status.trim())
										.filter(status => status.length > 0);
								}
								
								const rejectedStatus = this.getNodeParameter('rejectedStatus', i, credentials.rejectedStatuses || '') as string;
								if (rejectedStatus) {
									formattedPostbackData.rejected_status = rejectedStatus
										.split(',')
										.map(status => status.trim())
										.filter(status => status.length > 0);
								}
							} else {
								// Используем локальные настройки
								const leadStatus = this.getNodeParameter('leadStatus', i, '') as string;
								if (leadStatus) {
									formattedPostbackData.lead_status = leadStatus
										.split(',')
										.map(status => status.trim())
										.filter(status => status.length > 0);
								}
								
								const saleStatus = this.getNodeParameter('saleStatus', i, '') as string;
								if (saleStatus) {
									formattedPostbackData.sale_status = saleStatus
										.split(',')
										.map(status => status.trim())
										.filter(status => status.length > 0);
								}
								
								const rejectedStatus = this.getNodeParameter('rejectedStatus', i, '') as string;
								if (rejectedStatus) {
									formattedPostbackData.rejected_status = rejectedStatus
										.split(',')
										.map(status => status.trim())
										.filter(status => status.length > 0);
								}
							}
							
							// Проверяем, включены ли дополнительные настройки
							const useAdvanced = this.getNodeParameter('postbackAdvanced', i, false) as boolean;
							
							if (useAdvanced) {
								// Добавляем дополнительные настройки
								const postbackKey = this.getNodeParameter('postbackKey', i, useCredentialsSettings ? credentials.postbackKey || '' : '') as string;
								if (postbackKey) {
									formattedPostbackData.postback_key = postbackKey;
								}
								
								const currency = this.getNodeParameter('postbackCurrency', i, useCredentialsSettings ? credentials.defaultCurrency || 'USD' : 'USD') as string;
								if (currency) {
									formattedPostbackData.currency = currency;
								}
								
								const timeout = this.getNodeParameter('postbackTimeout', i, 30) as number;
								formattedPostbackData.timeout = timeout;
								
								const retryCount = this.getNodeParameter('postbackRetryCount', i, 3) as number;
								formattedPostbackData.retry_count = retryCount;
								
								const retryDelay = this.getNodeParameter('postbackRetryDelay', i, 60) as number;
								formattedPostbackData.retry_delay = retryDelay;
								
								// Обрабатываем кампании
								const campaigns = this.getNodeParameter('postbackCampaigns', i, '') as string;
								if (campaigns && campaigns.trim().length > 0) {
									formattedPostbackData.campaigns = campaigns
										.split(',')
										.map(id => parseInt(id.trim(), 10))
										.filter(id => !isNaN(id));
								}
								
								// Обрабатываем страны
								const countries = this.getNodeParameter('postbackCountries', i, '') as string;
								if (countries && countries.trim().length > 0) {
									formattedPostbackData.countries = countries
										.split(',')
										.map(country => country.trim())
										.filter(country => country.length > 0);
								}
								
								// Обработка статусов для регистраций и депозитов (Keitaro 10.3+)
								// Используем значения из настроек учетной записи, если доступны
								const regStatus = this.getNodeParameter('regStatus', i, 
									useCredentialsSettings && credentials.statusTransformation 
										? credentials.regStatuses || '' 
										: '') as string;
								if (regStatus) {
									formattedPostbackData.reg_status = regStatus
										.split(',')
										.map(status => status.trim())
										.filter(status => status.length > 0);
								}
								
								const depStatus = this.getNodeParameter('depStatus', i, 
									useCredentialsSettings && credentials.statusTransformation 
										? credentials.depStatuses || '' 
										: '') as string;
								if (depStatus) {
									formattedPostbackData.dep_status = depStatus
										.split(',')
										.map(status => status.trim())
										.filter(status => status.length > 0);
								}
								
								// Обработка HTTP заголовков
								const configureHeaders = this.getNodeParameter('postbackConfigureHeaders', i, false) as boolean;
								if (configureHeaders) {
									const headersCollection = this.getNodeParameter('postbackHeaders', i, { header: [] }) as IDataObject;
									if (headersCollection.header && Array.isArray(headersCollection.header) && headersCollection.header.length > 0) {
										const headers: Record<string, string> = {};
										for (const header of headersCollection.header as IDataObject[]) {
											const name = header.name as string;
											const value = header.value as string;
											if (name && value) {
												headers[name] = value;
											}
										}
										if (Object.keys(headers).length > 0) {
											formattedPostbackData.headers = headers;
										}
									}
								}
								
								// Обработка параметров постбека
								const parametersCollection = this.getNodeParameter('postbackParameters', i, { parameter: [] }) as IDataObject;
								if (parametersCollection.parameter && Array.isArray(parametersCollection.parameter) && parametersCollection.parameter.length > 0) {
									const parameters: Record<string, unknown> = {};
									for (const param of parametersCollection.parameter as IDataObject[]) {
										const name = param.name as string;
										const value = param.value as string;
										if (name && value) {
											parameters[name] = value;
										}
									}
									if (Object.keys(parameters).length > 0) {
										formattedPostbackData.parameters = parameters;
									}
								}
							}
							
							// Присваиваем отформатированные данные
							resourceData = formattedPostbackData;
							
							console.log(`Отформатированные данные постбэка:`, safeStringify(resourceData));
						} else if (resource === 'conversion' && operation === 'create') {
							// Проверяем, использует ли пользователь упрощенную форму для конверсий
							const useSimpleForm = this.getNodeParameter('conversionSimple', i, { values: null }) as IDataObject;
							
							if (useSimpleForm && useSimpleForm.values) {
								const conversionValues = useSimpleForm.values as IDataObject;
								const formattedConversionData: IDataObject = {};
								
								// Проверяем и добавляем обязательное поле click_id
								if (conversionValues.click_id) {
									formattedConversionData.click_id = conversionValues.click_id;
								} else {
									throw new Error('ID клика (click_id) обязателен для создания конверсии');
								}
								
								// Добавляем остальные поля, если они указаны
								if (conversionValues.status) formattedConversionData.status = conversionValues.status;
								if (conversionValues.revenue !== undefined) formattedConversionData.revenue = conversionValues.revenue;
								if (conversionValues.currency) formattedConversionData.currency = conversionValues.currency;
								if (conversionValues.transaction_id) formattedConversionData.transaction_id = conversionValues.transaction_id;
								if (conversionValues.comment) formattedConversionData.comment = conversionValues.comment;
								
								// Присваиваем отформатированные данные
								resourceData = formattedConversionData;
								
								console.log(`Отформатированные данные конверсии (упрощенная форма):`, safeStringify(resourceData));
							} else {
								// Используем данные из JSON-поля
								resourceData = this.getNodeParameter(`${resource}Data`, i) as object;
								console.log(`Данные конверсии из JSON:`, safeStringify(resourceData));
							}
						} else {
							resourceData = this.getNodeParameter(`${resource}Data`, i) as object;
						}
						
						if (!resourceData || Object.keys(resourceData).length === 0) {
							throw new Error(`Данные для ресурса "${resource}" необходимы для операции "${operation}".`);
						}
					} catch (error) {
						console.error(error);
						throw new Error(`Не удалось получить данные для ресурса "${resource}". Убедитесь, что данные указаны для операции "${operation}".`);
					}
				}

				// Получаем домен и API ключ из credentials
				let credentials;
				try {
					credentials = await this.getCredentials('keitaroApi');
				} catch {
					throw new Error('Не удалось получить учетные данные API Keitaro. Проверьте настройки учетных данных.');
				}
				
				const domain = credentials?.domain as string;
				const apiKey = credentials?.apiKey as string;
				
				if (!domain) {
					throw new Error('Domain (домен) обязателен в учетных данных');
				}
				if (!apiKey) {
					throw new Error('API Key (ключ API) обязателен в учетных данных');
				}
				
				// Форматируем базовый URL
				const baseUrl = formatBaseUrl(domain);
				
				// Формируем путь для запроса
				const requestPath = getApiPath(resourceMap, resource, resourceId, operation);
				const fullUrl = `${baseUrl}${requestPath}`;

				// Общие заголовки для всех запросов
				const headers = {
					'Accept': 'application/json',
					'Content-Type': 'application/json',
					'Api-Key': apiKey,
					'User-Agent': 'n8n-keitaro-node',
				};

				console.log(`Отправка запроса на: ${fullUrl}`);
				console.log(`Метод: ${operation === 'getAll' ? 'GET' : operation.toUpperCase()}`);

				try {
					let response;
					
					// Выполняем запрос в зависимости от операции
					switch (operation) {
						case 'get':
							response = await this.helpers.request({
								method: 'GET',
								url: fullUrl,
								headers,
								json: true,
								resolveWithFullResponse: true,
							});
							break;
							
						case 'getAll':
							// Для запроса к /clicks/log нужен POST с параметрами, а не GET
							if (resource === 'click') {
								console.log('🚀 Начинаем формирование запроса к /clicks/log');
								
								// Получаем параметры фильтрации, если они указаны
								const clickParametersCollection = this.getNodeParameter('clickParameters', i, {}) as IDataObject;
								console.log('Получены параметры из интерфейса:', safeStringify(clickParametersCollection));
								
								// Инициализация объекта для параметров запроса
								const clickParameters: IDataObject = {};
								
								// Извлекаем параметры диапазона дат
								if (clickParametersCollection.range && (clickParametersCollection.range as IDataObject)?.values) {
									const range = (clickParametersCollection.range as IDataObject)?.values as IDataObject;
									if (range.from) clickParameters.from = range.from;
									if (range.to) clickParameters.to = range.to;
									if (range.timezone) clickParameters.timezone = range.timezone;
									console.log('Установлены параметры диапазона:', safeStringify(clickParameters));
								}
								
								// Извлекаем интервал
								if (clickParametersCollection.interval && (clickParametersCollection.interval as IDataObject)?.values) {
									const interval = (clickParametersCollection.interval as IDataObject)?.values as IDataObject;
									console.log('Получены параметры интервала:', safeStringify(interval));
									if (interval.interval) {
										clickParameters.interval = interval.interval;
										console.log('Установлен интервал:', interval.interval);
									}
								}
								
								// Проверяем наличие обязательных параметров
								console.log('Проверка обязательных параметров:');
								console.log('- Есть ли интервал:', !!clickParameters.interval);
								console.log('- Есть ли диапазон дат:', !!(clickParameters.from && clickParameters.to));
								console.log('- Есть ли лимит:', !!clickParameters.limit);
								
								// Если нет ни одного обязательного параметра, добавляем лимит по умолчанию
								if (!clickParameters.interval && !(clickParameters.from && clickParameters.to) && !clickParameters.limit) {
									console.log('Не указаны обязательные параметры, добавляем лимит=100 по умолчанию');
									clickParameters.limit = 100;
								}
								
								console.log('Итоговые параметры запроса:', safeStringify(clickParameters));
								
								// Проверяем, что у нас есть хотя бы один обязательный параметр
								if (!clickParameters.interval && !(clickParameters.from && clickParameters.to) && !clickParameters.limit) {
									throw new Error('Необходимо указать хотя бы один из параметров: интервал, диапазон дат или лимит');
								}
								
								console.log('Отправляем запрос к /clicks/log с параметрами:', safeStringify(clickParameters));
								
								response = await this.helpers.request({
									method: 'POST',
									url: fullUrl,
									body: clickParameters,
									headers,
									json: true,
									resolveWithFullResponse: true,
								});
							} else if (resource === 'stats') {
								// Для статистики используем POST с параметрами
								const statsParametersCollection = this.getNodeParameter('statsParameters', i, {}) as IDataObject;
								
								console.log('🚀 Формируем запрос статистики');
								
								// Инициализация объекта для параметров запроса
								const statsParameters: IDataObject = {
									// Базовые метрики, которые всегда нужны
									metrics: [
										'clicks',
										'campaign_unique_clicks',
										'stream_unique_clicks',
										'global_unique_clicks',
										'leads',
										'sales',
										'rejected',
										'cost',
										'revenue',
										'profit',
										'cr',
										'roi',
										'epc',
										'cpc',
										'cpl',
										'cps'
									]
								};
								
								console.log('Полученные параметры из интерфейса:', safeStringify(statsParametersCollection));
								
								// Извлекаем интервал, если он указан
								if (statsParametersCollection.interval && (statsParametersCollection.interval as IDataObject)?.interval) {
									console.log('Найден объект interval:', safeStringify(statsParametersCollection.interval));
									const interval = (statsParametersCollection.interval as IDataObject)?.interval as IDataObject;
									console.log('Значения interval:', safeStringify(interval));
									if (interval) {
										statsParameters.range = { interval };
										console.log('Установлен интервал:', interval);
									} else {
										console.log('Поле interval не найдено в объекте values');
									}
								} else {
									console.log('Объект interval не найден или не содержит values:', safeStringify(statsParametersCollection));
								}
								
								// Извлекаем параметры даты только если не указан интервал
								if (!statsParameters.interval) {
									if (statsParametersCollection.dateRange && (statsParametersCollection.dateRange as IDataObject)?.values) {
										const dateRange = (statsParametersCollection.dateRange as IDataObject)?.values as IDataObject;
										if (dateRange.range_from && dateRange.range_to) {
											statsParameters.range_from = dateRange.range_from;
											statsParameters.range_to = dateRange.range_to;
											console.log('Установлен диапазон дат:', safeStringify({ from: statsParameters.range_from, to: statsParameters.range_to }));
										}
									}
								}
								
								// Проверяем наличие обязательных параметров
								console.log('Проверка параметров:');
								console.log('- Есть ли интервал:', !!statsParameters.interval);
								console.log('- Есть ли диапазон дат:', !!(statsParameters.range_from && statsParameters.range_to));
								
								// Если указан интервал, удаляем параметры диапазона дат
								if (statsParameters.interval) {
									delete statsParameters.range_from;
									delete statsParameters.range_to;
								}
								
								// Проверяем наличие обязательных параметров
								if (!statsParameters.interval || !(statsParameters.range_from && statsParameters.range_to)) {
									console.log('Не указаны обязательные параметры, добавляем limit=100000 по умолчанию');
									statsParameters.limit = 100000;
								}
								
								console.log('Итоговые параметры запроса статистики:', safeStringify(statsParameters));
								
								response = await this.helpers.request({
									method: 'POST',
									url: fullUrl,
									body: statsParameters,
									headers,
									json: true,
									resolveWithFullResponse: true,
								});
							} else if (resource === 'conversion') {
								// Получаем параметры фильтрации для конверсий
								const conversionParametersCollection = this.getNodeParameter('conversionParameters', i, {}) as IDataObject;
								
								// Инициализация объекта для параметров запроса
								const conversionParameters: IDataObject = {};
								
								// Извлекаем параметры диапазона дат
								if (conversionParametersCollection.range && (conversionParametersCollection.range as IDataObject)?.values) {
									const range = (conversionParametersCollection.range as IDataObject)?.values as IDataObject;
									if (range.from) conversionParameters.from = range.from;
									if (range.to) conversionParameters.to = range.to;
									if (range.timezone) conversionParameters.timezone = range.timezone;
								}
								
								// Извлекаем интервал
								if (conversionParametersCollection.interval && (conversionParametersCollection.interval as IDataObject)?.values) {
									const interval = (conversionParametersCollection.interval as IDataObject)?.values as IDataObject;
									if (interval.interval) conversionParameters.interval = interval.interval;
								}
								
								// Извлекаем параметры пагинации
								if (conversionParametersCollection.pagination && (conversionParametersCollection.pagination as IDataObject)?.values) {
									const pagination = (conversionParametersCollection.pagination as IDataObject)?.values as IDataObject;
									if (pagination.limit) conversionParameters.limit = pagination.limit;
									if (pagination.offset) conversionParameters.offset = pagination.offset;
								}
								
								// Извлекаем колонки
								if (conversionParametersCollection.columns && (conversionParametersCollection.columns as IDataObject)?.values) {
									const columns = (conversionParametersCollection.columns as IDataObject)?.values as IDataObject;
									conversionParameters.columns = Object.keys(columns).filter(key => columns[key] === true);
								}
								
								// Извлекаем фильтры
								if (conversionParametersCollection.filters && (conversionParametersCollection.filters as IDataObject)?.values) {
									const filters = (conversionParametersCollection.filters as IDataObject)?.values as IDataObject[];
									if (filters && filters.length > 0) {
										conversionParameters.filters = filters.map(filter => ({
											name: filter.name,
											operator: filter.operator,
											expression: filter.expression
										}));
									}
								}
								
								// Извлекаем параметры сортировки
								if (conversionParametersCollection.sort && (conversionParametersCollection.sort as IDataObject)?.values) {
									const sort = (conversionParametersCollection.sort as IDataObject)?.values as IDataObject;
									if (sort.name) conversionParameters.sort = sort.name;
									if (sort.order) conversionParameters.order = sort.order;
								}
								
								// Проверяем наличие обязательных параметров
								const hasDateRange = conversionParameters.from && conversionParameters.to;
								const hasLimit = conversionParameters.limit !== undefined;
								
								// Если ни один из обязательных параметров не указан, добавляем limit по умолчанию
								if (!hasDateRange && !hasLimit) {
									console.log('Не указаны обязательные параметры для получения конверсий. Добавляем limit=100 по умолчанию');
									conversionParameters.limit = 100;
								}
								
								console.log(`Получение конверсий с параметрами:`, safeStringify(conversionParameters));
								
								response = await this.helpers.request({
									method: 'POST',
									url: fullUrl,
									body: conversionParameters,
									headers,
									json: true,
									resolveWithFullResponse: true,
								});
							} else {
								response = await this.helpers.request({
									method: 'GET',
									url: fullUrl,
									headers,
									json: true,
									resolveWithFullResponse: true,
								});
							}
							break;
							
						case 'create':
							console.log(`Данные для создания ${resource}:`, safeStringify(resourceData));
							response = await this.helpers.request({
								method: 'POST',
								url: fullUrl,
								body: resourceData,
								headers,
								json: true,
								resolveWithFullResponse: true,
							});
							break;
							
						case 'update':
							console.log(`Данные для обновления ${resource}:`, safeStringify(resourceData));
							
							// Особая обработка для конверсий
							if (resource === 'conversion') {
								console.log(`Обновление конверсии с ID: ${resourceId}`);
								
								// Проверка наличия click_id, если его нет, добавляем
								const conversionData = resourceData as IDataObject;
								if (!conversionData.click_id && resourceId) {
									console.log(`ID конверсии: ${resourceId} будет использован как click_id`);
									conversionData.click_id = resourceId;
								}
							}
							
							response = await this.helpers.request({
								method: 'PUT',
								url: fullUrl,
								body: resourceData,
								headers,
								json: true,
								resolveWithFullResponse: true,
							});
							break;
							
						case 'delete':
							// Для конверсий проверяем особый формат ID
							if (resource === 'conversion') {
								console.log(`Удаление конверсии с ID: ${resourceId}`);
								
								// Проверка формата ID - если это UUID в формате 8c086ed9-5dd2-4fc4-8cb0-d391c9e78144
								const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(resourceId);
								
								if (isUuid) {
									console.log('ID имеет формат UUID, используем специальный формат запроса');
								}
							}
							
							response = await this.helpers.request({
								method: 'DELETE',
								url: fullUrl,
								headers,
								json: true,
								resolveWithFullResponse: true,
							});
							break;
							
						case 'test':
							if (resource === 'postback') {
								// Формируем URL для отправки тестовой конверсии
								const testUrl = `${baseUrl}/admin_api/v1/conversions`;
								
								// Получаем тестовые данные
								const testPostbackData = this.getNodeParameter('testPostbackData', i) as IDataObject;
								const testData = testPostbackData.testData ? (testPostbackData.testData as IDataObject).values as IDataObject : {};
								
								if (!testData.click_id) {
									throw new Error('ID клика (subid) обязателен для тестирования постбэка');
								}
								
								// Формируем данные для тестовой конверсии
								const testConversionData: IDataObject = {
									click_id: testData.click_id,
									status: testData.status || 'lead',
									revenue: testData.payout || 10,
									currency: testData.currency || 'USD',
								};
								
								// Добавляем ID транзакции, если указан
								if (testData.transaction_id) {
									testConversionData.transaction_id = testData.transaction_id;
								}
								
								// Добавляем sub_id параметры, если указаны
								if (testData.sub_id_1) {
									testConversionData.sub_id_1 = testData.sub_id_1;
								}
								
								// Добавляем стоимость, если указана
								if (testData.cost) {
									testConversionData.cost = testData.cost;
								}
								
								console.log(`Отправка тестовой конверсии:`, safeStringify(testConversionData));
								
								// Отправляем запрос
								response = await this.helpers.request({
									method: 'POST',
									url: testUrl,
									body: testConversionData,
									headers,
									json: true,
									resolveWithFullResponse: true,
								});
							} else {
								throw new Error(`Операция "test" поддерживается только для ресурса "postback"`);
							}
							break;
							
						default:
							throw new Error(`Неподдерживаемая операция: ${operation}`);
					}

					// Проверяем статус ответа
					if (response && response.statusCode) {
						console.log(`Статус ответа: ${response.statusCode}`);
						
						if (response.statusCode < 200 || response.statusCode >= 300) {
							throw new Error(`Ошибка API: ${response.statusCode} ${response.statusMessage || ''}`);
						}
					}

					console.log('Получен ответ:', safeStringify(response));

					// Извлекаем тело ответа
					let responseBody: KeitaroResponse = response;
					if (response && response.body) {
						responseBody = response.body;
					}
					
					// Анализируем ответ
					console.log('Тело ответа:', safeStringify(responseBody));

					// Обработка различных форматов ответа
					let responseData: unknown = null;
					
					if (responseBody !== null && responseBody !== undefined) {
						// Если ответ - строка, пытаемся распарсить JSON
						if (typeof responseBody === 'string') {
							try {
								responseBody = JSON.parse(responseBody);
								console.log('Распарсили JSON из строки:', safeStringify(responseBody));
							} catch {
								console.log('Не удалось распарсить JSON:', responseBody);
								// Оставляем как есть, если не удалось распарсить
							}
						}

						try {
							// Извлекаем данные из ответа
							responseData = getResponseData(responseBody);
							console.log(`Извлечены данные из ответа: ${safeStringify(responseData).substring(0, 200)}...`);
						} catch (error) {
							console.log('Ошибка при извлечении данных:', error instanceof Error ? error.message : String(error));
							// Если не удалось извлечь данные из ответа, используем весь ответ
							responseData = responseBody;
						}
					} else {
						console.log('Ответ пустой');
					}

					// Типизируем ответ на основе ресурса
					const typedResponseData = getTypedResponse(resource, responseData);
					
					// Проверка на пустой ответ
					if (typedResponseData === null || typedResponseData === undefined) {
						console.log('Ответ пустой, устанавливаем пустой массив');
						responseData = [];
					} else {
						console.log('Итоговый типизированный ответ получен');
						responseData = typedResponseData;
					}

					// Добавляем данные в returnData в зависимости от операции
					if (operation === 'get' && resourceId) {
						// Для получения одной записи
						const result: IDataObject = {
							request: {
								url: fullUrl,
								method: operation.toUpperCase(),
								headers: {
									'Api-Key': '***', // Скрываем API ключ
									'Accept': 'application/json',
									'Content-Type': 'application/json',
								} as IDataObject,
							} as IDataObject,
							resource,
							operation,
						};
						
						result.data = typedResponseData as IDataObject | GenericValue | GenericValue[] | IDataObject[];

						returnData.push({
							json: result,
						});
					} else if (operation === 'getAll') {
						// Для получения списка записей
						let formattedData: (IDataObject | GenericValue)[] = [];
						
						if (Array.isArray(responseData)) {
							formattedData = responseData.map((item) => getTypedResponse(resource, item) as IDataObject | GenericValue);
						} else {
							formattedData = [typedResponseData as IDataObject | GenericValue];
						}
						
						const result: IDataObject = {
							request: {
								url: fullUrl,
								method: 'GET',
								headers: {
									'Api-Key': '***',
									'Accept': 'application/json',
									'Content-Type': 'application/json',
								} as IDataObject,
							} as IDataObject,
							resource,
							operation,
							count: formattedData.length,
						};
						
						result.data = formattedData;

						returnData.push({
							json: result,
						});
					} else {
						// Для всех остальных операций (create, update, delete)
						const result: IDataObject = {
							request: {
								url: fullUrl,
								method: operation.toUpperCase(),
								headers: {
									'Api-Key': '***',
									'Accept': 'application/json',
									'Content-Type': 'application/json',
								} as IDataObject,
							} as IDataObject,
							resource,
							operation,
							success: true,
						};
						
						result.data = typedResponseData as IDataObject | GenericValue | GenericValue[] | IDataObject[];

						returnData.push({
							json: result,
						});
					}
				} catch (error) {
					// Обработка ошибок API
					if (this.continueOnFail()) {
						const errorMessage = error instanceof Error ? error.message : String(error);
						const errorStack = error instanceof Error ? error.stack : '';
						const keitaroError = error as KeitaroError;
						
						console.log('❌ Ошибка при выполнении запроса:', errorMessage);
						if (keitaroError.response) {
							console.log('Статус ответа:', keitaroError.response.status);
							console.log('Данные ответа:', safeStringify(keitaroError.response.data));
						}
						
						const errorDetails: IDataObject = {
							message: errorMessage,
							stack: errorStack,
							resource,
							operation,
							url: keitaroError.config?.url || '',
							status: keitaroError.response?.status || '',
							statusText: keitaroError.response?.statusText || '',
							responseData: safeStringify(keitaroError.response?.data),
							error: true,
						};
						returnData.push({
							json: {
								error: errorDetails,
							},
						});
						continue;
					}
					throw error;
				}
			} catch (error) {
				// Общая обработка ошибок
				if (this.continueOnFail()) {
					const errorMessage = error instanceof Error ? error.message : String(error);
					const errorStack = error instanceof Error ? error.stack : '';
					const keitaroError = error as KeitaroError;
					const errorDetails: IDataObject = {
						message: errorMessage,
						stack: errorStack,
						resource,
						operation,
						url: keitaroError.config?.url || '',
						status: keitaroError.response?.status || '',
						statusText: keitaroError.response?.statusText || '',
						responseData: safeStringify(keitaroError.response?.data),
						error: true,
					};
					returnData.push({
						json: {
							error: errorDetails,
						},
					});
					continue;
				}
				throw error;
			}
		}

		return [returnData];
	}
}