MP Manager WB Cluster Auto Strategy Setter

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

Size

144.3 KB

Version

1.8.139

Created

Mar 18, 2026

Updated

29 days ago

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