MP Manager Cluster Auto Strategy Setter

Автоматическая установка стратегии рекламной кампании на основе статистики

Size

135.2 KB

Version

1.8.111

Created

Feb 13, 2026

Updated

24 days ago

1// ==UserScript==
2// @name		MP Manager Cluster Auto Strategy Setter
3// @description		Автоматическая установка стратегии рекламной кампании на основе статистики
4// @version		1.8.111
5// @match		https://*.app.mpmgr.ru/*
6// @icon		https://app.mpmgr.ru/favicon.ico
7// @grant		GM.getValue
8// @grant		GM.setValue
9// @grant		GM.deleteValue
10// @grant		GM.openInTab
11// @grant		GM.setClipboard
12// ==/UserScript==
13(function() {
14    'use strict';
15
16    console.log('MP Manager Auto Strategy Setter загружен');
17
18    // Константы
19    const STRATEGY_CODE = 'eyJjYW1wYWlnblR5cGUiOiJTZWFyY2hDYXRhbG9nIiwidmVyc2lvbiI6MiwiZGF0YSI6eyJzdGF0ZSI6IkVuYWJsZWQiLCJtb2RlIjp7InR5cGUiOiJQb3NpdGlvbiIsInBhdXNlVHlwZSI6IlJlc3VtZSJ9LCJzdHJhdGVneSI6eyJ0eXBlIjoiQ2FtcGFpZ25TdGF0cyIsIm1vZGUiOiJQbGFjZSIsImJpZE1vZGUiOiJDb3N0UGVyQ2xpY2siLCJjYW1wYWlnblN0YXRzIjp7Im1heFByaWNlIjo2MCwibWluUHJpY2UiOjEsInBsYXRmb3JtcyI6W10sImludGVydmFsIjoiV2VlayIsInJ1bGVzIjpbeyJ0eXBlIjoiQ29zdFBlckFkZGVkVG9DYXJ0IiwibW9kZSI6IlZhbHVlIiwidmFsdWUiOiIifV19fSwicGxhY2VTdHJhdGVneSI6eyJ0eXBlIjoiS2V5d29yZHMiLCJrZXl3b3JkcyI6eyJrZXl3b3JkcyI6W119fSwiaXNDbHVzdGVyIjp0cnVlfX0=';
20    const CLUSTER_STRATEGY_CODE = 'eyJjYW1wYWlnblR5cGUiOiJTZWFyY2hDYXRhbG9nIiwidmVyc2lvbiI6MiwiZGF0YSI6eyJzdGF0ZSI6IkVuYWJsZWQiLCJtb2RlIjp7InR5cGUiOiJQb3NpdGlvbiIsInBhdXNlVHlwZSI6IlJlc3VtZSJ9LCJzdHJhdGVneSI6eyJ0eXBlIjoiQ2FtcGFpZ25TdGF0cyIsIm1vZGUiOiJQbGFjZSIsImJpZE1vZGUiOiJDb3N0UGVyQ2xpY2siLCJjYW1wYWlnblN0YXRzIjp7Im1heFByaWNlIjo2MCwibWluUHJpY2UiOjEsInBsYXRmb3JtcyI6W10sImludGVydmFsIjoiV2VlayIsInJ1bGVzIjpbeyJ0eXBlIjoiQ29zdFBlckFkZGVkVG9DYXJ0IiwibW9kZSI6IlZhbHVlIiwidmFsdWUiOiIifV19fSwicGxhY2VTdHJhdGVneSI6eyJ0eXBlIjoiS2V5d29yZHMiLCJrZXl3b3JkcyI6eyJrZXl3b3JkcyI6W119fSwiaXNDbHVzdGVyIjp0cnVlfX0=';
21    
22    // Стратегия для удержания места (обычная)
23    const HOLD_POSITION_STRATEGY_CODE = 'eyJjYW1wYWlnblR5cGUiOiJTZWFyY2hDYXRhbG9nIiwidmVyc2lvbiI6MiwiZGF0YSI6eyJzdGF0ZSI6IkVuYWJsZWQiLCJtb2RlIjp7InR5cGUiOiJQb3NpdGlvbiIsInBhdXNlVHlwZSI6IlJlc3VtZSJ9LCJzdHJhdGVneSI6eyJ0eXBlIjoiQ2FtcGFpZ25TdGF0cyIsIm1vZGUiOiJQbGFjZSIsImJpZE1vZGUiOiJDb3N0UGVyQ2xpY2siLCJjYW1wYWlnblN0YXRzIjp7Im1heFByaWNlIjo2MCwibWluUHJpY2UiOjEsInBsYXRmb3JtcyI6W10sImludGVydmFsIjoiV2VlayIsInJ1bGVzIjpbeyJ0eXBlIjoiQ29zdFBlckFkZGVkVG9DYXJ0IiwibW9kZSI6IlZhbHVlIiwidmFsdWUiOiIifV19fSwicGxhY2VTdHJhdGVneSI6eyJ0eXBlIjoiS2V5d29yZHMiLCJrZXl3b3JkcyI6eyJrZXl3b3JkcyI6W119fSwiaXNDbHVzdGVyIjp0cnVlfX0=';
24    
25    // Стратегия для удержания места (кластерная)
26    const HOLD_POSITION_CLUSTER_STRATEGY_CODE = 'eyJjYW1wYWlnblR5cGUiOiJTZWFyY2hDYXRhbG9nIiwidmVyc2lvbiI6MiwiZGF0YSI6eyJzdGF0ZSI6IkVuYWJsZWQiLCJtb2RlIjp7InR5cGUiOiJQb3NpdGlvbiIsInBhdXNlVHlwZSI6IlJlc3VtZSJ9LCJzdHJhdGVneSI6eyJ0eXBlIjoiQ2FtcGFpZ25TdGF0cyIsIm1vZGUiOiJQbGFjZSIsImJpZE1vZGUiOiJDb3N0UGVyQ2xpY2siLCJjbHVzdGVyU3RhdHMiOnsibWF4QmlkIjo4MDAwLCJtaW5CaWQiOjQwMCwiaW50ZXJ2YWwiOiJUaHJlZURheXMiLCJydWxlcyI6W3sidHlwZSI6IkF2ZXJhZ2VQb3NpdGlvbiIsIm1vZGUiOiJWYWx1ZSIsInZhbHVlIjoyfSx7InR5cGUiOiJDb3N0UGVyQWRkZWRUb0NhcnQiLCJtb2RlIjoiQXZlcmFnZVZhbHVlIn1dfSwicGxhY2VTdHJhdGVneSI6eyJ0eXBlIjoiS2V5d29yZHMiLCJrZXl3b3JkcyI6eyJrZXl3b3JkcyI6W119fSwiaXNDbHVzdGVyIjpmYWxzZX19';
27    
28    // Глобальные переменные для массовой обработки
29    let isBulkProcessing = false;
30    let bulkDesiredPercentage = 30;
31    let bulkPaused = false;
32
33    // Функция для получения сохраненных стратегий
34    async function getSavedStrategies() {
35        let strategies = await GM.getValue('saved_strategies', []);
36        
37        // Миграция: добавляем ID к стратегиям, у которых его нет
38        let needsMigration = false;
39        strategies = strategies.map((strategy, index) => {
40            if (!strategy.id) {
41                needsMigration = true;
42                return {
43                    ...strategy,
44                    id: 'strategy_migrated_' + Date.now() + '_' + index
45                };
46            }
47            return strategy;
48        });
49        
50        // Сохраняем обновленные стратегии, если была миграция
51        if (needsMigration) {
52            await GM.setValue('saved_strategies', strategies);
53            console.log('Миграция стратегий выполнена: добавлены ID');
54        }
55        
56        // Если нет сохраненных стратегий, добавляем стратегию по умолчанию
57        if (strategies.length === 0) {
58            return [{
59                id: 'default',
60                name: 'Стратегия по умолчанию',
61                data: STRATEGY_CODE
62            }];
63        }
64        return strategies;
65    }
66
67    // Функция для получения сохраненных стратегий для кластеров
68    async function getSavedClusterStrategies() {
69        let strategies = await GM.getValue('saved_cluster_strategies', []);
70        
71        // Миграция: добавляем ID к стратегиям, у которых его нет
72        let needsMigration = false;
73        strategies = strategies.map((strategy, index) => {
74            if (!strategy.id) {
75                needsMigration = true;
76                return {
77                    ...strategy,
78                    id: 'cluster_strategy_migrated_' + Date.now() + '_' + index
79                };
80            }
81            return strategy;
82        });
83        
84        // Сохраняем обновленные стратегии, если была миграция
85        if (needsMigration) {
86            await GM.setValue('saved_cluster_strategies', strategies);
87            console.log('Миграция кластерных стратегий выполнена: добавлены ID');
88        }
89        
90        // Если нет сохраненных стратегий, добавляем стратегию по умолчанию
91        if (strategies.length === 0) {
92            return [{
93                id: 'cluster_default',
94                name: 'Кластерная стратегия по умолчанию',
95                data: CLUSTER_STRATEGY_CODE
96            }];
97        }
98        return strategies;
99    }
100
101    // Функция для получения текущей стратегии
102    async function getCurrentStrategy() {
103        const currentId = await GM.getValue('current_strategy_id', 'default');
104        const strategies = await getSavedStrategies();
105        const strategy = strategies.find(s => s.id === currentId);
106        return strategy ? strategy.data : STRATEGY_CODE;
107    }
108
109    // Функция для получения текущей кластерной стратегии
110    async function getCurrentClusterStrategy() {
111        const currentId = await GM.getValue('current_cluster_strategy_id', 'cluster_default');
112        const strategies = await getSavedClusterStrategies();
113        const strategy = strategies.find(s => s.id === currentId);
114        return strategy ? strategy.data : CLUSTER_STRATEGY_CODE;
115    }
116
117    // Функция для получения стратегии удержания места
118    async function getHoldPositionStrategy() {
119        const holdPositionId = await GM.getValue('hold_position_strategy_id', null);
120        if (holdPositionId) {
121            const strategies = await getSavedStrategies();
122            const strategy = strategies.find(s => s.id === holdPositionId);
123            if (strategy) {
124                return strategy.data;
125            }
126        }
127        // Возвращаем специальную стратегию удержания места по умолчанию
128        return HOLD_POSITION_STRATEGY_CODE;
129    }
130
131    // Функция для получения кластерной стратегии удержания места
132    async function getHoldPositionClusterStrategy() {
133        const holdPositionId = await GM.getValue('hold_position_cluster_strategy_id', null);
134        if (holdPositionId) {
135            const strategies = await getSavedClusterStrategies();
136            const strategy = strategies.find(s => s.id === holdPositionId);
137            if (strategy) {
138                return strategy.data;
139            }
140        }
141        // Возвращаем специальную кластерную стратегию удержания места по умолчанию
142        return HOLD_POSITION_CLUSTER_STRATEGY_CODE;
143    }
144
145    // Функция для создания модального окна управления стратегиями
146    function createStrategyManagementModal() {
147        return new Promise(async (resolve) => {
148            // Создаем оверлей
149            const overlay = document.createElement('div');
150            overlay.style.cssText = `
151                position: fixed;
152                top: 0;
153                left: 0;
154                width: 100%;
155                height: 100%;
156                background: rgba(0, 0, 0, 0.5);
157                display: flex;
158                justify-content: center;
159                align-items: center;
160                z-index: 10001;
161            `;
162            
163            // Создаем модальное окно
164            const modal = document.createElement('div');
165            modal.style.cssText = `
166                background: white;
167                border-radius: 12px;
168                padding: 24px;
169                min-width: 500px;
170                max-width: 600px;
171                max-height: 80vh;
172                overflow-y: auto;
173                box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
174            `;
175            
176            // Заголовок
177            const title = document.createElement('h2');
178            title.textContent = 'Управление стратегиями';
179            title.style.cssText = `
180                margin: 0 0 20px 0;
181                font-size: 24px;
182                font-weight: bold;
183                color: #333;
184            `;
185            modal.appendChild(title);
186            
187            // Контейнер для списка стратегий
188            const listContainer = document.createElement('div');
189            listContainer.style.cssText = `
190                margin-bottom: 20px;
191                max-height: 300px;
192                overflow-y: auto;
193            `;
194            
195            // Функция для обновления списка
196            const updateList = async () => {
197                const currentStrategies = await getSavedStrategies();
198                const selectedStrategy = await GM.getValue('current_strategy_id', 'default');
199                const holdPositionStrategyId = await GM.getValue('hold_position_strategy_id', null);
200                listContainer.innerHTML = '';
201                
202                if (currentStrategies.length === 0) {
203                    const emptyMessage = document.createElement('p');
204                    emptyMessage.textContent = 'Нет сохраненных стратегий. Используется стратегия по умолчанию.';
205                    emptyMessage.style.cssText = `
206                        color: #666;
207                        font-style: italic;
208                        padding: 20px;
209                        text-align: center;
210                    `;
211                    listContainer.appendChild(emptyMessage);
212                } else {
213                    currentStrategies.forEach((strategy, index) => {
214                        const item = document.createElement('div');
215                        const isSelected = strategy.id === selectedStrategy;
216                        const isHoldPosition = strategy.id === holdPositionStrategyId;
217                        item.style.cssText = `
218                            display: flex;
219                            justify-content: space-between;
220                            align-items: center;
221                            padding: 12px;
222                            margin-bottom: 8px;
223                            background: ${isSelected ? '#e3f2fd' : '#f5f5f5'};
224                            border-radius: 8px;
225                            border: ${isSelected ? '2px solid #2196f3' : '1px solid #ddd'};
226                        `;
227                        
228                        const nameSpan = document.createElement('span');
229                        nameSpan.textContent = strategy.name + (isSelected ? ' ✓' : '') + (isHoldPosition ? ' 📍' : '');
230                        nameSpan.style.cssText = `
231                            font-size: 16px;
232                            color: #333;
233                            flex: 1;
234                            font-weight: ${isSelected ? 'bold' : 'normal'};
235                        `;
236                        
237                        const buttonsContainer = document.createElement('div');
238                        buttonsContainer.style.cssText = `
239                            display: flex;
240                            gap: 8px;
241                        `;
242                        
243                        // Кнопка выбора
244                        if (!isSelected) {
245                            const selectBtn = document.createElement('button');
246                            selectBtn.textContent = '✓ Выбрать';
247                            selectBtn.style.cssText = `
248                                background: #2196f3;
249                                color: white;
250                                border: none;
251                                padding: 6px 12px;
252                                border-radius: 6px;
253                                cursor: pointer;
254                                font-size: 14px;
255                            `;
256                            selectBtn.onmouseover = () => selectBtn.style.background = '#1976d2';
257                            selectBtn.onmouseout = () => selectBtn.style.background = '#2196f3';
258                            selectBtn.onclick = async () => {
259                                await GM.setValue('current_strategy_id', strategy.id);
260                                console.log(`Выбрана стратегия: ${strategy.name} (ID: ${strategy.id})`);
261                                await updateList();
262                            };
263                            buttonsContainer.appendChild(selectBtn);
264                        }
265                        
266                        // Кнопка "Удержание места"
267                        const holdBtn = document.createElement('button');
268                        holdBtn.textContent = isHoldPosition ? '📍 Удалить' : '📍 Удержание';
269                        holdBtn.style.cssText = `
270                            background: ${isHoldPosition ? '#ff9800' : '#4caf50'};
271                            color: white;
272                            border: none;
273                            padding: 6px 12px;
274                            border-radius: 6px;
275                            cursor: pointer;
276                            font-size: 14px;
277                        `;
278                        holdBtn.onmouseover = () => holdBtn.style.background = isHoldPosition ? '#f57c00' : '#45a049';
279                        holdBtn.onmouseout = () => holdBtn.style.background = isHoldPosition ? '#ff9800' : '#4caf50';
280                        holdBtn.onclick = async () => {
281                            if (isHoldPosition) {
282                                await GM.deleteValue('hold_position_strategy_id');
283                                console.log('Стратегия удержания места удалена');
284                            } else {
285                                await GM.setValue('hold_position_strategy_id', strategy.id);
286                                console.log(`Установлена стратегия удержания места: ${strategy.name} (ID: ${strategy.id})`);
287                            }
288                            await updateList();
289                        };
290                        buttonsContainer.appendChild(holdBtn);
291                        
292                        // Кнопка удаления
293                        const deleteBtn = document.createElement('button');
294                        deleteBtn.textContent = '🗑️';
295                        deleteBtn.style.cssText = `
296                            background: #f44336;
297                            color: white;
298                            border: none;
299                            padding: 6px 12px;
300                            border-radius: 6px;
301                            cursor: pointer;
302                            font-size: 14px;
303                        `;
304                        deleteBtn.onmouseover = () => deleteBtn.style.background = '#d32f2f';
305                        deleteBtn.onmouseout = () => deleteBtn.style.background = '#f44336';
306                        deleteBtn.onclick = async () => {
307                            if (confirm(`Удалить стратегию "${strategy.name}"?`)) {
308                                currentStrategies.splice(index, 1);
309                                await GM.setValue('saved_strategies', currentStrategies);
310                                // Если удаляем выбранную стратегию, возвращаемся к дефолтной
311                                if (isSelected) {
312                                    await GM.setValue('current_strategy_id', 'default');
313                                }
314                                // Если удаляем стратегию удержания места, очищаем её
315                                if (isHoldPosition) {
316                                    await GM.deleteValue('hold_position_strategy_id');
317                                }
318                                await updateList();
319                            }
320                        };
321                        buttonsContainer.appendChild(deleteBtn);
322                        
323                        item.appendChild(nameSpan);
324                        item.appendChild(buttonsContainer);
325                        listContainer.appendChild(item);
326                    });
327                }
328            };
329            
330            await updateList();
331            modal.appendChild(listContainer);
332            
333            // Кнопка добавления стратегии
334            const addButton = document.createElement('button');
335            addButton.textContent = '➕ Добавить новую стратегию';
336            addButton.style.cssText = `
337                width: 100%;
338                background: #4caf50;
339                color: white;
340                border: none;
341                padding: 12px;
342                border-radius: 8px;
343                cursor: pointer;
344                font-size: 16px;
345                font-weight: bold;
346                margin-bottom: 12px;
347            `;
348            addButton.onmouseover = () => addButton.style.background = '#45a049';
349            addButton.onmouseout = () => addButton.style.background = '#4caf50';
350            addButton.onclick = async () => {
351                const name = prompt('Введите название стратегии:');
352                if (!name) return;
353                
354                const data = prompt('Вставьте код стратегии (скопируйте из MP Manager):');
355                if (!data) return;
356                
357                const currentStrategies = await GM.getValue('saved_strategies', []);
358                const newId = 'strategy_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
359                currentStrategies.push({ id: newId, name, data });
360                await GM.setValue('saved_strategies', currentStrategies);
361                alert(`Стратегия "${name}" сохранена!`);
362                await updateList();
363            };
364            modal.appendChild(addButton);
365            
366            // Кнопка закрытия
367            const closeButton = document.createElement('button');
368            closeButton.textContent = 'Закрыть';
369            closeButton.style.cssText = `
370                width: 100%;
371                background: #666;
372                color: white;
373                border: none;
374                padding: 12px;
375                border-radius: 8px;
376                cursor: pointer;
377                font-size: 16px;
378            `;
379            closeButton.onmouseover = () => closeButton.style.background = '#555';
380            closeButton.onmouseout = () => closeButton.style.background = '#666';
381            closeButton.onclick = () => {
382                document.body.removeChild(overlay);
383                resolve();
384            };
385            modal.appendChild(closeButton);
386            
387            overlay.appendChild(modal);
388            document.body.appendChild(overlay);
389            
390            // Закрытие по клику на оверлей
391            overlay.onclick = (e) => {
392                if (e.target === overlay) {
393                    document.body.removeChild(overlay);
394                    resolve();
395                }
396            };
397        });
398    }
399
400    // Функция для создания модального окна управления кластерными стратегиями
401    function createClusterStrategyManagementModal() {
402        return new Promise(async (resolve) => {
403            // Создаем оверлей
404            const overlay = document.createElement('div');
405            overlay.style.cssText = `
406                position: fixed;
407                top: 0;
408                left: 0;
409                width: 100%;
410                height: 100%;
411                background: rgba(0, 0, 0, 0.5);
412                display: flex;
413                justify-content: center;
414                align-items: center;
415                z-index: 10001;
416            `;
417            
418            // Создаем модальное окно
419            const modal = document.createElement('div');
420            modal.style.cssText = `
421                background: white;
422                border-radius: 12px;
423                padding: 24px;
424                min-width: 500px;
425                max-width: 600px;
426                max-height: 80vh;
427                overflow-y: auto;
428                box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
429            `;
430            
431            // Заголовок
432            const title = document.createElement('h2');
433            title.textContent = 'Управление стратегиями для кластеров';
434            title.style.cssText = `
435                margin: 0 0 20px 0;
436                font-size: 24px;
437                font-weight: bold;
438                color: #333;
439            `;
440            modal.appendChild(title);
441            
442            // Контейнер для списка стратегий
443            const listContainer = document.createElement('div');
444            listContainer.style.cssText = `
445                margin-bottom: 20px;
446                max-height: 300px;
447                overflow-y: auto;
448            `;
449            
450            // Функция для обновления списка
451            const updateList = async () => {
452                const currentStrategies = await getSavedClusterStrategies();
453                const selectedStrategy = await GM.getValue('current_cluster_strategy_id', 'cluster_default');
454                const holdPositionStrategyId = await GM.getValue('hold_position_cluster_strategy_id', null);
455                listContainer.innerHTML = '';
456                
457                if (currentStrategies.length === 0) {
458                    const emptyMessage = document.createElement('p');
459                    emptyMessage.textContent = 'Нет сохраненных кластерных стратегий. Используется стратегия по умолчанию.';
460                    emptyMessage.style.cssText = `
461                        color: #666;
462                        font-style: italic;
463                        padding: 20px;
464                        text-align: center;
465                    `;
466                    listContainer.appendChild(emptyMessage);
467                } else {
468                    currentStrategies.forEach((strategy, index) => {
469                        const item = document.createElement('div');
470                        const isSelected = strategy.id === selectedStrategy;
471                        const isHoldPosition = strategy.id === holdPositionStrategyId;
472                        item.style.cssText = `
473                            display: flex;
474                            justify-content: space-between;
475                            align-items: center;
476                            padding: 12px;
477                            margin-bottom: 8px;
478                            background: ${isSelected ? '#e3f2fd' : '#f5f5f5'};
479                            border-radius: 8px;
480                            border: ${isSelected ? '2px solid #2196f3' : '1px solid #ddd'};
481                        `;
482                        
483                        const nameSpan = document.createElement('span');
484                        nameSpan.textContent = strategy.name + (isSelected ? ' ✓' : '') + (isHoldPosition ? ' 📍' : '');
485                        nameSpan.style.cssText = `
486                            font-size: 16px;
487                            color: #333;
488                            flex: 1;
489                            font-weight: ${isSelected ? 'bold' : 'normal'};
490                        `;
491                        
492                        const buttonsContainer = document.createElement('div');
493                        buttonsContainer.style.cssText = `
494                            display: flex;
495                            gap: 8px;
496                        `;
497                        
498                        // Кнопка выбора
499                        if (!isSelected) {
500                            const selectBtn = document.createElement('button');
501                            selectBtn.textContent = '✓ Выбрать';
502                            selectBtn.style.cssText = `
503                                background: #2196f3;
504                                color: white;
505                                border: none;
506                                padding: 6px 12px;
507                                border-radius: 6px;
508                                cursor: pointer;
509                                font-size: 14px;
510                            `;
511                            selectBtn.onmouseover = () => selectBtn.style.background = '#1976d2';
512                            selectBtn.onmouseout = () => selectBtn.style.background = '#2196f3';
513                            selectBtn.onclick = async () => {
514                                await GM.setValue('current_cluster_strategy_id', strategy.id);
515                                console.log(`Выбрана кластерная стратегия: ${strategy.name} (ID: ${strategy.id})`);
516                                await updateList();
517                            };
518                            buttonsContainer.appendChild(selectBtn);
519                        }
520                        
521                        // Кнопка "Удержание места"
522                        const holdBtn = document.createElement('button');
523                        holdBtn.textContent = isHoldPosition ? '📍 Удалить' : '📍 Удержание';
524                        holdBtn.style.cssText = `
525                            background: ${isHoldPosition ? '#ff9800' : '#4caf50'};
526                            color: white;
527                            border: none;
528                            padding: 6px 12px;
529                            border-radius: 6px;
530                            cursor: pointer;
531                            font-size: 14px;
532                        `;
533                        holdBtn.onmouseover = () => holdBtn.style.background = isHoldPosition ? '#f57c00' : '#45a049';
534                        holdBtn.onmouseout = () => holdBtn.style.background = isHoldPosition ? '#ff9800' : '#4caf50';
535                        holdBtn.onclick = async () => {
536                            if (isHoldPosition) {
537                                await GM.deleteValue('hold_position_cluster_strategy_id');
538                                console.log('Кластерная стратегия удержания места удалена');
539                            } else {
540                                await GM.setValue('hold_position_cluster_strategy_id', strategy.id);
541                                console.log(`Установлена кластерная стратегия удержания места: ${strategy.name} (ID: ${strategy.id})`);
542                            }
543                            await updateList();
544                        };
545                        buttonsContainer.appendChild(holdBtn);
546                        
547                        // Кнопка удаления
548                        const deleteBtn = document.createElement('button');
549                        deleteBtn.textContent = '🗑️';
550                        deleteBtn.style.cssText = `
551                            background: #f44336;
552                            color: white;
553                            border: none;
554                            padding: 6px 12px;
555                            border-radius: 6px;
556                            cursor: pointer;
557                            font-size: 14px;
558                        `;
559                        deleteBtn.onmouseover = () => deleteBtn.style.background = '#d32f2f';
560                        deleteBtn.onmouseout = () => deleteBtn.style.background = '#f44336';
561                        deleteBtn.onclick = async () => {
562                            if (confirm(`Удалить кластерную стратегию "${strategy.name}"?`)) {
563                                currentStrategies.splice(index, 1);
564                                await GM.setValue('saved_cluster_strategies', currentStrategies);
565                                // Если удаляем выбранную стратегию, возвращаемся к дефолтной
566                                if (isSelected) {
567                                    await GM.setValue('current_cluster_strategy_id', 'cluster_default');
568                                }
569                                // Если удаляем стратегию удержания места, очищаем её
570                                if (isHoldPosition) {
571                                    await GM.deleteValue('hold_position_cluster_strategy_id');
572                                }
573                                await updateList();
574                            }
575                        };
576                        buttonsContainer.appendChild(deleteBtn);
577                        
578                        item.appendChild(nameSpan);
579                        item.appendChild(buttonsContainer);
580                        listContainer.appendChild(item);
581                    });
582                }
583            };
584            
585            await updateList();
586            modal.appendChild(listContainer);
587            
588            // Кнопка добавления стратегии
589            const addButton = document.createElement('button');
590            addButton.textContent = '➕ Добавить новую кластерную стратегию';
591            addButton.style.cssText = `
592                width: 100%;
593                background: #4caf50;
594                color: white;
595                border: none;
596                padding: 12px;
597                border-radius: 8px;
598                cursor: pointer;
599                font-size: 16px;
600                font-weight: bold;
601                margin-bottom: 12px;
602            `;
603            addButton.onmouseover = () => addButton.style.background = '#45a049';
604            addButton.onmouseout = () => addButton.style.background = '#4caf50';
605            addButton.onclick = async () => {
606                const name = prompt('Введите название кластерной стратегии:');
607                if (!name) return;
608                
609                const data = prompt('Вставьте код кластерной стратегии (скопируйте из MP Manager):');
610                if (!data) return;
611                
612                const currentStrategies = await GM.getValue('saved_cluster_strategies', []);
613                const newId = 'cluster_strategy_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
614                currentStrategies.push({ id: newId, name, data });
615                await GM.setValue('saved_cluster_strategies', currentStrategies);
616                alert(`Кластерная стратегия "${name}" сохранена!`);
617                await updateList();
618            };
619            modal.appendChild(addButton);
620            
621            // Кнопка закрытия
622            const closeButton = document.createElement('button');
623            closeButton.textContent = 'Закрыть';
624            closeButton.style.cssText = `
625                width: 100%;
626                background: #666;
627                color: white;
628                border: none;
629                padding: 12px;
630                border-radius: 8px;
631                cursor: pointer;
632                font-size: 16px;
633            `;
634            closeButton.onmouseover = () => closeButton.style.background = '#555';
635            closeButton.onmouseout = () => closeButton.style.background = '#666';
636            closeButton.onclick = () => {
637                document.body.removeChild(overlay);
638                resolve();
639            };
640            modal.appendChild(closeButton);
641            
642            overlay.appendChild(modal);
643            document.body.appendChild(overlay);
644            
645            // Закрытие по клику на оверлей
646            overlay.onclick = (e) => {
647                if (e.target === overlay) {
648                    document.body.removeChild(overlay);
649                    resolve();
650                }
651            };
652        });
653    }
654
655    // Функция для создания модального окна управления стратегиями удержания места
656    function createHoldPositionStrategyManagementModal() {
657        return new Promise(async (resolve) => {
658            // Создаем оверлей
659            const overlay = document.createElement('div');
660            overlay.style.cssText = `
661                position: fixed;
662                top: 0;
663                left: 0;
664                width: 100%;
665                height: 100%;
666                background: rgba(0, 0, 0, 0.5);
667                display: flex;
668                justify-content: center;
669                align-items: center;
670                z-index: 10001;
671            `;
672            
673            // Создаем модальное окно
674            const modal = document.createElement('div');
675            modal.style.cssText = `
676                background: white;
677                border-radius: 12px;
678                padding: 24px;
679                min-width: 500px;
680                max-width: 600px;
681                max-height: 80vh;
682                overflow-y: auto;
683                box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
684            `;
685            
686            // Заголовок
687            const title = document.createElement('h2');
688            title.textContent = 'Стратегии удержания места';
689            title.style.cssText = `
690                margin: 0 0 20px 0;
691                font-size: 24px;
692                font-weight: bold;
693                color: #333;
694            `;
695            modal.appendChild(title);
696            
697            // Описание
698            const description = document.createElement('p');
699            description.textContent = 'Здесь вы можете управлять стратегиями для обычных кампаний и кластеров, которые будут применяться при включенном чекбоксе "Удержание места".';
700            description.style.cssText = `
701                margin: 0 0 20px 0;
702                font-size: 14px;
703                color: #666;
704            `;
705            modal.appendChild(description);
706            
707            // Секция для обычных стратегий
708            const normalSection = document.createElement('div');
709            normalSection.style.cssText = `
710                margin-bottom: 30px;
711                padding: 15px;
712                background: #f9f9f9;
713                border-radius: 8px;
714            `;
715            
716            const normalTitle = document.createElement('h3');
717            normalTitle.textContent = '📋 Обычные кампании';
718            normalTitle.style.cssText = `
719                margin: 0 0 15px 0;
720                font-size: 18px;
721                font-weight: bold;
722                color: #333;
723            `;
724            normalSection.appendChild(normalTitle);
725            
726            const normalListContainer = document.createElement('div');
727            normalListContainer.style.cssText = `
728                margin-bottom: 15px;
729                max-height: 200px;
730                overflow-y: auto;
731            `;
732            
733            // Функция для обновления списка обычных стратегий
734            const updateNormalList = async () => {
735                const strategies = await getSavedStrategies();
736                const holdPositionStrategyId = await GM.getValue('hold_position_strategy_id', null);
737                normalListContainer.innerHTML = '';
738                
739                if (strategies.length === 0) {
740                    const emptyMessage = document.createElement('p');
741                    emptyMessage.textContent = 'Нет сохраненных стратегий.';
742                    emptyMessage.style.cssText = `
743                        color: #666;
744                        font-style: italic;
745                        padding: 10px;
746                        text-align: center;
747                    `;
748                    normalListContainer.appendChild(emptyMessage);
749                } else {
750                    strategies.forEach((strategy) => {
751                        const item = document.createElement('div');
752                        const isHoldPosition = strategy.id === holdPositionStrategyId;
753                        item.style.cssText = `
754                            display: flex;
755                            justify-content: space-between;
756                            align-items: center;
757                            padding: 10px;
758                            margin-bottom: 8px;
759                            background: ${isHoldPosition ? '#e8f5e9' : 'white'};
760                            border-radius: 6px;
761                            border: ${isHoldPosition ? '2px solid #4caf50' : '1px solid #ddd'};
762                        `;
763                        
764                        const nameSpan = document.createElement('span');
765                        nameSpan.textContent = strategy.name + (isHoldPosition ? ' ✓' : '');
766                        nameSpan.style.cssText = `
767                            font-size: 14px;
768                            color: #333;
769                            flex: 1;
770                            font-weight: ${isHoldPosition ? 'bold' : 'normal'};
771                        `;
772                        
773                        const selectBtn = document.createElement('button');
774                        selectBtn.textContent = isHoldPosition ? '✓ Выбрана' : 'Выбрать';
775                        selectBtn.disabled = isHoldPosition;
776                        selectBtn.style.cssText = `
777                            background: ${isHoldPosition ? '#4caf50' : '#2196f3'};
778                            color: white;
779                            border: none;
780                            padding: 6px 12px;
781                            border-radius: 6px;
782                            cursor: ${isHoldPosition ? 'default' : 'pointer'};
783                            font-size: 13px;
784                            opacity: ${isHoldPosition ? '0.7' : '1'};
785                        `;
786                        if (!isHoldPosition) {
787                            selectBtn.onmouseover = () => selectBtn.style.background = '#1976d2';
788                            selectBtn.onmouseout = () => selectBtn.style.background = '#2196f3';
789                            selectBtn.onclick = async () => {
790                                await GM.setValue('hold_position_strategy_id', strategy.id);
791                                console.log(`Установлена стратегия удержания места: ${strategy.name}`);
792                                await updateNormalList();
793                            };
794                        }
795                        
796                        item.appendChild(nameSpan);
797                        item.appendChild(selectBtn);
798                        normalListContainer.appendChild(item);
799                    });
800                }
801            };
802            
803            await updateNormalList();
804            normalSection.appendChild(normalListContainer);
805            
806            const normalResetBtn = document.createElement('button');
807            normalResetBtn.textContent = '🔄 Сбросить на стандартную';
808            normalResetBtn.style.cssText = `
809                width: 100%;
810                background: #ff9800;
811                color: white;
812                border: none;
813                padding: 10px;
814                border-radius: 6px;
815                cursor: pointer;
816                font-size: 14px;
817                font-weight: 600;
818            `;
819            normalResetBtn.onmouseover = () => normalResetBtn.style.background = '#f57c00';
820            normalResetBtn.onmouseout = () => normalResetBtn.style.background = '#ff9800';
821            normalResetBtn.onclick = async () => {
822                await GM.deleteValue('hold_position_strategy_id');
823                console.log('Стратегия удержания места сброшена на стандартную');
824                await updateNormalList();
825            };
826            normalSection.appendChild(normalResetBtn);
827            
828            modal.appendChild(normalSection);
829            
830            // Секция для кластерных стратегий
831            const clusterSection = document.createElement('div');
832            clusterSection.style.cssText = `
833                margin-bottom: 20px;
834                padding: 15px;
835                background: #f9f9f9;
836                border-radius: 8px;
837            `;
838            
839            const clusterTitle = document.createElement('h3');
840            clusterTitle.textContent = '🎯 Кластеры';
841            clusterTitle.style.cssText = `
842                margin: 0 0 15px 0;
843                font-size: 18px;
844                font-weight: bold;
845                color: #333;
846            `;
847            clusterSection.appendChild(clusterTitle);
848            
849            const clusterListContainer = document.createElement('div');
850            clusterListContainer.style.cssText = `
851                margin-bottom: 15px;
852                max-height: 200px;
853                overflow-y: auto;
854            `;
855            
856            // Функция для обновления списка кластерных стратегий
857            const updateClusterList = async () => {
858                const strategies = await getSavedClusterStrategies();
859                const holdPositionStrategyId = await GM.getValue('hold_position_cluster_strategy_id', null);
860                clusterListContainer.innerHTML = '';
861                
862                if (strategies.length === 0) {
863                    const emptyMessage = document.createElement('p');
864                    emptyMessage.textContent = 'Нет сохраненных кластерных стратегий.';
865                    emptyMessage.style.cssText = `
866                        color: #666;
867                        font-style: italic;
868                        padding: 10px;
869                        text-align: center;
870                    `;
871                    clusterListContainer.appendChild(emptyMessage);
872                } else {
873                    strategies.forEach((strategy) => {
874                        const item = document.createElement('div');
875                        const isHoldPosition = strategy.id === holdPositionStrategyId;
876                        item.style.cssText = `
877                            display: flex;
878                            justify-content: space-between;
879                            align-items: center;
880                            padding: 10px;
881                            margin-bottom: 8px;
882                            background: ${isHoldPosition ? '#e8f5e9' : 'white'};
883                            border-radius: 6px;
884                            border: ${isHoldPosition ? '2px solid #4caf50' : '1px solid #ddd'};
885                        `;
886                        
887                        const nameSpan = document.createElement('span');
888                        nameSpan.textContent = strategy.name + (isHoldPosition ? ' ✓' : '');
889                        nameSpan.style.cssText = `
890                            font-size: 14px;
891                            color: #333;
892                            flex: 1;
893                            font-weight: ${isHoldPosition ? 'bold' : 'normal'};
894                        `;
895                        
896                        const selectBtn = document.createElement('button');
897                        selectBtn.textContent = isHoldPosition ? '✓ Выбрана' : 'Выбрать';
898                        selectBtn.disabled = isHoldPosition;
899                        selectBtn.style.cssText = `
900                            background: ${isHoldPosition ? '#4caf50' : '#2196f3'};
901                            color: white;
902                            border: none;
903                            padding: 6px 12px;
904                            border-radius: 6px;
905                            cursor: ${isHoldPosition ? 'default' : 'pointer'};
906                            font-size: 13px;
907                            opacity: ${isHoldPosition ? '0.7' : '1'};
908                        `;
909                        if (!isHoldPosition) {
910                            selectBtn.onmouseover = () => selectBtn.style.background = '#1976d2';
911                            selectBtn.onmouseout = () => selectBtn.style.background = '#2196f3';
912                            selectBtn.onclick = async () => {
913                                await GM.setValue('hold_position_cluster_strategy_id', strategy.id);
914                                console.log(`Установлена кластерная стратегия удержания места: ${strategy.name}`);
915                                await updateClusterList();
916                            };
917                        }
918                        
919                        item.appendChild(nameSpan);
920                        item.appendChild(selectBtn);
921                        clusterListContainer.appendChild(item);
922                    });
923                }
924            };
925            
926            await updateClusterList();
927            clusterSection.appendChild(clusterListContainer);
928            
929            const clusterResetBtn = document.createElement('button');
930            clusterResetBtn.textContent = '🔄 Сбросить на стандартную';
931            clusterResetBtn.style.cssText = `
932                width: 100%;
933                background: #ff9800;
934                color: white;
935                border: none;
936                padding: 10px;
937                border-radius: 6px;
938                cursor: pointer;
939                font-size: 14px;
940                font-weight: 600;
941            `;
942            clusterResetBtn.onmouseover = () => clusterResetBtn.style.background = '#f57c00';
943            clusterResetBtn.onmouseout = () => clusterResetBtn.style.background = '#ff9800';
944            clusterResetBtn.onclick = async () => {
945                await GM.deleteValue('hold_position_cluster_strategy_id');
946                console.log('Кластерная стратегия удержания места сброшена на стандартную');
947                await updateClusterList();
948            };
949            clusterSection.appendChild(clusterResetBtn);
950            
951            modal.appendChild(clusterSection);
952            
953            // Кнопка закрытия
954            const closeButton = document.createElement('button');
955            closeButton.textContent = 'Закрыть';
956            closeButton.style.cssText = `
957                width: 100%;
958                background: #666;
959                color: white;
960                border: none;
961                padding: 12px;
962                border-radius: 8px;
963                cursor: pointer;
964                font-size: 16px;
965            `;
966            closeButton.onmouseover = () => closeButton.style.background = '#555';
967            closeButton.onmouseout = () => closeButton.style.background = '#666';
968            closeButton.onclick = () => {
969                document.body.removeChild(overlay);
970                resolve();
971            };
972            modal.appendChild(closeButton);
973            
974            overlay.appendChild(modal);
975            document.body.appendChild(overlay);
976            
977            // Закрытие по клику на оверлей
978            overlay.onclick = (e) => {
979                if (e.target === overlay) {
980                    document.body.removeChild(overlay);
981                    resolve();
982                }
983            };
984        });
985    }
986
987    // Функция для создания UI
988    function createUI() {
989        console.log('Создание UI панели');
990        
991        // Проверяем, есть ли сохраненный ДРР для массовой обработки
992        GM.getValue('bulkProcessingDRR', null).then(savedDRR => {
993            if (savedDRR !== null) {
994                console.log(`Найден сохраненный ДРР для массовой обработки: ${savedDRR}`);
995                // Автоматически запускаем стратегию с сохраненным ДРР
996                setTimeout(() => {
997                    const input = document.getElementById('desired-percentage');
998                    if (input) {
999                        input.value = savedDRR;
1000                        // Запускаем стратегию автоматически
1001                        runStrategy();
1002                    }
1003                }, 2000);
1004            }
1005        });
1006        
1007        const panel = document.createElement('div');
1008        panel.id = 'auto-strategy-panel';
1009        panel.style.cssText = `
1010            position: fixed;
1011            top: 20px;
1012            right: 20px;
1013            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1014            padding: 15px;
1015            border-radius: 12px;
1016            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
1017            z-index: 10000;
1018            min-width: 280px;
1019            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1020            color: white;
1021            transition: all 0.3s ease;
1022            cursor: move;
1023        `;
1024
1025        panel.innerHTML = `
1026            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; cursor: pointer;" id="panel-header">
1027                <h3 style="margin: 0; font-size: 16px; font-weight: 600;">🚀 Авто-стратегия</h3>
1028                <span id="toggle-icon" style="font-size: 18px;"></span>
1029            </div>
1030            
1031            <div id="panel-content" style="display: none;">
1032                <div style="margin-bottom: 15px;">
1033                    <label style="display: block; margin-bottom: 8px; font-size: 13px; font-weight: 500;">
1034                        Желаемый % рекламных расходов:
1035                    </label>
1036                    <input 
1037                        type="number" 
1038                        id="desired-percentage" 
1039                        value="30" 
1040                        min="1" 
1041                        max="100" 
1042                        step="0.1"
1043                        style="
1044                            width: 100%;
1045                            padding: 10px;
1046                            border: none;
1047                            border-radius: 8px;
1048                            font-size: 14px;
1049                            box-sizing: border-box;
1050                            background: rgba(255, 255, 255, 0.95);
1051                            color: #333;
1052                            cursor: text;
1053                        "
1054                    />
1055                </div>
1056
1057                <div style="margin-bottom: 15px;">
1058                    <label style="display: flex; align-items: center; cursor: pointer; font-size: 13px; font-weight: 500;">
1059                        <input 
1060                            type="checkbox" 
1061                            id="apply-to-clusters" 
1062                            checked
1063                            style="
1064                                margin-right: 8px;
1065                                width: 18px;
1066                                height: 18px;
1067                                cursor: pointer;
1068                            "
1069                        />
1070                        Применить стратегию к кластерам
1071                    </label>
1072                </div>
1073
1074                <div style="margin-bottom: 15px;">
1075                    <label style="display: flex; align-items: center; cursor: pointer; font-size: 13px; font-weight: 500;">
1076                        <input 
1077                            type="checkbox" 
1078                            id="hold-position" 
1079                            checked
1080                            style="
1081                                margin-right: 8px;
1082                                width: 18px;
1083                                height: 18px;
1084                                cursor: pointer;
1085                            "
1086                        />
1087                        Удержание места
1088                    </label>
1089                </div>
1090
1091                <button 
1092                    id="run-strategy-btn"
1093                    style="
1094                        width: 100%;
1095                        padding: 12px;
1096                        background: white;
1097                        color: #667eea;
1098                        border: none;
1099                        border-radius: 8px;
1100                        font-size: 14px;
1101                        font-weight: 600;
1102                        cursor: pointer;
1103                        transition: all 0.3s ease;
1104                        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1105                        margin-bottom: 10px;
1106                    "
1107                    onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 6px 16px rgba(0, 0, 0, 0.2)';"
1108                    onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 4px 12px rgba(0, 0, 0, 0.15)';"
1109                >
1110                    Запустить
1111                </button>
1112
1113                <button 
1114                    id="manage-strategies-btn"
1115                    style="
1116                        width: 100%;
1117                        padding: 10px;
1118                        background: rgba(255, 255, 255, 0.2);
1119                        color: white;
1120                        border: 1px solid rgba(255, 255, 255, 0.3);
1121                        border-radius: 8px;
1122                        font-size: 13px;
1123                        font-weight: 600;
1124                        cursor: pointer;
1125                        transition: all 0.3s ease;
1126                        margin-bottom: 8px;
1127                    "
1128                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1129                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1130                >
1131                    ⚙️ Управление стратегиями
1132                </button>
1133
1134                <button 
1135                    id="manage-cluster-strategies-btn"
1136                    style="
1137                        width: 100%;
1138                        padding: 10px;
1139                        background: rgba(255, 255, 255, 0.2);
1140                        color: white;
1141                        border: 1px solid rgba(255, 255, 255, 0.3);
1142                        border-radius: 8px;
1143                        font-size: 13px;
1144                        font-weight: 600;
1145                        cursor: pointer;
1146                        transition: all 0.3s ease;
1147                        margin-bottom: 8px;
1148                    "
1149                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1150                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1151                >
1152                    🎯 Стратегии для кластеров
1153                </button>
1154
1155                <button 
1156                    id="manage-hold-position-strategies-btn"
1157                    style="
1158                        width: 100%;
1159                        padding: 10px;
1160                        background: rgba(255, 255, 255, 0.2);
1161                        color: white;
1162                        border: 1px solid rgba(255, 255, 255, 0.3);
1163                        border-radius: 8px;
1164                        font-size: 13px;
1165                        font-weight: 600;
1166                        cursor: pointer;
1167                        transition: all 0.3s ease;
1168                    "
1169                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1170                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1171                >
1172                    📍 Стратегии удержания места
1173                </button>
1174
1175                <div id="status-message" style="
1176                    margin-top: 15px;
1177                    padding: 10px;
1178                    border-radius: 8px;
1179                    font-size: 12px;
1180                    background: rgba(255, 255, 255, 0.2);
1181                    display: none;
1182                "></div>
1183            </div>
1184        `;
1185
1186        document.body.appendChild(panel);
1187        console.log('UI панель создана');
1188
1189        // Добавляем возможность перетаскивания
1190        makeDraggable(panel);
1191
1192        // Добавляем обработчик клика на заголовок для разворачивания/сворачивания
1193        document.getElementById('panel-header').addEventListener('click', () => {
1194            const content = document.getElementById('panel-content');
1195            const icon = document.getElementById('toggle-icon');
1196            if (content.style.display === 'none') {
1197                content.style.display = 'block';
1198                icon.textContent = '▲';
1199            } else {
1200                content.style.display = 'none';
1201                icon.textContent = '▼';
1202            }
1203        });
1204
1205        // Добавляем обработчик клика на кнопку
1206        document.getElementById('run-strategy-btn').addEventListener('click', runStrategy);
1207        
1208        // Добавляем обработчик для кнопки управления стратегиями
1209        document.getElementById('manage-strategies-btn').addEventListener('click', async () => {
1210            await createStrategyManagementModal();
1211        });
1212        
1213        // Добавляем обработчик для кнопки управления кластерными стратегиями
1214        document.getElementById('manage-cluster-strategies-btn').addEventListener('click', async () => {
1215            await createClusterStrategyManagementModal();
1216        });
1217        
1218        // Добавляем обработчик для кнопки управления стратегиями удержания места
1219        document.getElementById('manage-hold-position-strategies-btn').addEventListener('click', async () => {
1220            await createHoldPositionStrategyManagementModal();
1221        });
1222    }
1223
1224    // Функция для создания UI панели массового изменения
1225    function createBulkUI() {
1226        console.log('Создание UI панели массового изменения');
1227        
1228        const panel = document.createElement('div');
1229        panel.id = 'bulk-strategy-panel';
1230        panel.style.cssText = `
1231            position: fixed;
1232            top: 20px;
1233            right: 20px;
1234            background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
1235            padding: 15px;
1236            border-radius: 12px;
1237            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
1238            z-index: 10000;
1239            min-width: 300px;
1240            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1241            color: white;
1242            transition: all 0.3s ease;
1243            cursor: move;
1244        `;
1245
1246        panel.innerHTML = `
1247            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; cursor: pointer;" id="bulk-panel-header">
1248                <h3 style="margin: 0; font-size: 16px; font-weight: 600;">📦 Массовое изменение</h3>
1249                <span id="bulk-toggle-icon" style="font-size: 18px;"></span>
1250            </div>
1251            
1252            <div id="bulk-panel-content" style="display: none;">
1253                <div style="margin-bottom: 15px;">
1254                    <label style="display: block; margin-bottom: 8px; font-size: 13px; font-weight: 500;">
1255                        Желаемый % рекламных расходов (ДРР):
1256                    </label>
1257                    <input 
1258                        type="number" 
1259                        id="bulk-desired-percentage" 
1260                        value="30" 
1261                        min="1" 
1262                        max="100" 
1263                        step="0.1"
1264                        style="
1265                            width: 100%;
1266                            padding: 10px;
1267                            border: none;
1268                            border-radius: 8px;
1269                            font-size: 14px;
1270                            box-sizing: border-box;
1271                            background: rgba(255, 255, 255, 0.95);
1272                            color: #333;
1273                            cursor: text;
1274                        "
1275                    />
1276                </div>
1277
1278                <div id="bulk-campaigns-info" style="
1279                    margin-bottom: 15px;
1280                    padding: 10px;
1281                    border-radius: 8px;
1282                    font-size: 12px;
1283                    background: rgba(255, 255, 255, 0.2);
1284                ">
1285                    Найдено кампаний: <span id="campaigns-count">0</span>
1286                </div>
1287
1288                <button 
1289                    id="run-bulk-strategy-btn"
1290                    style="
1291                        width: 100%;
1292                        padding: 12px;
1293                        background: white;
1294                        color: #f5576c;
1295                        border: none;
1296                        border-radius: 8px;
1297                        font-size: 14px;
1298                        font-weight: 600;
1299                        cursor: pointer;
1300                        transition: all 0.3s ease;
1301                        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1302                        margin-bottom: 10px;
1303                    "
1304                    onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 6px 16px rgba(0, 0, 0, 0.2)';"
1305                    onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 4px 12px rgba(0, 0, 0, 0.15)';"
1306                >
1307                    Запустить
1308                </button>
1309
1310                <button 
1311                    id="bulk-manage-strategies-btn"
1312                    style="
1313                        width: 100%;
1314                        padding: 10px;
1315                        background: rgba(255, 255, 255, 0.2);
1316                        color: white;
1317                        border: 1px solid rgba(255, 255, 255, 0.3);
1318                        border-radius: 8px;
1319                        font-size: 13px;
1320                        font-weight: 600;
1321                        cursor: pointer;
1322                        transition: all 0.3s ease;
1323                        margin-bottom: 10px;
1324                    "
1325                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1326                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1327                >
1328                    ⚙️ Управление стратегиями
1329                </button>
1330
1331                <button 
1332                    id="bulk-manage-cluster-strategies-btn"
1333                    style="
1334                        width: 100%;
1335                        padding: 10px;
1336                        background: rgba(255, 255, 255, 0.2);
1337                        color: white;
1338                        border: 1px solid rgba(255, 255, 255, 0.3);
1339                        border-radius: 8px;
1340                        font-size: 13px;
1341                        font-weight: 600;
1342                        cursor: pointer;
1343                        transition: all 0.3s ease;
1344                        margin-bottom: 10px;
1345                    "
1346                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1347                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1348                >
1349                    🎯 Стратегии для кластеров
1350                </button>
1351
1352                <div style="margin-bottom: 15px;">
1353                    <label style="display: flex; align-items: center; cursor: pointer; font-size: 13px; font-weight: 500;">
1354                        <input 
1355                            type="checkbox" 
1356                            id="bulk-apply-to-clusters" 
1357                            checked
1358                            style="
1359                                margin-right: 8px;
1360                                width: 18px;
1361                                height: 18px;
1362                                cursor: pointer;
1363                            "
1364                        />
1365                        Применить стратегию к кластерам
1366                    </label>
1367                </div>
1368
1369                <div style="margin-bottom: 15px;">
1370                    <label style="display: flex; align-items: center; cursor: pointer; font-size: 13px; font-weight: 500;">
1371                        <input 
1372                            type="checkbox" 
1373                            id="bulk-hold-position" 
1374                            checked
1375                            style="
1376                                margin-right: 8px;
1377                                width: 18px;
1378                                height: 18px;
1379                                cursor: pointer;
1380                            "
1381                        />
1382                        Удержание места
1383                    </label>
1384                </div>
1385
1386                <div id="bulk-control-buttons" style="
1387                    margin-top: 10px;
1388                    display: none;
1389                    gap: 10px;
1390                ">
1391                    <button 
1392                        id="pause-bulk-btn"
1393                        style="
1394                            flex: 1;
1395                            padding: 10px;
1396                            background: rgba(255, 255, 255, 0.9);
1397                            color: #f5576c;
1398                            border: none;
1399                            border-radius: 8px;
1400                            font-size: 13px;
1401                            font-weight: 600;
1402                            cursor: pointer;
1403                            transition: all 0.3s ease;
1404                        "
1405                    >
1406                        ⏏️ Пауза
1407                    </button>
1408                    <button 
1409                        id="stop-bulk-btn"
1410                        style="
1411                            flex: 1;
1412                            padding: 10px;
1413                            background: rgba(255, 59, 48, 0.9);
1414                            color: white;
1415                            border: none;
1416                            border-radius: 8px;
1417                            font-size: 13px;
1418                            font-weight: 600;
1419                            cursor: pointer;
1420                            transition: all 0.3s ease;
1421                        "
1422                    >
1423                        ⏹️ Стоп
1424                    </button>
1425                </div>
1426
1427                <div id="bulk-status-message" style="
1428                    margin-top: 15px;
1429                    padding: 10px;
1430                    border-radius: 8px;
1431                    font-size: 12px;
1432                    background: rgba(255, 255, 255, 0.2);
1433                    display: none;
1434                "></div>
1435
1436                <div id="bulk-progress" style="
1437                    margin-top: 15px;
1438                    display: none;
1439                ">
1440                    <div style="margin-bottom: 5px; font-size: 12px;">
1441                        Прогресс: <span id="bulk-progress-text">0/0</span>
1442                    </div>
1443                    <div style="
1444                        width: 100%;
1445                        height: 8px;
1446                        background: rgba(255, 255, 255, 0.3);
1447                        border-radius: 4px;
1448                        overflow: hidden;
1449                    ">
1450                        <div id="bulk-progress-bar" style="
1451                            width: 0%;
1452                            height: 100%;
1453                            background: white;
1454                            transition: width 0.3s ease;
1455                        "></div>
1456                    </div>
1457                </div>
1458            </div>
1459        `;
1460
1461        document.body.appendChild(panel);
1462        console.log('UI панель массового изменения создана');
1463
1464        // Добавляем возможность перетаскивания
1465        makeDraggable(panel);
1466
1467        // Подсчитываем количество кампаний
1468        updateCampaignsCount();
1469
1470        // Добавляем обработчик клика на заголовок для разворачивания/сворачивания
1471        document.getElementById('bulk-panel-header').addEventListener('click', () => {
1472            const content = document.getElementById('bulk-panel-content');
1473            const icon = document.getElementById('bulk-toggle-icon');
1474            if (content.style.display === 'none') {
1475                content.style.display = 'block';
1476                icon.textContent = '▲';
1477            } else {
1478                content.style.display = 'none';
1479                icon.textContent = '▼';
1480            }
1481        });
1482
1483        // Добавляем обработчик клика на кнопку
1484        document.getElementById('run-bulk-strategy-btn').addEventListener('click', runBulkStrategy);
1485        
1486        // Добавляем обработчик для кнопки управления стратегиями
1487        document.getElementById('bulk-manage-strategies-btn').addEventListener('click', async () => {
1488            await createStrategyManagementModal();
1489        });
1490        
1491        // Добавляем обработчик для кнопки управления кластерными стратегиями
1492        document.getElementById('bulk-manage-cluster-strategies-btn').addEventListener('click', async () => {
1493            await createClusterStrategyManagementModal();
1494        });
1495        
1496        // Добавляем обработчики для кнопок управления
1497        document.getElementById('pause-bulk-btn').addEventListener('click', pauseBulkProcessing);
1498        document.getElementById('stop-bulk-btn').addEventListener('click', stopBulkProcessing);
1499    }
1500
1501    // Функция для создания перетаскиваемого элемента
1502    function makeDraggable(element) {
1503        let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
1504        let isDragging = false;
1505
1506        element.onmousedown = dragMouseDown;
1507
1508        function dragMouseDown(e) {
1509            // Не перетаскиваем, если кликнули на input, button или другие интерактивные элементы
1510            if (e.target.tagName === 'INPUT' || e.target.tagName === 'BUTTON' || e.target.tagName === 'TEXTAREA') {
1511                return;
1512            }
1513            
1514            e.preventDefault();
1515            isDragging = true;
1516            pos3 = e.clientX;
1517            pos4 = e.clientY;
1518            document.onmouseup = closeDragElement;
1519            document.onmousemove = elementDrag;
1520        }
1521
1522        function elementDrag(e) {
1523            if (!isDragging) return;
1524            pos1 = pos3 - e.clientX;
1525            pos2 = pos4 - e.clientY;
1526            pos3 = e.clientX;
1527            pos4 = e.clientY;
1528            element.style.top = (element.offsetTop - pos2) + 'px';
1529            element.style.left = (element.offsetLeft - pos1) + 'px';
1530            element.style.right = 'auto';
1531            element.style.bottom = 'auto';
1532        }
1533
1534        function closeDragElement() {
1535            isDragging = false;
1536            document.onmouseup = null;
1537            document.onmousemove = null;
1538        }
1539    }
1540
1541    // Функция для обновления количества кампаний
1542    function updateCampaignsCount() {
1543        const campaignLinks = document.querySelectorAll('a[href*="/campaigns/auto-campaigns/"][href*="/campaign"]');
1544        const count = campaignLinks.length;
1545        const countElement = document.getElementById('campaigns-count');
1546        if (countElement) {
1547            countElement.textContent = count;
1548        }
1549        console.log(`Найдено кампаний: ${count}`);
1550    }
1551
1552    // Функция для показа статуса массовой обработки
1553    function showBulkStatus(message, isError = false) {
1554        const statusDiv = document.getElementById('bulk-status-message');
1555        if (statusDiv) {
1556            statusDiv.textContent = message;
1557            statusDiv.style.display = 'block';
1558            statusDiv.style.background = isError ? 'rgba(255, 59, 48, 0.9)' : 'rgba(52, 199, 89, 0.9)';
1559            console.log(`Статус массовой обработки: ${message}`);
1560        }
1561    }
1562
1563    // Функция для обновления прогресса
1564    function updateBulkProgress(current, total) {
1565        const progressDiv = document.getElementById('bulk-progress');
1566        const progressText = document.getElementById('bulk-progress-text');
1567        const progressBar = document.getElementById('bulk-progress-bar');
1568        
1569        if (progressDiv && progressText && progressBar) {
1570            progressDiv.style.display = 'block';
1571            progressText.textContent = `${current}/${total}`;
1572            const percentage = (current / total) * 100;
1573            progressBar.style.width = `${percentage}%`;
1574        }
1575    }
1576
1577    // Функция для прокрутки страницы вниз для загрузки всех кампаний
1578    async function scrollToLoadAllCampaigns() {
1579        console.log('Начинаем загрузку всех кампаний через прокрутку...');
1580        
1581        // Находим контейнер с прокруткой
1582        const tableContainer = document.querySelector('.container.MuiBox-root.css-9hf803');
1583        
1584        if (!tableContainer) {
1585            console.error('Контейнер таблицы не найден');
1586            return [];
1587        }
1588        
1589        console.log('Контейнер найден, начинаем прокрутку...');
1590        console.log(`Высота контейнера: ${tableContainer.scrollHeight}px`);
1591        
1592        // Собираем уникальные ссылки во время прокрутки
1593        const uniqueLinks = new Set();
1594        
1595        // Прокручиваем контейнер постепенно, чтобы загрузить все кампании
1596        let previousLinksCount = 0;
1597        let stableCount = 0;
1598        const maxAttempts = 200; // Максимум попыток
1599        let attempts = 0;
1600        const scrollStep = 500; // Прокручиваем по 500px за раз
1601        
1602        while (attempts < maxAttempts) {
1603            // Собираем ссылки на текущем шаге
1604            const currentLinks = document.querySelectorAll('a[href*="/campaigns/auto-campaigns/"][href*="/campaign"]');
1605            currentLinks.forEach(link => {
1606                uniqueLinks.add(link.href);
1607            });
1608            
1609            const currentCount = uniqueLinks.size;
1610            console.log(`Загружено кампаний: ${currentCount}, прокрутка: ${tableContainer.scrollTop}/${tableContainer.scrollHeight}`);
1611            
1612            // Прокручиваем контейнер постепенно
1613            tableContainer.scrollTop += scrollStep;
1614            
1615            // Ждем загрузки новых элементов
1616            await wait(500);
1617            
1618            // Если количество не изменилось
1619            if (currentCount === previousLinksCount) {
1620                stableCount++;
1621                // Если количество стабильно 5 раз подряд - значит все загружено
1622                if (stableCount >= 5) {
1623                    console.log('Все кампании загружены');
1624                    break;
1625                }
1626            } else {
1627                stableCount = 0;
1628                previousLinksCount = currentCount;
1629            }
1630            
1631            // Если достигли конца контейнера
1632            if (tableContainer.scrollTop + tableContainer.clientHeight >= tableContainer.scrollHeight - 10) {
1633                console.log('Достигнут конец контейнера');
1634                // Ждем еще немного для загрузки последних элементов
1635                await wait(1000);
1636                
1637                // Собираем последние ссылки
1638                const finalLinks = document.querySelectorAll('a[href*="/campaigns/auto-campaigns/"][href*="/campaign"]');
1639                finalLinks.forEach(link => {
1640                    uniqueLinks.add(link.href);
1641                });
1642                
1643                // Проверяем еще раз количество
1644                if (uniqueLinks.size === previousLinksCount) {
1645                    break;
1646                }
1647                previousLinksCount = uniqueLinks.size;
1648            }
1649            
1650            attempts++;
1651        }
1652        
1653        // Преобразуем Set в массив URL (НЕ прокручиваем обратно!)
1654        const links = Array.from(uniqueLinks);
1655        
1656        console.log(`Найдено кампаний: ${links.length}`);
1657        console.log(`Всего попыток прокрутки: ${attempts}`);
1658        return links;
1659    }
1660
1661    // Функция для массовой обработки кампаний
1662    async function runBulkStrategy() {
1663        if (isBulkProcessing) {
1664            showBulkStatus('Обработка уже выполняется', true);
1665            return;
1666        }
1667
1668        try {
1669            isBulkProcessing = true;
1670            console.log('Начало массовой обработки кампаний');
1671            
1672            bulkDesiredPercentage = parseFloat(document.getElementById('bulk-desired-percentage').value);
1673            if (!bulkDesiredPercentage || bulkDesiredPercentage <= 0) {
1674                showBulkStatus('Ошибка: введите корректный процент', true);
1675                isBulkProcessing = false;
1676                return;
1677            }
1678            console.log(`Желаемый процент: ${bulkDesiredPercentage}%`);
1679
1680            // Сохраняем ДРР для автоматической обработки
1681            await GM.setValue('bulkProcessingDRR', bulkDesiredPercentage);
1682            console.log(`ДРР ${bulkDesiredPercentage} сохранен для массовой обработки`);
1683
1684            // Прокручиваем страницу для загрузки всех кампаний
1685            const campaignLinks = await scrollToLoadAllCampaigns();
1686            
1687            if (campaignLinks.length === 0) {
1688                showBulkStatus('Ошибка: кампании не найдены', true);
1689                isBulkProcessing = false;
1690                await GM.deleteValue('bulkProcessingDRR');
1691                return;
1692            }
1693
1694            console.log(`Найдено кампаний для обработки: ${campaignLinks.length}`);
1695            showBulkStatus(`Начинаем обработку ${campaignLinks.length} кампаний...`);
1696            updateBulkProgress(0, campaignLinks.length);
1697
1698            // Сохраняем список кампаний (массив URL), текущий индекс и общее количество
1699            await GM.setValue('bulkCampaigns', JSON.stringify(campaignLinks));
1700            await GM.setValue('bulkCurrentIndex', 0);
1701            await GM.setValue('bulkTotalCampaigns', campaignLinks.length);
1702
1703            // Показываем кнопки управления
1704            const controlButtons = document.getElementById('bulk-control-buttons');
1705            if (controlButtons) {
1706                controlButtons.style.display = 'flex';
1707            }
1708
1709            // Открываем первую кампанию в новой вкладке через window.open
1710            if (campaignLinks.length > 0) {
1711                console.log(`Открытие кампании 1/${campaignLinks.length}: ${campaignLinks[0]}`);
1712                window.open(campaignLinks[0], '_blank');
1713            }
1714
1715        } catch (error) {
1716            console.error('Ошибка при массовой обработке:', error);
1717            showBulkStatus(`Ошибка: ${error.message}`, true);
1718            isBulkProcessing = false;
1719            await GM.deleteValue('bulkProcessingDRR');
1720        }
1721    }
1722
1723    // Функция для паузы массовой обработки
1724    async function pauseBulkProcessing() {
1725        bulkPaused = !bulkPaused;
1726        const pauseBtn = document.getElementById('pause-bulk-btn');
1727        
1728        if (bulkPaused) {
1729            await GM.setValue('bulkPaused', true);
1730            pauseBtn.textContent = '▶️ Продолжить';
1731            showBulkStatus('⏸️ Обработка приостановлена');
1732            console.log('Массовая обработка приостановлена');
1733        } else {
1734            await GM.deleteValue('bulkPaused');
1735            pauseBtn.textContent = '⏸️ Пауза';
1736            showBulkStatus('▶️ Обработка возобновлена');
1737            console.log('Массовая обработка возобновлена');
1738            
1739            // Продолжаем обработку - открываем следующую кампанию
1740            const campaignsJson = await GM.getValue('bulkCampaigns', null);
1741            const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
1742            const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
1743            
1744            if (campaignsJson) {
1745                const campaigns = JSON.parse(campaignsJson);
1746                const nextIndex = currentIndex + 1;
1747                
1748                console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
1749                
1750                if (nextIndex < campaigns.length) {
1751                    // Сохраняем новый индекс
1752                    await GM.setValue('bulkCurrentIndex', nextIndex);
1753                    
1754                    // Открываем следующую кампанию в новой вкладке через window.open
1755                    console.log(`Открываем кампанию ${nextIndex + 1}: ${campaigns[nextIndex]}`);
1756                    const newTab = window.open(campaigns[nextIndex], '_blank');
1757                    
1758                    if (newTab) {
1759                        // Закрываем текущую вкладку
1760                        await wait(1000);
1761                        window.close();
1762                    } else {
1763                        // Если блокировщик всплывающих окон, используем редирект
1764                        console.log('Блокировщик всплывающих окон, используем редирект');
1765                        window.location.href = campaigns[nextIndex];
1766                    }
1767                }
1768            }
1769        }
1770    }
1771
1772    // Функция для остановки массовой обработки
1773    async function stopBulkProcessing() {
1774        await GM.deleteValue('bulkProcessingDRR');
1775        await GM.deleteValue('bulkCampaigns');
1776        await GM.deleteValue('bulkCurrentIndex');
1777        await GM.deleteValue('bulkTotalCampaigns');
1778        
1779        showBulkStatus('⏹️ Обработка остановлена', true);
1780        console.log('Массовая обработка остановлена');
1781        
1782        // Скрываем кнопки управления
1783        const controlButtons = document.getElementById('bulk-control-buttons');
1784        if (controlButtons) {
1785            controlButtons.style.display = 'none';
1786        }
1787        
1788        isBulkProcessing = false;
1789        bulkPaused = false;
1790    }
1791
1792    // Функция для показа статуса
1793    function showStatus(message, isError = false) {
1794        const statusDiv = document.getElementById('status-message');
1795        if (statusDiv) {
1796            statusDiv.textContent = message;
1797            statusDiv.style.display = 'block';
1798            statusDiv.style.background = isError ? 'rgba(255, 59, 48, 0.9)' : 'rgba(52, 199, 89, 0.9)';
1799            console.log(`Статус: ${message}`);
1800        }
1801    }
1802
1803    // Функция для ожидания
1804    function wait(ms) {
1805        return new Promise(resolve => setTimeout(resolve, ms));
1806    }
1807
1808    // Функция для парсинга числа из строки
1809    function parseNumber(str) {
1810        if (!str) return 0;
1811        // Убираем все символы кроме цифр, точек и запятых
1812        const cleaned = str.replace(/[^\d.,]/g, '').replace(/\s/g, '');
1813        // Заменяем запятую на точку
1814        const normalized = cleaned.replace(',', '.');
1815        return parseFloat(normalized) || 0;
1816    }
1817
1818    // Функция для парсинга процента
1819    function parsePercentage(str) {
1820        if (!str) return 0;
1821        const cleaned = str.replace('%', '').replace(',', '.').trim();
1822        return parseFloat(cleaned) || 0;
1823    }
1824
1825    // Основная функция запуска стратегии
1826    async function runStrategy() {
1827        try {
1828            console.log('Начало выполнения стратегии');
1829            showStatus('Запуск процесса...');
1830
1831            const desiredPercentage = parseFloat(document.getElementById('desired-percentage').value);
1832            if (!desiredPercentage || desiredPercentage <= 0) {
1833                showStatus('Ошибка: введите корректный процент', true);
1834                await handleStrategyError();
1835                return;
1836            }
1837            console.log(`Желаемый процент: ${desiredPercentage}%`);
1838
1839            // Проверяем, включен ли чекбокс "Удержание места"
1840            const holdPositionCheckbox = document.getElementById('hold-position');
1841            const shouldApplyHoldPosition = holdPositionCheckbox ? holdPositionCheckbox.checked : false;
1842
1843            // Шаг 1: Кликаем на статистику
1844            showStatus('Открытие статистики...');
1845            const statsButton = document.querySelector('.css-amj7dw');
1846            if (!statsButton) {
1847                showStatus('Ошибка: кнопка статистики не найдена', true);
1848                await handleStrategyError();
1849                return;
1850            }
1851            statsButton.click();
1852            console.log('Клик на статистику выполнен');
1853            await wait(2000);
1854
1855            // Шаг 1.5: Выбираем режим "Товары"
1856            showStatus('Выбор режима "Товары"...');
1857            const modeLabels = Array.from(document.querySelectorAll('label'));
1858            let modeInput = null;
1859            
1860            for (const label of modeLabels) {
1861                if (label.textContent.trim() === 'Режим') {
1862                    const inputId = label.getAttribute('for');
1863                    if (inputId) {
1864                        modeInput = document.getElementById(inputId);
1865                        console.log(`Найдено поле Режим с id: ${inputId}`);
1866                        break;
1867                    }
1868                }
1869            }
1870            
1871            if (modeInput) {
1872                modeInput.value = 'Товары';
1873                const inputEvent = new Event('input', { bubbles: true });
1874                const changeEvent = new Event('change', { bubbles: true });
1875                modeInput.dispatchEvent(inputEvent);
1876                modeInput.dispatchEvent(changeEvent);
1877                
1878                console.log('Установлено значение: Товары');
1879                await wait(1000);
1880                
1881                const options = document.querySelectorAll('[role="option"]');
1882                console.log(`Найдено опций: ${options.length}`);
1883                
1884                if (options.length > 0) {
1885                    const tovarOption = Array.from(options).find(opt => opt.textContent.includes('Товары'));
1886                    if (tovarOption) {
1887                        tovarOption.click();
1888                        console.log('Выбран режим "Товары"');
1889                        await wait(1000);
1890                    }
1891                }
1892            }
1893
1894            // Шаг 2: Извлекаем данные из статистики
1895            showStatus('Извлечение данных...');
1896            await wait(500);
1897            
1898            const stats = Array.from(document.querySelectorAll('.MuiTypography-caption.css-1et52kr'));
1899            
1900            let sumOrders = 0;
1901            let ordersCount = 0;
1902            let cartToOrderPercent = 0;
1903
1904            stats.forEach(el => {
1905                const text = el.textContent.trim();
1906                const valueElement = el.closest('.MuiBox-root')?.querySelector('.MuiTypography-h3 .MuiTypography-body1');
1907                const value = valueElement ? valueElement.textContent.trim() : '';
1908
1909                console.log(`Найден показатель: ${text} = ${value}`);
1910
1911                if (text === 'Сумма заказов') {
1912                    sumOrders = parseNumber(value);
1913                    console.log(`Сумма заказов: ${sumOrders}`);
1914                } else if (text === 'Заказов') {
1915                    ordersCount = parseNumber(value);
1916                    console.log(`Заказов: ${ordersCount}`);
1917                } else if (text === 'Корзина → Заказ') {
1918                    cartToOrderPercent = parsePercentage(value);
1919                    console.log(`Корзина → Заказ: ${cartToOrderPercent}%`);
1920                }
1921            });
1922
1923            if (sumOrders === 0 || ordersCount === 0 || cartToOrderPercent === 0) {
1924                showStatus('Ошибка: не удалось получить данные статистики', true);
1925                console.error('Недостаточно данных:', { sumOrders, ordersCount, cartToOrderPercent });
1926                await handleStrategyError();
1927                return;
1928            }
1929
1930            // Шаг 3: Вычисляем стоимость корзины
1931            const cartCost = (sumOrders / ordersCount) * (desiredPercentage / 100) * (cartToOrderPercent / 100);
1932            const cartCostRounded = Math.round(cartCost * 100) / 100;
1933            console.log(`Расчет: (${sumOrders} / ${ordersCount}) * (${desiredPercentage} / 100) * (${cartToOrderPercent} / 100) = ${cartCostRounded}`);
1934            showStatus(`Рассчитано: ${cartCostRounded}`);
1935
1936            // Закрываем статистику
1937            statsButton.click();
1938            await wait(500);
1939
1940            // Шаг 4: Кликаем на "Вставить стратегию"
1941            showStatus('Вставка стратегии...');
1942            const insertButtons = document.querySelectorAll('.css-5kbhos');
1943            let insertButton = null;
1944            
1945            for (const btn of insertButtons) {
1946                if (btn.textContent.includes('Вставить стратегию')) {
1947                    insertButton = btn;
1948                    break;
1949                }
1950            }
1951
1952            if (!insertButton && insertButtons.length >= 2) {
1953                insertButton = insertButtons[1];
1954            } else if (!insertButton && insertButtons.length === 1) {
1955                insertButton = insertButtons[0];
1956            }
1957
1958            if (!insertButton) {
1959                showStatus('Ошибка: кнопка "Вставить стратегию" не найдена', true);
1960                await handleStrategyError();
1961                return;
1962            }
1963
1964            // Получаем текущую выбранную стратегию
1965            let currentStrategyCode;
1966            if (shouldApplyHoldPosition) {
1967                currentStrategyCode = await getHoldPositionStrategy();
1968                console.log('Используем стратегию удержания места, длина:', currentStrategyCode.length);
1969            } else {
1970                currentStrategyCode = await getCurrentStrategy();
1971                console.log('Используем обычную стратегию, длина:', currentStrategyCode.length);
1972            }
1973            
1974            // Копируем код стратегии в буфер обмена
1975            console.log('Копируем стратегию в буфер обмена...');
1976            
1977            try {
1978                await navigator.clipboard.writeText(currentStrategyCode);
1979                console.log('✓ Стратегия скопирована через navigator.clipboard');
1980            } catch (e) {
1981                console.log('navigator.clipboard не сработал, пробуем GM.setClipboard...');
1982                try {
1983                    await GM.setClipboard(currentStrategyCode);
1984                    console.log('✓ Стратегия скопирована через GM.setClipboard');
1985                } catch (e2) {
1986                    console.error('Ошибка копирования через GM.setClipboard:', e2.message);
1987                }
1988            }
1989            
1990            await wait(500);
1991
1992            insertButton.click();
1993            console.log('Клик на "Вставить стратегию" выполнен');
1994            await wait(500);
1995            
1996            console.log('✓ Стратегия вставлена из буфера обмена');
1997            await wait(500);
1998
1999            // Шаг 5: Находим поле "Желаемое значение" и вставляем результат
2000            showStatus('Заполнение поля...');
2001            
2002            const inputLabels = Array.from(document.querySelectorAll('.MuiInputLabel-root'));
2003            let targetInput = null;
2004
2005            for (const label of inputLabels) {
2006                const labelText = label.textContent;
2007                if (labelText.includes('Желаемое значение За корзину')) {
2008                    const inputId = label.getAttribute('for');
2009                    if (inputId) {
2010                        targetInput = document.getElementById(inputId);
2011                        console.log(`Найдено поле: ${labelText}, id: ${inputId}`);
2012                        break;
2013                    }
2014                }
2015            }
2016
2017            if (!targetInput) {
2018                const inputs = document.querySelectorAll('input[type="number"]');
2019                for (const input of inputs) {
2020                    const name = input.getAttribute('name') || '';
2021                    if (name.includes('rules') && name.includes('value')) {
2022                        targetInput = input;
2023                        console.log(`Найдено поле по имени: ${name}`);
2024                        break;
2025                    }
2026                }
2027            }
2028
2029            if (!targetInput) {
2030                showStatus('Ошибка: поле для ввода не найдено', true);
2031                console.error('Не удалось найти поле для ввода значения');
2032                await handleStrategyError();
2033                return;
2034            }
2035
2036            targetInput.focus();
2037            targetInput.value = cartCostRounded.toString();
2038            
2039            const inputEvent = new Event('input', { bubbles: true });
2040            const changeEvent = new Event('change', { bubbles: true });
2041            targetInput.dispatchEvent(inputEvent);
2042            targetInput.dispatchEvent(changeEvent);
2043            
2044            console.log(`Значение ${cartCostRounded} установлено в поле ${targetInput.id}`);
2045            await wait(500);
2046
2047            // Шаг 6: Нажимаем "Сохранить"
2048            showStatus('Сохранение...');
2049            const saveButtons = document.querySelectorAll('button');
2050            let saveButton = null;
2051
2052            for (const btn of saveButtons) {
2053                if (btn.textContent.trim() === 'Сохранить') {
2054                    saveButton = btn;
2055                    break;
2056                }
2057            }
2058
2059            if (!saveButton) {
2060                showStatus('Ошибка: кнопка "Сохранить" не найдена', true);
2061                await handleStrategyError();
2062                return;
2063            }
2064
2065            saveButton.click();
2066            console.log('Клик на "Сохранить" выполнен');
2067            await wait(500);
2068
2069            showStatus(`✅ Готово! Стоимость корзины: ${cartCostRounded}`);
2070            console.log('Стратегия успешно установлена');
2071
2072            // Шаг 7: Работа с кластерами
2073            const applyToClusters = document.getElementById('apply-to-clusters');
2074            const shouldApplyToClusters = applyToClusters ? applyToClusters.checked : true;
2075            
2076            if (!shouldApplyToClusters) {
2077                console.log('Применение стратегии к кластерам отключено');
2078                showStatus('✅ Готово! Кластеры пропущены');
2079                return;
2080            }
2081
2082            console.log('Применение стратегии к кластерам включено');
2083            
2084            // Переходим во вкладку "Кластеры"
2085            const tabs = Array.from(document.querySelectorAll('button[role="tab"]'));
2086            const clustersTab = tabs.find(tab => tab.textContent.trim() === 'Кластеры');
2087            if (!clustersTab) {
2088                console.error('Вкладка "Кластеры" не найдена');
2089                showStatus('⚠️ Вкладка "Кластеры" не найдена', true);
2090                return;
2091            }
2092
2093            clustersTab.click();
2094            console.log('Клик на "Кластеры" выполнен');
2095            await wait(1000);
2096            
2097            // Ждем загрузки кластеров
2098            let loadingAttempts = 0;
2099            while (loadingAttempts < 10) {
2100                const skeleton = document.querySelector('.MuiSkeleton-root');
2101                if (!skeleton) {
2102                    console.log('Кластеры загружены');
2103                    break;
2104                }
2105                console.log(`Ожидание загрузки кластеров, попытка ${loadingAttempts + 1}`);
2106                await wait(500);
2107                loadingAttempts++;
2108            }
2109            
2110            // СНАЧАЛА применяем обычную стратегию ко ВСЕМ кластерам
2111            showStatus('Применение обычной стратегии ко всем кластерам...');
2112            console.log('Шаг 1: Применяем обычную стратегию ко всем кластерам');
2113            
2114            // Выделяем отфильтрованные кластеры
2115            showStatus('Выделение отфильтрованных кластеров...');
2116            
2117            // Сначала кликаем на первый чекбокс в списке кластеров
2118            const firstClusterCheckbox = document.querySelector('tbody input[type="checkbox"]');
2119            if (firstClusterCheckbox) {
2120                firstClusterCheckbox.click();
2121                console.log('Клик на первый чекбокс кластера выполнен');
2122                await wait(500);
2123            }
2124            
2125            // Теперь кликаем на общий чекбокс для выделения всех
2126            let selectAllCheckbox2 = document.querySelector('.css-1ytbthu .css-vlug8u');
2127            if (!selectAllCheckbox2) {
2128                selectAllCheckbox2 = document.querySelector('thead .css-vlug8u');
2129            }
2130            if (!selectAllCheckbox2) {
2131                const checkboxes2 = document.querySelectorAll('input[type="checkbox"]');
2132                if (checkboxes2.length > 0) {
2133                    selectAllCheckbox2 = checkboxes2[0];
2134                }
2135            }
2136            
2137            if (!selectAllCheckbox2) {
2138                console.error('Checkbox для отфильтрованных кластеров не найден');
2139                return;
2140            }
2141
2142            selectAllCheckbox2.click();
2143            console.log('Клик на checkbox отфильтрованных кластеров выполнен');
2144            await wait(1000);
2145            
2146            // Открываем меню "Действия"
2147            showStatus('Открытие меню действий...');
2148            console.log('Ищем кнопку "Действия"...');
2149            const actionsButton = document.querySelector('.css-1rll63h');
2150            if (!actionsButton) {
2151                console.error('Кнопка "Действия" не найдена');
2152                showStatus('⚠️ Кнопка "Действия" не найдена', true);
2153                return;
2154            }
2155
2156            console.log('Кнопка "Действия" найдена, кликаем...');
2157            actionsButton.click();
2158            console.log('Клик на "Действия" выполнен');
2159            await wait(300);
2160            
2161            // Кликаем на "Управление"
2162            showStatus('Открытие управления...');
2163            console.log('Ищем кнопку "Управление"...');
2164            const managementButtons = document.querySelectorAll('.css-hq58ok');
2165            console.log(`Найдено кнопок управления: ${managementButtons.length}`);
2166            if (managementButtons.length < 2) {
2167                console.error('Кнопка "Управление" не найдена');
2168                showStatus('⚠️ Кнопка "Управление" не найдена', true);
2169                return;
2170            }
2171
2172            console.log('Кликаем на вторую кнопку "Управление"...');
2173            managementButtons[1].click();
2174            console.log('Клик на "Управление" выполнен');
2175            await wait(300);
2176            
2177            // Кликаем на "Стратегия"
2178            showStatus('Открытие стратегии кластеров...');
2179            console.log('Ищем вкладку "Стратегия"...');
2180            const strategyTabs = document.querySelectorAll('.css-582wun');
2181            console.log(`Найдено вкладок стратегии: ${strategyTabs.length}`);
2182            if (strategyTabs.length < 3) {
2183                console.error('Вкладка "Стратегия" не найдена');
2184                showStatus('⚠️ Вкладка "Стратегия" не найдена', true);
2185                return;
2186            }
2187
2188            console.log('Кликаем на третью вкладку "Стратегия"...');
2189            strategyTabs[2].click();
2190            console.log('Клик на "Стратегия" выполнен');
2191            await wait(300);
2192            
2193            // Вставляем ОБЫЧНУЮ стратегию для всех кластеров
2194            showStatus('Вставка обычной стратегии для всех кластеров...');
2195            const clusterInsertButtons = document.querySelectorAll('.css-5kbhos');
2196            let clusterInsertButton = null;
2197            
2198            for (const btn of clusterInsertButtons) {
2199                if (btn.textContent.includes('Вставить стратегию')) {
2200                    clusterInsertButton = btn;
2201                    break;
2202                }
2203            }
2204            
2205            if (!clusterInsertButton && clusterInsertButtons.length > 0) {
2206                clusterInsertButton = clusterInsertButtons[0];
2207            }
2208            
2209            if (!clusterInsertButton) {
2210                console.error('Кнопка "Вставить стратегию" для кластеров не найдена');
2211                showStatus('⚠️ Кнопка вставки стратегии не найдена', true);
2212                return;
2213            }
2214
2215            // Получаем ОБЫЧНУЮ кластерную стратегию
2216            const currentClusterStrategyCode = await getCurrentClusterStrategy();
2217            console.log('Используем обычную кластерную стратегию, длина:', currentClusterStrategyCode.length);
2218            
2219            // Копируем стратегию в буфер обмена
2220            try {
2221                await navigator.clipboard.writeText(currentClusterStrategyCode);
2222                console.log('✓ Обычная кластерная стратегия скопирована');
2223            } catch {
2224                await GM.setClipboard(currentClusterStrategyCode);
2225                console.log('✓ Обычная кластерная стратегия скопирована через GM');
2226            }
2227            
2228            await wait(500);
2229            
2230            clusterInsertButton.click();
2231            console.log('Клик на "Вставить стратегию" для всех кластеров выполнен');
2232            await wait(1000);
2233            
2234            // Находим поле для ввода ставки
2235            const clusterInputLabels = Array.from(document.querySelectorAll('.MuiInputLabel-root'));
2236            let clusterTargetInput = null;
2237            
2238            for (const label of clusterInputLabels) {
2239                const labelText = label.textContent.trim();
2240                if (labelText.includes('Желаемое значение За корзину')) {
2241                    const inputId = label.getAttribute('for');
2242                    if (inputId) {
2243                        clusterTargetInput = document.getElementById(inputId);
2244                        console.log(`Найдено поле для кластеров: ${labelText}`);
2245                        break;
2246                    }
2247                }
2248            }
2249
2250            if (!clusterTargetInput) {
2251                const clusterInputs = document.querySelectorAll('input[type="number"]');
2252                for (const input of clusterInputs) {
2253                    const name = input.getAttribute('name') || '';
2254                    if (name.includes('CostPerAddedToCart') || name.includes('value')) {
2255                        clusterTargetInput = input;
2256                        console.log(`Найдено поле по имени: ${name}`);
2257                        break;
2258                    }
2259                }
2260            }
2261            
2262            if (clusterTargetInput) {
2263                clusterTargetInput.focus();
2264                clusterTargetInput.value = cartCostRounded.toString();
2265                clusterTargetInput.dispatchEvent(new Event('input', { bubbles: true }));
2266                clusterTargetInput.dispatchEvent(new Event('change', { bubbles: true }));
2267                console.log(`Значение ${cartCostRounded} установлено для всех кластеров`);
2268                await wait(500);
2269            }
2270            
2271            // Нажимаем "Применить"
2272            showStatus('Применение обычной стратегии ко всем кластерам...');
2273            const clusterStrategyApplyButtons = document.querySelectorAll('.css-eqlbov');
2274            if (clusterStrategyApplyButtons.length < 2) {
2275                console.error('Кнопка "Применить" не найдена');
2276                showStatus('⚠️ Кнопка "Применить" не найдена', true);
2277                return;
2278            }
2279
2280            clusterStrategyApplyButtons[1].click();
2281            console.log('Клик на "Применить" обычную стратегию выполнен');
2282            await wait(1000);
2283            
2284            // Закрываем модальное окно
2285            const closeModalButtons = document.querySelectorAll('button[aria-label="Close"]');
2286            if (closeModalButtons.length > 0) {
2287                closeModalButtons[closeModalButtons.length - 1].click();
2288                console.log('Модальное окно закрыто');
2289                await wait(1000);
2290            }
2291            
2292            // Снимаем выделение со всех кластеров
2293            console.log('Снимаем выделение со всех кластеров');
2294            let deselectAllCheckbox = document.querySelector('.css-1ytbthu .css-vlug8u');
2295            if (!deselectAllCheckbox) {
2296                deselectAllCheckbox = document.querySelector('thead .css-vlug8u');
2297            }
2298            if (!deselectAllCheckbox) {
2299                const checkboxes = document.querySelectorAll('input[type="checkbox"]');
2300                if (checkboxes.length > 0) {
2301                    deselectAllCheckbox = checkboxes[0];
2302                }
2303            }
2304            
2305            if (deselectAllCheckbox) {
2306                deselectAllCheckbox.click();
2307                console.log('Клик на checkbox для снятия выделения выполнен');
2308                await wait(1000);
2309            }
2310            
2311            // ТЕПЕРЬ, если включен чекбокс "Удержание места", применяем фильтры
2312            if (shouldApplyHoldPosition) {
2313                console.log('Шаг 2: Применяем фильтры и стратегию удержания места');
2314                await applyHoldPositionToFilteredClusters(cartCostRounded);
2315            }
2316            
2317            // Работаем с автофильтрами
2318            await applyAutofilters();
2319
2320            showStatus(`✅ Полностью готово! Стоимость корзины: ${cartCostRounded}`);
2321
2322            // Проверяем, идет ли массовая обработка
2323            const savedDRR = await GM.getValue('bulkProcessingDRR', null);
2324            if (savedDRR !== null) {
2325                console.log('Массовая обработка: переход к следующей кампании');
2326                await wait(2000);
2327                
2328                const campaignsJson = await GM.getValue('bulkCampaigns', null);
2329                const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
2330                const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
2331                
2332                if (campaignsJson) {
2333                    const campaigns = JSON.parse(campaignsJson);
2334                    const nextIndex = currentIndex + 1;
2335                    
2336                    console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
2337                    
2338                    if (nextIndex < campaigns.length) {
2339                        await GM.setValue('bulkCurrentIndex', nextIndex);
2340                        console.log(`Открываем кампанию ${nextIndex + 1}: ${campaigns[nextIndex]}`);
2341                        const newTab = window.open(campaigns[nextIndex], '_blank');
2342                        
2343                        if (newTab) {
2344                            await wait(1000);
2345                            window.close();
2346                        } else {
2347                            console.log('Блокировщик всплывающих окон, используем редирект');
2348                            window.location.href = campaigns[nextIndex];
2349                        }
2350                    } else {
2351                        console.log('Все кампании обработаны');
2352                        await GM.deleteValue('bulkProcessingDRR');
2353                        await GM.deleteValue('bulkCampaigns');
2354                        await GM.deleteValue('bulkCurrentIndex');
2355                        await GM.deleteValue('bulkTotalCampaigns');
2356                        
2357                        showStatus('✅ Все кампании обработаны! Закрытие вкладки...');
2358                        await wait(2000);
2359                        window.close();
2360                    }
2361                }
2362            }
2363
2364        } catch (error) {
2365            console.error('Ошибка при выполнении стратегии:', error);
2366            showStatus(`Ошибка: ${error.message}`, true);
2367            await handleStrategyError();
2368        }
2369    }
2370
2371    // Функция для применения стратегии удержания места к отфильтрованным кластерам
2372    async function applyHoldPositionToFilteredClusters(cartCostRounded) {
2373        showStatus('Настройка фильтра "Удержание места"...');
2374        await wait(1500);
2375        
2376        // Выбираем дату "За 7 дней"
2377        showStatus('Выбор даты "За 7 дней"...');
2378        const jt7z00Elements = document.querySelectorAll('.css-jt7z00');
2379        
2380        if (jt7z00Elements.length >= 6) {
2381            const clusterIntervalInput = jt7z00Elements[5];
2382            Object.defineProperty(clusterIntervalInput, 'readOnly', { value: false, writable: true });
2383            clusterIntervalInput.focus();
2384            clusterIntervalInput.dispatchEvent(new Event('focusin', { bubbles: true }));
2385            clusterIntervalInput.click();
2386            
2387            await wait(2000);
2388            
2389            const dateButtons = document.querySelectorAll('.css-ghy8jd');
2390            if (dateButtons.length >= 2) {
2391                dateButtons[1].click();
2392                console.log('Клик на "За 7 дней" выполнен');
2393                await wait(1000);
2394                
2395                const applyDateButtons = document.querySelectorAll('.css-7wa720');
2396                if (applyDateButtons.length > 0) {
2397                    applyDateButtons[0].click();
2398                    console.log('Клик на "Применить" дату выполнен');
2399                    await wait(1500);
2400                }
2401            }
2402        }
2403        
2404        // Открываем фильтры
2405        const filtersButton = document.querySelector('.css-a54mx2');
2406        if (!filtersButton) {
2407            console.error('Кнопка "Фильтры" не найдена');
2408            return;
2409        }
2410
2411        filtersButton.click();
2412        console.log('Клик на "Фильтры" выполнен');
2413        await wait(1500);
2414        
2415        // Добавляем фильтр
2416        const addFilterButtons = document.querySelectorAll('.css-8h18y2');
2417        if (addFilterButtons.length < 2) {
2418            console.error('Кнопка "Добавить фильтр" не найдена');
2419            return;
2420        }
2421
2422        addFilterButtons[1].click();
2423        console.log('Клик на "Добавить фильтр" выполнен');
2424        await wait(1500);
2425        
2426        // Выбираем "Среднее место в выдаче"
2427        const filterOptions = document.querySelectorAll('.css-1ytbthu');
2428        if (filterOptions.length < 6) {
2429            console.error('Опция "Среднее место в выдаче" не найдена');
2430            return;
2431        }
2432
2433        filterOptions[5].click();
2434        console.log('Клик на "Среднее место в выдаче" выполнен');
2435        await wait(1500);
2436        
2437        // Очищаем фильтр
2438        const allInputsWithVse = document.querySelectorAll('input[value="Все"]');
2439        let avgPositionInput = allInputsWithVse.length >= 2 ? allInputsWithVse[1] : allInputsWithVse[0];
2440        
2441        if (!avgPositionInput) {
2442            console.error('Input "Среднее место в выдаче" не найден');
2443            return;
2444        }
2445
2446        const inputContainer = avgPositionInput.closest('.MuiInputBase-root');
2447        const clearButton = inputContainer?.querySelector('button');
2448        
2449        if (!clearButton) {
2450            console.error('Кнопка очистки не найдена');
2451            return;
2452        }
2453
2454        clearButton.click();
2455        console.log('Клик на кнопку очистки выполнен');
2456        await wait(1500);
2457        
2458        // Выбираем "Между"
2459        const hiddenInputsForComparison = document.querySelectorAll('input.MuiSelect-nativeInput');
2460        let comparisonContainer = null;
2461        
2462        for (const inp of hiddenInputsForComparison) {
2463            const container = inp.closest('.MuiFormControl-root');
2464            const label = container?.querySelector('label');
2465            if (label && label.textContent.includes('Сравнение')) {
2466                comparisonContainer = container;
2467                break;
2468            }
2469        }
2470        
2471        if (!comparisonContainer) {
2472            console.error('Контейнер "Сравнение" не найден');
2473            return;
2474        }
2475
2476        const arrowButton = comparisonContainer.querySelector('button');
2477        if (!arrowButton) {
2478            console.error('Кнопка со стрелкой не найдена');
2479            return;
2480        }
2481
2482        arrowButton.click();
2483        console.log('Клик на кнопку со стрелкой выполнен');
2484        await wait(1000);
2485        
2486        // Выбираем "Между"
2487        const options = document.querySelectorAll('[role="option"]');
2488        const betweenOption = Array.from(options).find(opt => opt.textContent.trim() === 'Между');
2489        
2490        if (!betweenOption) {
2491            console.error('Опция "Между" не найдена');
2492            return;
2493        }
2494
2495        betweenOption.click();
2496        console.log('Клик на "Между" выполнен');
2497        await wait(1500);
2498        
2499        // Устанавливаем значения "от" и "до"
2500        const allLabels = document.querySelectorAll('label');
2501        let fromInput = null;
2502        let toInput = null;
2503        
2504        for (const label of allLabels) {
2505            const text = label.textContent.trim();
2506            if (text === 'Значение от') {
2507                const inputId = label.getAttribute('for');
2508                if (inputId) {
2509                    fromInput = document.getElementById(inputId);
2510                }
2511            } else if (text === 'Значение до') {
2512                const inputId = label.getAttribute('for');
2513                if (inputId) {
2514                    toInput = document.getElementById(inputId);
2515                }
2516            }
2517        }
2518        
2519        if (!fromInput || !toInput) {
2520            console.error('Поля "от" и "до" не найдены');
2521            return;
2522        }
2523
2524        // Устанавливаем "от" = 1
2525        fromInput.focus();
2526        fromInput.value = '1';
2527        fromInput.dispatchEvent(new Event('input', { bubbles: true }));
2528        fromInput.dispatchEvent(new Event('change', { bubbles: true }));
2529        console.log('Установлено значение "от" = 1');
2530        await wait(500);
2531        
2532        // Устанавливаем "до" = 4
2533        toInput.focus();
2534        toInput.value = '4';
2535        toInput.dispatchEvent(new Event('input', { bubbles: true }));
2536        toInput.dispatchEvent(new Event('change', { bubbles: true }));
2537        console.log('Установлено значение "до" = 4');
2538        await wait(1000);
2539        
2540        // Выделяем отфильтрованные кластеры
2541        showStatus('Выделение отфильтрованных кластеров...');
2542        
2543        // Сначала кликаем на первый чекбокс в списке кластеров
2544        const firstClusterCheckbox = document.querySelector('tbody input[type="checkbox"]');
2545        if (firstClusterCheckbox) {
2546            firstClusterCheckbox.click();
2547            console.log('Клик на первый чекбокс кластера выполнен');
2548            await wait(500);
2549        }
2550        
2551        // Теперь кликаем на общий чекбокс для выделения всех
2552        let selectAllCheckbox2 = document.querySelector('.css-1ytbthu .css-vlug8u');
2553        if (!selectAllCheckbox2) {
2554            selectAllCheckbox2 = document.querySelector('thead .css-vlug8u');
2555        }
2556        if (!selectAllCheckbox2) {
2557            const checkboxes2 = document.querySelectorAll('input[type="checkbox"]');
2558            if (checkboxes2.length > 0) {
2559                selectAllCheckbox2 = checkboxes2[0];
2560            }
2561        }
2562        
2563        if (!selectAllCheckbox2) {
2564            console.error('Checkbox для отфильтрованных кластеров не найден');
2565            return;
2566        }
2567
2568        selectAllCheckbox2.click();
2569        console.log('Клик на checkbox отфильтрованных кластеров выполнен');
2570        await wait(1000);
2571        
2572        // Открываем меню "Действия"
2573        showStatus('Открытие меню действий для отфильтрованных кластеров...');
2574        const actionsButton2 = document.querySelector('.css-1rll63h');
2575        if (!actionsButton2) {
2576            console.error('Кнопка "Действия" не найдена');
2577            return;
2578        }
2579
2580        actionsButton2.click();
2581        await wait(300);
2582        
2583        // Кликаем на "Управление"
2584        const managementButtons2 = document.querySelectorAll('.css-hq58ok');
2585        if (managementButtons2.length < 2) {
2586            console.error('Кнопка "Управление" не найдена');
2587            return;
2588        }
2589
2590        managementButtons2[1].click();
2591        await wait(300);
2592        
2593        // Кликаем на "Стратегия"
2594        const strategyTabs2 = document.querySelectorAll('.css-582wun');
2595        if (strategyTabs2.length < 3) {
2596            console.error('Вкладка "Стратегия" не найдена');
2597            return;
2598        }
2599
2600        strategyTabs2[2].click();
2601        await wait(300);
2602        
2603        // Вставляем стратегию УДЕРЖАНИЯ МЕСТА
2604        showStatus('Вставка стратегии удержания места...');
2605        const clusterInsertButtons2 = document.querySelectorAll('.css-5kbhos');
2606        let clusterInsertButton2 = null;
2607        
2608        for (const btn of clusterInsertButtons2) {
2609            if (btn.textContent.includes('Вставить стратегию')) {
2610                clusterInsertButton2 = btn;
2611                break;
2612            }
2613        }
2614        
2615        if (!clusterInsertButton2 && clusterInsertButtons2.length > 0) {
2616            clusterInsertButton2 = clusterInsertButtons2[0];
2617        }
2618        
2619        if (!clusterInsertButton2) {
2620            console.error('Кнопка "Вставить стратегию" для отфильтрованных кластеров не найдена');
2621            return;
2622        }
2623
2624        // Получаем стратегию УДЕРЖАНИЯ МЕСТА
2625        const holdPositionClusterStrategyCode = await getHoldPositionClusterStrategy();
2626        console.log('Используем стратегию удержания места, длина:', holdPositionClusterStrategyCode.length);
2627        
2628        try {
2629            await navigator.clipboard.writeText(holdPositionClusterStrategyCode);
2630            console.log('✓ Стратегия удержания места скопирована');
2631        } catch {
2632            await GM.setClipboard(holdPositionClusterStrategyCode);
2633            console.log('✓ Стратегия удержания места скопирована через GM');
2634        }
2635        
2636        await wait(500);
2637        
2638        clusterInsertButton2.click();
2639        console.log('Клик на "Вставить стратегию" удержания места выполнен');
2640        await wait(1000);
2641        
2642        // Находим поле для ввода ставки
2643        const clusterInputLabels2 = Array.from(document.querySelectorAll('.MuiInputLabel-root'));
2644        let clusterTargetInput2 = null;
2645        
2646        for (const label of clusterInputLabels2) {
2647            const labelText = label.textContent.trim();
2648            if (labelText.includes('Желаемое значение За корзину')) {
2649                const inputId = label.getAttribute('for');
2650                if (inputId) {
2651                    clusterTargetInput2 = document.getElementById(inputId);
2652                    break;
2653                }
2654            }
2655        }
2656
2657        if (!clusterTargetInput2) {
2658            const clusterInputs2 = document.querySelectorAll('input[type="number"]');
2659            for (const input of clusterInputs2) {
2660                const name = input.getAttribute('name') || '';
2661                if (name.includes('CostPerAddedToCart') || name.includes('value')) {
2662                    clusterTargetInput2 = input;
2663                    break;
2664                }
2665            }
2666        }
2667        
2668        if (clusterTargetInput2) {
2669            clusterTargetInput2.focus();
2670            clusterTargetInput2.value = cartCostRounded.toString();
2671            clusterTargetInput2.dispatchEvent(new Event('input', { bubbles: true }));
2672            clusterTargetInput2.dispatchEvent(new Event('change', { bubbles: true }));
2673            console.log(`Значение ${cartCostRounded} установлено для отфильтрованных кластеров`);
2674            await wait(500);
2675        }
2676        
2677        // Нажимаем "Применить"
2678        showStatus('Применение стратегии удержания места...');
2679        const clusterStrategyApplyButtons2 = document.querySelectorAll('.css-eqlbov');
2680        if (clusterStrategyApplyButtons2.length >= 2) {
2681            clusterStrategyApplyButtons2[1].click();
2682            console.log('Клик на "Применить" стратегию удержания места выполнен');
2683            await wait(1000);
2684            
2685            // Закрываем модальное окно
2686            const closeModalButtons2 = document.querySelectorAll('button[aria-label="Close"]');
2687            if (closeModalButtons2.length > 0) {
2688                closeModalButtons2[closeModalButtons2.length - 1].click();
2689                console.log('Модальное окно закрыто');
2690                await wait(1000);
2691            }
2692        }
2693    }
2694
2695    // Функция для применения автофильтров
2696    async function applyAutofilters() {
2697        showStatus('Открытие автофильтров...');
2698        
2699        const autofilterAccordion = document.getElementById('bidder-constructor');
2700        if (!autofilterAccordion) {
2701            console.error('Аккордеон "Автофильтры" не найден');
2702            return;
2703        }
2704
2705        const accordionButton = autofilterAccordion.querySelector('button[aria-expanded]');
2706        const isExpanded = accordionButton && accordionButton.getAttribute('aria-expanded') === 'true';
2707        
2708        if (!isExpanded && accordionButton) {
2709            accordionButton.click();
2710            console.log('Аккордеон "Автофильтры" раскрыт');
2711            await wait(1000);
2712        }
2713        
2714        // Кликаем на "Шаблоны"
2715        showStatus('Открытие шаблонов...');
2716        const templatesButtons = autofilterAccordion.querySelectorAll('button');
2717        let templateButton = null;
2718        
2719        for (const btn of templatesButtons) {
2720            if (btn.textContent.trim() === 'Шаблоны') {
2721                templateButton = btn;
2722                break;
2723            }
2724        }
2725        
2726        if (!templateButton) {
2727            console.error('Кнопка "Шаблоны" не найдена');
2728            return;
2729        }
2730
2731        templateButton.click();
2732        console.log('Кнопка "Шаблоны" выбрана');
2733        await wait(500);
2734        
2735        // Выбираем "Расширение"
2736        showStatus('Выбор шаблона "Расширение"...');
2737        const allElements = document.querySelectorAll('div, button, span, p');
2738        let extensionTemplate = null;
2739        
2740        for (const el of allElements) {
2741            const text = el.textContent.trim();
2742            if (text === 'Расширение') {
2743                extensionTemplate = el;
2744                break;
2745            }
2746        }
2747        
2748        if (!extensionTemplate) {
2749            console.error('Шаблон "Расширение" не найден');
2750            return;
2751        }
2752
2753        extensionTemplate.click();
2754        console.log('Шаблон "Расширение" выбран');
2755        await wait(500);
2756        
2757        // Сохраняем
2758        showStatus('Сохранение автофильтров...');
2759        const saveButtonsAfterTemplate = document.querySelectorAll('button');
2760        let saveAutofilterButton = null;
2761        
2762        for (const btn of saveButtonsAfterTemplate) {
2763            if (btn.textContent.trim() === 'Сохранить') {
2764                saveAutofilterButton = btn;
2765                break;
2766            }
2767        }
2768        
2769        if (!saveAutofilterButton) {
2770            console.error('Кнопка "Сохранить" не найдена');
2771            return;
2772        }
2773
2774        saveAutofilterButton.click();
2775        console.log('Клик на "Сохранить" автофильтры выполнен');
2776        await wait(1000);
2777        
2778        // Применяем автофильтры вручную
2779        showStatus('Применение автофильтров вручную...');
2780        const applyButtonsAfterSave = document.querySelectorAll('button');
2781        let applyAutofilterButton = null;
2782        
2783        for (const btn of applyButtonsAfterSave) {
2784            if (btn.textContent.trim() === 'Применить автофильтры вручную') {
2785                applyAutofilterButton = btn;
2786                break;
2787            }
2788        }
2789        
2790        if (!applyAutofilterButton) {
2791            console.error('Кнопка "Применить автофильтры вручную" не найдена');
2792            return;
2793        }
2794
2795        applyAutofilterButton.click();
2796        console.log('Клик на "Применить автофильтры вручную" выполнен');
2797        await wait(1000);
2798    }
2799
2800    // Функция для обработки ошибок и перехода к следующей кампании
2801    async function handleStrategyError() {
2802        const savedDRR = await GM.getValue('bulkProcessingDRR', null);
2803        if (savedDRR !== null) {
2804            console.log('Обнаружена ошибка при массовой обработке, ждем 10 секунд');
2805            showStatus('⚠️ Ошибка! Переход к следующей кампании через 10 секунд...', true);
2806            
2807            for (let i = 10; i > 0; i--) {
2808                showStatus(`⚠️ Ошибка! Переход к следующей через ${i} сек...`, true);
2809                await wait(1000);
2810            }
2811            
2812            const campaignsJson = await GM.getValue('bulkCampaigns', null);
2813            const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
2814            const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
2815            
2816            if (campaignsJson) {
2817                const campaigns = JSON.parse(campaignsJson);
2818                const nextIndex = currentIndex + 1;
2819                
2820                console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
2821                
2822                if (nextIndex < campaigns.length) {
2823                    await GM.setValue('bulkCurrentIndex', nextIndex);
2824                    console.log(`Открываем кампанию ${nextIndex + 1}: ${campaigns[nextIndex]}`);
2825                    const newTab = window.open(campaigns[nextIndex], '_blank');
2826                    
2827                    if (newTab) {
2828                        await wait(1000);
2829                        window.close();
2830                    } else {
2831                        console.log('Блокировщик всплывающих окон, используем редирект');
2832                        window.location.href = campaigns[nextIndex];
2833                    }
2834                } else {
2835                    console.log('Все кампании обработаны');
2836                    await GM.deleteValue('bulkProcessingDRR');
2837                    await GM.deleteValue('bulkCampaigns');
2838                    await GM.deleteValue('bulkCurrentIndex');
2839                    await GM.deleteValue('bulkTotalCampaigns');
2840                    
2841                    showStatus('✅ Все кампании обработаны! Закрытие вкладки...');
2842                    await wait(2000);
2843                    window.close();
2844                }
2845            }
2846        }
2847    }
2848
2849    // Инициализация
2850    function init() {
2851        console.log('Инициализация расширения');
2852        
2853        if (window.location.href.includes('/advert/campaigns')) {
2854            console.log('Страница списка кампаний обнаружена');
2855            setTimeout(() => {
2856                if (document.body) {
2857                    createBulkUI();
2858                } else {
2859                    console.error('Body не найден');
2860                }
2861            }, 1000);
2862        } else if (window.location.href.includes('/campaigns/auto-campaigns/') && window.location.href.includes('/campaign')) {
2863            console.log('Страница кампании обнаружена');
2864            setTimeout(() => {
2865                if (document.body) {
2866                    createUI();
2867                } else {
2868                    console.error('Body не найден');
2869                }
2870            }, 1000);
2871        } else {
2872            console.log('Не на странице кампании, UI не создается');
2873        }
2874    }
2875
2876    // Запускаем инициализацию
2877    init();
2878
2879})();