MP Manager Cluster Auto Strategy Setter

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

Size

109.3 KB

Version

1.8.118

Created

Feb 13, 2026

Updated

about 1 month ago

1// ==UserScript==
2// @name		MP Manager Cluster Auto Strategy Setter
3// @description		Автоматическая установка стратегии рекламной кампании на основе статистики
4// @version		1.8.118
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 = 'eyJjYW1wYWlnblR5cGUiOiJTZWFyY2hDYXRhbG9nIiwidmVyc2lvbiI6MiwiZGF0YSI6eyJzdGF0ZSI6IkVuYWJsZWQiLCJtb2RlIjp7InR5cGUiOiJQb3NpdGlvbiIsInBhdXNlVHlwZSI6IlJlc3VtZSJ9LCJzdHJhdGVneSI6eyJ0eXBlIjoiQ2FtcGFpZ25TdGF0cyIsIm1vZGUiOiJQbGFjZSIsImJpZE1vZGUiOiJDb3N0UGVyQ2xpY2siLCJjbHVzdGVyU3RhdHMiOnsibWF4QmlkIjo4MDAwLCJtaW5CaWQiOjQwMCwiaW50ZXJ2YWwiOiJUaHJlZURheXMiLCJydWxlcyI6W3sidHlwZSI6IkF2ZXJhZ2VQb3NpdGlvbiIsIm1vZGUiOiJWYWx1ZSIsInZhbHVlIjoyfSx7InR5cGUiOiJDb3N0UGVyQWRkZWRUb0NhcnQiLCJtb2RlIjoiQXZlcmFnZVZhbHVlIn1dfSwicGxhY2VTdHJhdGVneSI6eyJ0eXBlIjoiS2V5d29yZHMiLCJrZXl3b3JkcyI6eyJrZXl3b3JkcyI6W119fSwiaXNDbHVzdGVyIjp0cnVlfX0=';
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(() => {
1007                    const input = document.getElementById('desired-percentage');
1008                    if (input) {
1009                        input.value = savedDRR;
1010                        // Запускаем стратегию автоматически
1011                        runStrategy();
1012                    }
1013                }, 2000);
1014            }
1015        });
1016        
1017        const panel = document.createElement('div');
1018        panel.id = 'auto-strategy-panel';
1019        panel.style.cssText = `
1020            position: fixed;
1021            top: 20px;
1022            right: 20px;
1023            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1024            padding: 15px;
1025            border-radius: 12px;
1026            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
1027            z-index: 10000;
1028            min-width: 280px;
1029            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1030            color: white;
1031            transition: all 0.3s ease;
1032            cursor: move;
1033        `;
1034
1035        panel.innerHTML = `
1036            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; cursor: pointer;" id="panel-header">
1037                <h3 style="margin: 0; font-size: 16px; font-weight: 600;">🚀 Авто-стратегия</h3>
1038                <span id="toggle-icon" style="font-size: 18px;"></span>
1039            </div>
1040            
1041            <div id="panel-content" style="display: none;">
1042                <div style="margin-bottom: 15px;">
1043                    <label style="display: block; margin-bottom: 8px; font-size: 13px; font-weight: 500;">
1044                        Желаемый % рекламных расходов:
1045                    </label>
1046                    <input 
1047                        type="number" 
1048                        id="desired-percentage" 
1049                        value="30" 
1050                        min="1" 
1051                        max="100" 
1052                        step="0.1"
1053                        style="
1054                            width: 100%;
1055                            padding: 10px;
1056                            border: none;
1057                            border-radius: 8px;
1058                            font-size: 14px;
1059                            box-sizing: border-box;
1060                            background: rgba(255, 255, 255, 0.95);
1061                            color: #333;
1062                            cursor: text;
1063                        "
1064                    />
1065                </div>
1066
1067                <div style="margin-bottom: 15px;">
1068                    <label style="display: flex; align-items: center; cursor: pointer; font-size: 13px; font-weight: 500;">
1069                        <input 
1070                            type="checkbox" 
1071                            id="apply-to-clusters" 
1072                            checked
1073                            style="
1074                                margin-right: 8px;
1075                                width: 18px;
1076                                height: 18px;
1077                                cursor: pointer;
1078                            "
1079                        />
1080                        Применить стратегию к кластерам
1081                    </label>
1082                </div>
1083
1084                <div style="margin-bottom: 15px;">
1085                    <label style="display: flex; align-items: center; cursor: pointer; font-size: 13px; font-weight: 500;">
1086                        <input 
1087                            type="checkbox" 
1088                            id="hold-position" 
1089                            checked
1090                            style="
1091                                margin-right: 8px;
1092                                width: 18px;
1093                                height: 18px;
1094                                cursor: pointer;
1095                            "
1096                        />
1097                        Удержание места
1098                    </label>
1099                </div>
1100
1101                <button 
1102                    id="run-strategy-btn"
1103                    style="
1104                        width: 100%;
1105                        padding: 12px;
1106                        background: white;
1107                        color: #667eea;
1108                        border: none;
1109                        border-radius: 8px;
1110                        font-size: 14px;
1111                        font-weight: 600;
1112                        cursor: pointer;
1113                        transition: all 0.3s ease;
1114                        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1115                        margin-bottom: 10px;
1116                    "
1117                    onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 6px 16px rgba(0, 0, 0, 0.2)';"
1118                    onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 4px 12px rgba(0, 0, 0, 0.15)';"
1119                >
1120                    Запустить
1121                </button>
1122
1123                <button 
1124                    id="manage-strategies-btn"
1125                    style="
1126                        width: 100%;
1127                        padding: 10px;
1128                        background: rgba(255, 255, 255, 0.2);
1129                        color: white;
1130                        border: 1px solid rgba(255, 255, 255, 0.3);
1131                        border-radius: 8px;
1132                        font-size: 13px;
1133                        font-weight: 600;
1134                        cursor: pointer;
1135                        transition: all 0.3s ease;
1136                        margin-bottom: 8px;
1137                    "
1138                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1139                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1140                >
1141                    ⚙️ Управление стратегиями
1142                </button>
1143
1144                <button 
1145                    id="manage-cluster-strategies-btn"
1146                    style="
1147                        width: 100%;
1148                        padding: 10px;
1149                        background: rgba(255, 255, 255, 0.2);
1150                        color: white;
1151                        border: 1px solid rgba(255, 255, 255, 0.3);
1152                        border-radius: 8px;
1153                        font-size: 13px;
1154                        font-weight: 600;
1155                        cursor: pointer;
1156                        transition: all 0.3s ease;
1157                        margin-bottom: 8px;
1158                    "
1159                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1160                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1161                >
1162                    🎯 Стратегии для кластеров
1163                </button>
1164
1165                <button 
1166                    id="manage-hold-position-strategies-btn"
1167                    style="
1168                        width: 100%;
1169                        padding: 10px;
1170                        background: rgba(255, 255, 255, 0.2);
1171                        color: white;
1172                        border: 1px solid rgba(255, 255, 255, 0.3);
1173                        border-radius: 8px;
1174                        font-size: 13px;
1175                        font-weight: 600;
1176                        cursor: pointer;
1177                        transition: all 0.3s ease;
1178                    "
1179                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1180                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1181                >
1182                    📍 Стратегии удержания места
1183                </button>
1184
1185                <div id="status-message" style="
1186                    margin-top: 15px;
1187                    padding: 10px;
1188                    border-radius: 8px;
1189                    font-size: 12px;
1190                    background: rgba(255, 255, 255, 0.2);
1191                    display: none;
1192                "></div>
1193            </div>
1194        `;
1195
1196        document.body.appendChild(panel);
1197        console.log('UI панель создана');
1198
1199        // Добавляем возможность перетаскивания
1200        makeDraggable(panel);
1201
1202        // Добавляем обработчик клика на заголовок для разворачивания/сворачивания
1203        document.getElementById('panel-header').addEventListener('click', () => {
1204            const content = document.getElementById('panel-content');
1205            const icon = document.getElementById('toggle-icon');
1206            if (content.style.display === 'none') {
1207                content.style.display = 'block';
1208                icon.textContent = '▲';
1209            } else {
1210                content.style.display = 'none';
1211                icon.textContent = '▼';
1212            }
1213        });
1214
1215        // Добавляем обработчик клика на кнопку
1216        document.getElementById('run-strategy-btn').addEventListener('click', runStrategy);
1217        
1218        // Добавляем обработчик для кнопки управления стратегиями
1219        document.getElementById('manage-strategies-btn').addEventListener('click', async () => {
1220            await createStrategyManagementModal();
1221        });
1222        
1223        // Добавляем обработчик для кнопки управления кластерными стратегиями
1224        document.getElementById('manage-cluster-strategies-btn').addEventListener('click', async () => {
1225            await createClusterStrategyManagementModal();
1226        });
1227        
1228        // Добавляем обработчик для кнопки управления стратегиями удержания места
1229        document.getElementById('manage-hold-position-strategies-btn').addEventListener('click', async () => {
1230            await createHoldPositionStrategyManagementModal();
1231        });
1232    }
1233
1234    // Функция для создания UI панели массового изменения
1235    function createBulkUI() {
1236        console.log('Создание UI панели массового изменения');
1237        
1238        const panel = document.createElement('div');
1239        panel.id = 'bulk-strategy-panel';
1240        panel.style.cssText = `
1241            position: fixed;
1242            top: 20px;
1243            right: 20px;
1244            background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
1245            padding: 15px;
1246            border-radius: 12px;
1247            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
1248            z-index: 10000;
1249            min-width: 300px;
1250            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1251            color: white;
1252            transition: all 0.3s ease;
1253            cursor: move;
1254        `;
1255
1256        panel.innerHTML = `
1257            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; cursor: pointer;" id="bulk-panel-header">
1258                <h3 style="margin: 0; font-size: 16px; font-weight: 600;">📦 Массовое изменение</h3>
1259                <span id="bulk-toggle-icon" style="font-size: 18px;"></span>
1260            </div>
1261            
1262            <div id="bulk-panel-content" style="display: none;">
1263                <div style="margin-bottom: 15px;">
1264                    <label style="display: block; margin-bottom: 8px; font-size: 13px; font-weight: 500;">
1265                        Желаемый % рекламных расходов (ДРР):
1266                    </label>
1267                    <input 
1268                        type="number" 
1269                        id="bulk-desired-percentage" 
1270                        value="30" 
1271                        min="1" 
1272                        max="100" 
1273                        step="0.1"
1274                        style="
1275                            width: 100%;
1276                            padding: 10px;
1277                            border: none;
1278                            border-radius: 8px;
1279                            font-size: 14px;
1280                            box-sizing: border-box;
1281                            background: rgba(255, 255, 255, 0.95);
1282                            color: #333;
1283                            cursor: text;
1284                        "
1285                    />
1286                </div>
1287
1288                <div id="bulk-campaigns-info" style="
1289                    margin-bottom: 15px;
1290                    padding: 10px;
1291                    border-radius: 8px;
1292                    font-size: 12px;
1293                    background: rgba(255, 255, 255, 0.2);
1294                ">
1295                    Найдено кампаний: <span id="campaigns-count">0</span>
1296                </div>
1297
1298                <button 
1299                    id="run-bulk-strategy-btn"
1300                    style="
1301                        width: 100%;
1302                        padding: 12px;
1303                        background: white;
1304                        color: #f5576c;
1305                        border: none;
1306                        border-radius: 8px;
1307                        font-size: 14px;
1308                        font-weight: 600;
1309                        cursor: pointer;
1310                        transition: all 0.3s ease;
1311                        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1312                        margin-bottom: 10px;
1313                    "
1314                    onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 6px 16px rgba(0, 0, 0, 0.2)';"
1315                    onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 4px 12px rgba(0, 0, 0, 0.15)';"
1316                >
1317                    Запустить
1318                </button>
1319
1320                <button 
1321                    id="bulk-manage-strategies-btn"
1322                    style="
1323                        width: 100%;
1324                        padding: 10px;
1325                        background: rgba(255, 255, 255, 0.2);
1326                        color: white;
1327                        border: 1px solid rgba(255, 255, 255, 0.3);
1328                        border-radius: 8px;
1329                        font-size: 13px;
1330                        font-weight: 600;
1331                        cursor: pointer;
1332                        transition: all 0.3s ease;
1333                        margin-bottom: 10px;
1334                    "
1335                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1336                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1337                >
1338                    ⚙️ Управление стратегиями
1339                </button>
1340
1341                <button 
1342                    id="bulk-manage-cluster-strategies-btn"
1343                    style="
1344                        width: 100%;
1345                        padding: 10px;
1346                        background: rgba(255, 255, 255, 0.2);
1347                        color: white;
1348                        border: 1px solid rgba(255, 255, 255, 0.3);
1349                        border-radius: 8px;
1350                        font-size: 13px;
1351                        font-weight: 600;
1352                        cursor: pointer;
1353                        transition: all 0.3s ease;
1354                        margin-bottom: 10px;
1355                    "
1356                    onmouseover="this.style.background='rgba(255, 255, 255, 0.3)';"
1357                    onmouseout="this.style.background='rgba(255, 255, 255, 0.2)';"
1358                >
1359                    🎯 Стратегии для кластеров
1360                </button>
1361
1362                <div style="margin-bottom: 15px;">
1363                    <label style="display: flex; align-items: center; cursor: pointer; font-size: 13px; font-weight: 500;">
1364                        <input 
1365                            type="checkbox" 
1366                            id="bulk-apply-to-clusters" 
1367                            checked
1368                            style="
1369                                margin-right: 8px;
1370                                width: 18px;
1371                                height: 18px;
1372                                cursor: pointer;
1373                            "
1374                        />
1375                        Применить стратегию к кластерам
1376                    </label>
1377                </div>
1378
1379                <div style="margin-bottom: 15px;">
1380                    <label style="display: flex; align-items: center; cursor: pointer; font-size: 13px; font-weight: 500;">
1381                        <input 
1382                            type="checkbox" 
1383                            id="bulk-hold-position" 
1384                            checked
1385                            style="
1386                                margin-right: 8px;
1387                                width: 18px;
1388                                height: 18px;
1389                                cursor: pointer;
1390                            "
1391                        />
1392                        Удержание места
1393                    </label>
1394                </div>
1395
1396                <div id="bulk-control-buttons" style="
1397                    margin-top: 10px;
1398                    display: none;
1399                    gap: 10px;
1400                ">
1401                    <button 
1402                        id="pause-bulk-btn"
1403                        style="
1404                            flex: 1;
1405                            padding: 10px;
1406                            background: rgba(255, 255, 255, 0.9);
1407                            color: #f5576c;
1408                            border: none;
1409                            border-radius: 8px;
1410                            font-size: 13px;
1411                            font-weight: 600;
1412                            cursor: pointer;
1413                            transition: all 0.3s ease;
1414                        "
1415                    >
1416                        ⏏️ Пауза
1417                    </button>
1418                    <button 
1419                        id="stop-bulk-btn"
1420                        style="
1421                            flex: 1;
1422                            padding: 10px;
1423                            background: rgba(255, 59, 48, 0.9);
1424                            color: white;
1425                            border: none;
1426                            border-radius: 8px;
1427                            font-size: 13px;
1428                            font-weight: 600;
1429                            cursor: pointer;
1430                            transition: all 0.3s ease;
1431                        "
1432                    >
1433                        ⏹️ Стоп
1434                    </button>
1435                </div>
1436
1437                <div id="bulk-status-message" style="
1438                    margin-top: 15px;
1439                    padding: 10px;
1440                    border-radius: 8px;
1441                    font-size: 12px;
1442                    background: rgba(255, 255, 255, 0.2);
1443                    display: none;
1444                "></div>
1445
1446                <div id="bulk-progress" style="
1447                    margin-top: 15px;
1448                    display: none;
1449                ">
1450                    <div style="margin-bottom: 5px; font-size: 12px;">
1451                        Прогресс: <span id="bulk-progress-text">0/0</span>
1452                    </div>
1453                    <div style="
1454                        width: 100%;
1455                        height: 8px;
1456                        background: rgba(255, 255, 255, 0.3);
1457                        border-radius: 4px;
1458                        overflow: hidden;
1459                    ">
1460                        <div id="bulk-progress-bar" style="
1461                            width: 0%;
1462                            height: 100%;
1463                            background: white;
1464                            transition: width 0.3s ease;
1465                        "></div>
1466                    </div>
1467                </div>
1468            </div>
1469        `;
1470
1471        document.body.appendChild(panel);
1472        console.log('UI панель массового изменения создана');
1473
1474        // Добавляем возможность перетаскивания
1475        makeDraggable(panel);
1476
1477        // Подсчитываем количество кампаний
1478        updateCampaignsCount();
1479
1480        // Добавляем обработчик клика на заголовок для разворачивания/сворачивания
1481        document.getElementById('bulk-panel-header').addEventListener('click', () => {
1482            const content = document.getElementById('bulk-panel-content');
1483            const icon = document.getElementById('bulk-toggle-icon');
1484            if (content.style.display === 'none') {
1485                content.style.display = 'block';
1486                icon.textContent = '▲';
1487            } else {
1488                content.style.display = 'none';
1489                icon.textContent = '▼';
1490            }
1491        });
1492
1493        // Добавляем обработчик клика на кнопку
1494        document.getElementById('run-bulk-strategy-btn').addEventListener('click', runBulkStrategy);
1495        
1496        // Добавляем обработчик для кнопки управления стратегиями
1497        document.getElementById('bulk-manage-strategies-btn').addEventListener('click', async () => {
1498            await createStrategyManagementModal();
1499        });
1500        
1501        // Добавляем обработчик для кнопки управления кластерными стратегиями
1502        document.getElementById('bulk-manage-cluster-strategies-btn').addEventListener('click', async () => {
1503            await createClusterStrategyManagementModal();
1504        });
1505        
1506        // Добавляем обработчики для кнопок управления
1507        document.getElementById('pause-bulk-btn').addEventListener('click', pauseBulkProcessing);
1508        document.getElementById('stop-bulk-btn').addEventListener('click', stopBulkProcessing);
1509    }
1510
1511    // Функция для создания перетаскиваемого элемента
1512    function makeDraggable(element) {
1513        let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
1514        let isDragging = false;
1515
1516        element.onmousedown = dragMouseDown;
1517
1518        function dragMouseDown(e) {
1519            // Не перетаскиваем, если кликнули на input, button или другие интерактивные элементы
1520            if (e.target.tagName === 'INPUT' || e.target.tagName === 'BUTTON' || e.target.tagName === 'TEXTAREA') {
1521                return;
1522            }
1523            
1524            e.preventDefault();
1525            isDragging = true;
1526            pos3 = e.clientX;
1527            pos4 = e.clientY;
1528            document.onmouseup = closeDragElement;
1529            document.onmousemove = elementDrag;
1530        }
1531
1532        function elementDrag(e) {
1533            if (!isDragging) return;
1534            pos1 = pos3 - e.clientX;
1535            pos2 = pos4 - e.clientY;
1536            pos3 = e.clientX;
1537            pos4 = e.clientY;
1538            element.style.top = (element.offsetTop - pos2) + 'px';
1539            element.style.left = (element.offsetLeft - pos1) + 'px';
1540            element.style.right = 'auto';
1541            element.style.bottom = 'auto';
1542        }
1543
1544        function closeDragElement() {
1545            isDragging = false;
1546            document.onmouseup = null;
1547            document.onmousemove = null;
1548        }
1549    }
1550
1551    // Функция для обновления количества кампаний
1552    function updateCampaignsCount() {
1553        const campaignLinks = document.querySelectorAll('a[href*="/campaigns/auto-campaigns/"][href*="/campaign"]');
1554        const count = campaignLinks.length;
1555        const countElement = document.getElementById('campaigns-count');
1556        if (countElement) {
1557            countElement.textContent = count;
1558        }
1559        console.log(`Найдено кампаний: ${count}`);
1560    }
1561
1562    // Функция для показа статуса массовой обработки
1563    function showBulkStatus(message, isError = false) {
1564        const statusDiv = document.getElementById('bulk-status-message');
1565        if (statusDiv) {
1566            statusDiv.textContent = message;
1567            statusDiv.style.display = 'block';
1568            statusDiv.style.background = isError ? 'rgba(255, 59, 48, 0.9)' : 'rgba(52, 199, 89, 0.9)';
1569            console.log(`Статус массовой обработки: ${message}`);
1570        }
1571    }
1572
1573    // Функция для обновления прогресса
1574    function updateBulkProgress(current, total) {
1575        const progressDiv = document.getElementById('bulk-progress');
1576        const progressText = document.getElementById('bulk-progress-text');
1577        const progressBar = document.getElementById('bulk-progress-bar');
1578        
1579        if (progressDiv && progressText && progressBar) {
1580            progressDiv.style.display = 'block';
1581            progressText.textContent = `${current}/${total}`;
1582            const percentage = (current / total) * 100;
1583            progressBar.style.width = `${percentage}%`;
1584        }
1585    }
1586
1587    // Функция для прокрутки страницы вниз для загрузки всех кампаний
1588    async function scrollToLoadAllCampaigns() {
1589        console.log('Начинаем загрузку всех кампаний через прокрутку...');
1590        
1591        // Находим контейнер с прокруткой
1592        const tableContainer = document.querySelector('.container.MuiBox-root.css-9hf803');
1593        
1594        if (!tableContainer) {
1595            console.error('Контейнер таблицы не найден');
1596            return [];
1597        }
1598        
1599        console.log('Контейнер найден, начинаем прокрутку...');
1600        console.log(`Высота контейнера: ${tableContainer.scrollHeight}px`);
1601        
1602        // Собираем уникальные ссылки во время прокрутки
1603        const uniqueLinks = new Set();
1604        
1605        // Прокручиваем контейнер постепенно, чтобы загрузить все кампании
1606        let previousLinksCount = 0;
1607        let stableCount = 0;
1608        const maxAttempts = 200; // Максимум попыток
1609        let attempts = 0;
1610        const scrollStep = 500; // Прокручиваем по 500px за раз
1611        
1612        while (attempts < maxAttempts) {
1613            // Собираем ссылки на текущем шаге
1614            const currentLinks = document.querySelectorAll('a[href*="/campaigns/auto-campaigns/"][href*="/campaign"]');
1615            currentLinks.forEach(link => {
1616                uniqueLinks.add(link.href);
1617            });
1618            
1619            const currentCount = uniqueLinks.size;
1620            console.log(`Загружено кампаний: ${currentCount}, прокрутка: ${tableContainer.scrollTop}/${tableContainer.scrollHeight}`);
1621            
1622            // Прокручиваем контейнер постепенно
1623            tableContainer.scrollTop += scrollStep;
1624            
1625            // Ждем загрузки новых элементов
1626            await wait(500);
1627            
1628            // Если количество не изменилось
1629            if (currentCount === previousLinksCount) {
1630                stableCount++;
1631                // Если количество стабильно 5 раз подряд - значит все загружено
1632                if (stableCount >= 5) {
1633                    console.log('Все кампании загружены');
1634                    break;
1635                }
1636            } else {
1637                stableCount = 0;
1638                previousLinksCount = currentCount;
1639            }
1640            
1641            // Если достигли конца контейнера
1642            if (tableContainer.scrollTop + tableContainer.clientHeight >= tableContainer.scrollHeight - 10) {
1643                console.log('Достигнут конец контейнера');
1644                // Ждем еще немного для загрузки последних элементов
1645                await wait(1000);
1646                
1647                // Собираем последние ссылки
1648                const finalLinks = document.querySelectorAll('a[href*="/campaigns/auto-campaigns/"][href*="/campaign"]');
1649                finalLinks.forEach(link => {
1650                    uniqueLinks.add(link.href);
1651                });
1652                
1653                // Проверяем еще раз количество
1654                if (uniqueLinks.size === previousLinksCount) {
1655                    break;
1656                }
1657                previousLinksCount = uniqueLinks.size;
1658            }
1659            
1660            attempts++;
1661        }
1662        
1663        // Преобразуем Set в массив URL (НЕ прокручиваем обратно!)
1664        const links = Array.from(uniqueLinks);
1665        
1666        console.log(`Найдено кампаний: ${links.length}`);
1667        console.log(`Всего попыток прокрутки: ${attempts}`);
1668        return links;
1669    }
1670
1671    // Функция для массовой обработки кампаний
1672    async function runBulkStrategy() {
1673        if (isBulkProcessing) {
1674            showBulkStatus('Обработка уже выполняется', true);
1675            return;
1676        }
1677
1678        try {
1679            isBulkProcessing = true;
1680            console.log('Начало массовой обработки кампаний');
1681            
1682            bulkDesiredPercentage = parseFloat(document.getElementById('bulk-desired-percentage').value);
1683            if (!bulkDesiredPercentage || bulkDesiredPercentage <= 0) {
1684                showBulkStatus('Ошибка: введите корректный процент', true);
1685                isBulkProcessing = false;
1686                return;
1687            }
1688            console.log(`Желаемый процент: ${bulkDesiredPercentage}%`);
1689
1690            // Сохраняем ДРР для автоматической обработки
1691            await GM.setValue('bulkProcessingDRR', bulkDesiredPercentage);
1692            console.log(`ДРР ${bulkDesiredPercentage} сохранен для массовой обработки`);
1693            
1694            // Сохраняем состояние чекбоксов
1695            const bulkApplyToClusters = document.getElementById('bulk-apply-to-clusters');
1696            const bulkHoldPosition = document.getElementById('bulk-hold-position');
1697            await GM.setValue('bulkApplyToClusters', bulkApplyToClusters ? bulkApplyToClusters.checked : true);
1698            await GM.setValue('bulkHoldPosition', bulkHoldPosition ? bulkHoldPosition.checked : true);
1699            console.log(`Сохранены настройки: применить к кластерам = ${bulkApplyToClusters?.checked}, удержание места = ${bulkHoldPosition?.checked}`);
1700
1701            // Прокручиваем страницу для загрузки всех кампаний
1702            const campaignLinks = await scrollToLoadAllCampaigns();
1703            
1704            if (campaignLinks.length === 0) {
1705                showBulkStatus('Ошибка: кампании не найдены', true);
1706                isBulkProcessing = false;
1707                await GM.deleteValue('bulkProcessingDRR');
1708                return;
1709            }
1710
1711            console.log(`Найдено кампаний для обработки: ${campaignLinks.length}`);
1712            showBulkStatus(`Начинаем обработку ${campaignLinks.length} кампаний...`);
1713            updateBulkProgress(0, campaignLinks.length);
1714
1715            // Сохраняем список кампаний (массив URL), текущий индекс и общее количество
1716            await GM.setValue('bulkCampaigns', JSON.stringify(campaignLinks));
1717            await GM.setValue('bulkCurrentIndex', 0);
1718            await GM.setValue('bulkTotalCampaigns', campaignLinks.length);
1719
1720            // Показываем кнопки управления
1721            const controlButtons = document.getElementById('bulk-control-buttons');
1722            if (controlButtons) {
1723                controlButtons.style.display = 'flex';
1724            }
1725
1726            // Открываем первую кампанию в новой вкладке через window.open
1727            if (campaignLinks.length > 0) {
1728                console.log(`Открытие кампании 1/${campaignLinks.length}: ${campaignLinks[0]}`);
1729                window.open(campaignLinks[0], '_blank');
1730            }
1731
1732        } catch (error) {
1733            console.error('Ошибка при массовой обработке:', error);
1734            showBulkStatus(`Ошибка: ${error.message}`, true);
1735            isBulkProcessing = false;
1736            await GM.deleteValue('bulkProcessingDRR');
1737        }
1738    }
1739
1740    // Функция для паузы массовой обработки
1741    async function pauseBulkProcessing() {
1742        bulkPaused = !bulkPaused;
1743        const pauseBtn = document.getElementById('pause-bulk-btn');
1744        
1745        if (bulkPaused) {
1746            await GM.setValue('bulkPaused', true);
1747            pauseBtn.textContent = '▶️ Продолжить';
1748            showBulkStatus('⏸️ Обработка приостановлена');
1749            console.log('Массовая обработка приостановлена');
1750        } else {
1751            await GM.deleteValue('bulkPaused');
1752            pauseBtn.textContent = '⏸️ Пауза';
1753            showBulkStatus('▶️ Обработка возобновлена');
1754            console.log('Массовая обработка возобновлена');
1755            
1756            // Продолжаем обработку - открываем следующую кампанию
1757            const campaignsJson = await GM.getValue('bulkCampaigns', null);
1758            const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
1759            const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
1760            
1761            if (campaignsJson) {
1762                const campaigns = JSON.parse(campaignsJson);
1763                const nextIndex = currentIndex + 1;
1764                
1765                console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
1766                
1767                if (nextIndex < campaigns.length) {
1768                    // Сохраняем новый индекс
1769                    await GM.setValue('bulkCurrentIndex', nextIndex);
1770                    
1771                    // Открываем следующую кампанию в новой вкладке через window.open
1772                    console.log(`Открываем кампанию ${nextIndex + 1}: ${campaigns[nextIndex]}`);
1773                    const newTab = window.open(campaigns[nextIndex], '_blank');
1774                    
1775                    if (newTab) {
1776                        // Закрываем текущую вкладку
1777                        await wait(1000);
1778                        window.close();
1779                    } else {
1780                        // Если блокировщик всплывающих окон, используем редирект
1781                        console.log('Блокировщик всплывающих окон, используем редирект');
1782                        window.location.href = campaigns[nextIndex];
1783                    }
1784                }
1785            }
1786        }
1787    }
1788
1789    // Функция для остановки массовой обработки
1790    async function stopBulkProcessing() {
1791        await GM.deleteValue('bulkProcessingDRR');
1792        await GM.deleteValue('bulkCampaigns');
1793        await GM.deleteValue('bulkCurrentIndex');
1794        await GM.deleteValue('bulkTotalCampaigns');
1795        
1796        showBulkStatus('⏹️ Обработка остановлена', true);
1797        console.log('Массовая обработка остановлена');
1798        
1799        // Скрываем кнопки управления
1800        const controlButtons = document.getElementById('bulk-control-buttons');
1801        if (controlButtons) {
1802            controlButtons.style.display = 'none';
1803        }
1804        
1805        isBulkProcessing = false;
1806        bulkPaused = false;
1807    }
1808
1809    // Функция для показа статуса
1810    function showStatus(message, isError = false) {
1811        const statusDiv = document.getElementById('status-message');
1812        if (statusDiv) {
1813            statusDiv.textContent = message;
1814            statusDiv.style.display = 'block';
1815            statusDiv.style.background = isError ? 'rgba(255, 59, 48, 0.9)' : 'rgba(52, 199, 89, 0.9)';
1816            console.log(`Статус: ${message}`);
1817        }
1818    }
1819
1820    // Функция для ожидания
1821    function wait(ms) {
1822        return new Promise(resolve => setTimeout(resolve, ms));
1823    }
1824
1825    // Функция для парсинга числа из строки
1826    function parseNumber(str) {
1827        if (!str) return 0;
1828        // Убираем все символы кроме цифр, точек и запятых
1829        const cleaned = str.replace(/[^\d.,]/g, '').replace(/\s/g, '');
1830        // Заменяем запятую на точку
1831        const normalized = cleaned.replace(',', '.');
1832        return parseFloat(normalized) || 0;
1833    }
1834
1835    // Функция для парсинга процента
1836    function parsePercentage(str) {
1837        if (!str) return 0;
1838        const cleaned = str.replace('%', '').replace(',', '.').trim();
1839        return parseFloat(cleaned) || 0;
1840    }
1841
1842    // Основная функция запуска стратегии
1843    async function runStrategy() {
1844        try {
1845            console.log('Начало выполнения стратегии');
1846            showStatus('Запуск процесса...');
1847
1848            const desiredPercentage = parseFloat(document.getElementById('desired-percentage').value);
1849            if (!desiredPercentage || desiredPercentage <= 0) {
1850                showStatus('Ошибка: введите корректный процент', true);
1851                await handleStrategyError();
1852                return;
1853            }
1854            console.log(`Желаемый процент: ${desiredPercentage}%`);
1855
1856            // Проверяем, включен ли чекбокс "Удержание места"
1857            const holdPositionCheckbox = document.getElementById('hold-position');
1858            const shouldApplyHoldPosition = holdPositionCheckbox ? holdPositionCheckbox.checked : false;
1859
1860            // Шаг 1: Кликаем на статистику
1861            showStatus('Открытие статистики...');
1862            const statsButton = document.querySelector('.css-amj7dw');
1863            if (!statsButton) {
1864                showStatus('Ошибка: кнопка статистики не найдена', true);
1865                await handleStrategyError();
1866                return;
1867            }
1868            statsButton.click();
1869            console.log('Клик на статистику выполнен');
1870            await wait(2000);
1871
1872            // Шаг 1.5: Выбираем режим "Товары"
1873            showStatus('Выбор режима "Товары"...');
1874            const modeLabels = Array.from(document.querySelectorAll('label'));
1875            let modeInput = null;
1876            
1877            for (const label of modeLabels) {
1878                if (label.textContent.trim() === 'Режим') {
1879                    const inputId = label.getAttribute('for');
1880                    if (inputId) {
1881                        modeInput = document.getElementById(inputId);
1882                        console.log(`Найдено поле Режим с id: ${inputId}`);
1883                        break;
1884                    }
1885                }
1886            }
1887            
1888            if (modeInput) {
1889                modeInput.value = 'Товары';
1890                const inputEvent = new Event('input', { bubbles: true });
1891                const changeEvent = new Event('change', { bubbles: true });
1892                modeInput.dispatchEvent(inputEvent);
1893                modeInput.dispatchEvent(changeEvent);
1894                
1895                console.log('Установлено значение: Товары');
1896                await wait(1000);
1897                
1898                const options = document.querySelectorAll('[role="option"]');
1899                console.log(`Найдено опций: ${options.length}`);
1900                
1901                if (options.length > 0) {
1902                    const tovarOption = Array.from(options).find(opt => opt.textContent.includes('Товары'));
1903                    if (tovarOption) {
1904                        tovarOption.click();
1905                        console.log('Выбран режим "Товары"');
1906                        await wait(1000);
1907                    }
1908                }
1909            }
1910
1911            // Шаг 2: Извлекаем данные из статистики
1912            showStatus('Извлечение данных...');
1913            await wait(500);
1914            
1915            const stats = Array.from(document.querySelectorAll('.MuiTypography-caption.css-1et52kr'));
1916            
1917            let sumOrders = 0;
1918            let ordersCount = 0;
1919            let cartToOrderPercent = 0;
1920
1921            stats.forEach(el => {
1922                const text = el.textContent.trim();
1923                const valueElement = el.closest('.MuiBox-root')?.querySelector('.MuiTypography-h3 .MuiTypography-body1');
1924                const value = valueElement ? valueElement.textContent.trim() : '';
1925
1926                console.log(`Найден показатель: ${text} = ${value}`);
1927
1928                if (text === 'Сумма заказов') {
1929                    sumOrders = parseNumber(value);
1930                    console.log(`Сумма заказов: ${sumOrders}`);
1931                } else if (text === 'Заказов') {
1932                    ordersCount = parseNumber(value);
1933                    console.log(`Заказов: ${ordersCount}`);
1934                } else if (text === 'Корзина → Заказ') {
1935                    cartToOrderPercent = parsePercentage(value);
1936                    console.log(`Корзина → Заказ: ${cartToOrderPercent}%`);
1937                }
1938            });
1939
1940            if (sumOrders === 0 || ordersCount === 0 || cartToOrderPercent === 0) {
1941                showStatus('Ошибка: не удалось получить данные статистики', true);
1942                console.error('Недостаточно данных:', { sumOrders, ordersCount, cartToOrderPercent });
1943                await handleStrategyError();
1944                return;
1945            }
1946
1947            // Шаг 3: Вычисляем стоимость корзины
1948            const cartCost = (sumOrders / ordersCount) * (desiredPercentage / 100) * (cartToOrderPercent / 100);
1949            const cartCostRounded = Math.round(cartCost * 100) / 100;
1950            console.log(`Расчет: (${sumOrders} / ${ordersCount}) * (${desiredPercentage} / 100) * (${cartToOrderPercent} / 100) = ${cartCostRounded}`);
1951            showStatus(`Рассчитано: ${cartCostRounded}`);
1952
1953            // Закрываем статистику
1954            statsButton.click();
1955            await wait(500);
1956
1957            // Шаг 4: Кликаем на "Вставить стратегию"
1958            showStatus('Вставка стратегии...');
1959            const insertButtons = document.querySelectorAll('.css-5kbhos');
1960            let insertButton = null;
1961            
1962            for (const btn of insertButtons) {
1963                if (btn.textContent.includes('Вставить стратегию')) {
1964                    insertButton = btn;
1965                    break;
1966                }
1967            }
1968
1969            if (!insertButton && insertButtons.length >= 2) {
1970                insertButton = insertButtons[1];
1971            } else if (!insertButton && insertButtons.length === 1) {
1972                insertButton = insertButtons[0];
1973            }
1974
1975            if (!insertButton) {
1976                showStatus('Ошибка: кнопка "Вставить стратегию" не найдена', true);
1977                await handleStrategyError();
1978                return;
1979            }
1980
1981            // Получаем текущую выбранную стратегию
1982            let currentStrategyCode;
1983            if (shouldApplyHoldPosition) {
1984                currentStrategyCode = await getHoldPositionStrategy();
1985                console.log('Используем стратегию удержания места, длина:', currentStrategyCode.length);
1986            } else {
1987                currentStrategyCode = await getCurrentStrategy();
1988                console.log('Используем обычную стратегию, длина:', currentStrategyCode.length);
1989            }
1990            
1991            // Копируем код стратегии в буфер обмена
1992            console.log('Копируем стратегию в буфер обмена...');
1993            
1994            try {
1995                await navigator.clipboard.writeText(currentStrategyCode);
1996                console.log('✓ Стратегия скопирована через navigator.clipboard');
1997            } catch {
1998                console.log('navigator.clipboard не сработал, пробуем GM.setClipboard...');
1999                try {
2000                    await GM.setClipboard(currentStrategyCode);
2001                    console.log('✓ Стратегия скопирована через GM.setClipboard');
2002                } catch (e2) {
2003                    console.error('Ошибка копирования через GM.setClipboard:', e2.message);
2004                }
2005            }
2006            
2007            await wait(500);
2008
2009            insertButton.click();
2010            console.log('Клик на "Вставить стратегию" выполнен');
2011            await wait(500);
2012            
2013            console.log('✓ Стратегия вставлена из буфера обмена');
2014            await wait(500);
2015
2016            // Шаг 5: Находим поле "Желаемое значение" и вставляем результат
2017            showStatus('Заполнение поля...');
2018            
2019            const inputLabels = Array.from(document.querySelectorAll('.MuiInputLabel-root'));
2020            let targetInput = null;
2021
2022            for (const label of inputLabels) {
2023                const labelText = label.textContent;
2024                if (labelText.includes('Желаемое значение За корзину')) {
2025                    const inputId = label.getAttribute('for');
2026                    if (inputId) {
2027                        targetInput = document.getElementById(inputId);
2028                        console.log(`Найдено поле: ${labelText}, id: ${inputId}`);
2029                        break;
2030                    }
2031                }
2032            }
2033
2034            if (!targetInput) {
2035                const inputs = document.querySelectorAll('input[type="number"]');
2036                for (const input of inputs) {
2037                    const name = input.getAttribute('name') || '';
2038                    if (name.includes('rules') && name.includes('value')) {
2039                        targetInput = input;
2040                        console.log(`Найдено поле по имени: ${name}`);
2041                        break;
2042                    }
2043                }
2044            }
2045
2046            if (!targetInput) {
2047                showStatus('Ошибка: поле для ввода не найдено', true);
2048                console.error('Не удалось найти поле для ввода значения');
2049                await handleStrategyError();
2050                return;
2051            }
2052
2053            targetInput.focus();
2054            targetInput.value = cartCostRounded.toString();
2055            
2056            const inputEvent = new Event('input', { bubbles: true });
2057            const changeEvent = new Event('change', { bubbles: true });
2058            targetInput.dispatchEvent(inputEvent);
2059            targetInput.dispatchEvent(changeEvent);
2060            
2061            console.log(`Значение ${cartCostRounded} установлено в поле ${targetInput.id}`);
2062            await wait(500);
2063
2064            // Шаг 6: Нажимаем "Сохранить"
2065            showStatus('Сохранение...');
2066            const saveButtons = document.querySelectorAll('button');
2067            let saveButton = null;
2068
2069            for (const btn of saveButtons) {
2070                if (btn.textContent.trim() === 'Сохранить') {
2071                    saveButton = btn;
2072                    break;
2073                }
2074            }
2075
2076            if (!saveButton) {
2077                showStatus('Ошибка: кнопка "Сохранить" не найдена', true);
2078                await handleStrategyError();
2079                return;
2080            }
2081
2082            saveButton.click();
2083            console.log('Клик на "Сохранить" выполнен');
2084            await wait(500);
2085
2086            showStatus(`✅ Готово! Стоимость корзины: ${cartCostRounded}`);
2087            console.log('Стратегия успешно установлена');
2088
2089            // Проверяем, идет ли массовая обработка
2090            const savedDRR = await GM.getValue('bulkProcessingDRR', null);
2091            if (savedDRR !== null) {
2092                // Проверяем настройки чекбоксов
2093                const bulkApplyToClusters = await GM.getValue('bulkApplyToClusters', true);
2094                const bulkHoldPosition = await GM.getValue('bulkHoldPosition', true);
2095                
2096                console.log(`Настройки массовой обработки: применить к кластерам = ${bulkApplyToClusters}, удержание места = ${bulkHoldPosition}`);
2097                
2098                // Если нужно применить стратегию к кластерам
2099                if (bulkApplyToClusters) {
2100                    console.log('Переходим к обработке кластеров...');
2101                    showStatus('🎯 Обработка кластеров...');
2102                    
2103                    // Ждем немного после сохранения
2104                    await wait(2000);
2105                    
2106                    // Ищем вкладку "Кластеры"
2107                    const tabs = document.querySelectorAll('[role="tab"]');
2108                    let clustersTab = null;
2109                    
2110                    for (const tab of tabs) {
2111                        if (tab.textContent.includes('Кластеры')) {
2112                            clustersTab = tab;
2113                            console.log('Найдена вкладка "Кластеры"');
2114                            break;
2115                        }
2116                    }
2117                    
2118                    if (clustersTab) {
2119                        // Кликаем на вкладку "Кластеры"
2120                        clustersTab.click();
2121                        console.log('Клик на вкладку "Кластеры" выполнен');
2122                        await wait(2000);
2123                        
2124                        // Ищем все ссылки на кластеры
2125                        const clusterLinks = document.querySelectorAll('a[href*="/cluster"]');
2126                        console.log(`Найдено кластеров: ${clusterLinks.length}`);
2127                        
2128                        if (clusterLinks.length > 0) {
2129                            // Обрабатываем каждый кластер
2130                            for (let i = 0; i < clusterLinks.length; i++) {
2131                                const clusterLink = clusterLinks[i];
2132                                const clusterUrl = clusterLink.href;
2133                                
2134                                console.log(`Обработка кластера ${i + 1}/${clusterLinks.length}: ${clusterUrl}`);
2135                                showStatus(`🎯 Кластер ${i + 1}/${clusterLinks.length}...`);
2136                                
2137                                // Переходим к кластеру
2138                                window.location.href = clusterUrl;
2139                                
2140                                // Ждем загрузки страницы кластера и применяем стратегию
2141                                // (это будет обработано при следующей загрузке страницы)
2142                                return;
2143                            }
2144                        } else {
2145                            console.log('Кластеры не найдены, переходим к следующей кампании');
2146                        }
2147                    } else {
2148                        console.log('Вкладка "Кластеры" не найдена, переходим к следующей кампании');
2149                    }
2150                }
2151                
2152                console.log('Массовая обработка активна, переходим к следующей кампании');
2153                showStatus('✅ Готово! Переход к следующей кампании через 3 секунды...');
2154                
2155                // Ждем 3 секунды перед переходом
2156                await wait(3000);
2157                
2158                const campaignsJson = await GM.getValue('bulkCampaigns', null);
2159                const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
2160                const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
2161                
2162                if (campaignsJson) {
2163                    const campaigns = JSON.parse(campaignsJson);
2164                    const nextIndex = currentIndex + 1;
2165                    
2166                    console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
2167                    
2168                    if (nextIndex < campaigns.length) {
2169                        // Сохраняем новый индекс
2170                        await GM.setValue('bulkCurrentIndex', nextIndex);
2171                        
2172                        // Переходим к следующей кампании
2173                        console.log(`Переходим к кампании ${nextIndex + 1}: ${campaigns[nextIndex]}`);
2174                        window.location.href = campaigns[nextIndex];
2175                    } else {
2176                        // Все кампании обработаны
2177                        console.log('Все кампании обработаны');
2178                        await GM.deleteValue('bulkProcessingDRR');
2179                        await GM.deleteValue('bulkCampaigns');
2180                        await GM.deleteValue('bulkCurrentIndex');
2181                        await GM.deleteValue('bulkTotalCampaigns');
2182                        await GM.deleteValue('bulkApplyToClusters');
2183                        await GM.deleteValue('bulkHoldPosition');
2184                        
2185                        showStatus('✅ Все кампании обработаны!');
2186                        alert('✅ Все кампании обработаны!');
2187                    }
2188                }
2189            }
2190
2191        } catch (error) {
2192            console.error('Ошибка при выполнении стратегии:', error);
2193            showStatus(`Ошибка: ${error.message}`, true);
2194            await handleStrategyError();
2195        }
2196    }
2197
2198    // Функция для обработки ошибок и перехода к следующей кампании
2199    async function handleStrategyError() {
2200        const savedDRR = await GM.getValue('bulkProcessingDRR', null);
2201        if (savedDRR !== null) {
2202            console.log('Обнаружена ошибка при массовой обработке, ждем 10 секунд');
2203            showStatus('⚠️ Ошибка! Переход к следующей кампании через 10 секунд...', true);
2204            
2205            for (let i = 10; i > 0; i--) {
2206                showStatus(`⚠️ Ошибка! Переход к следующей через ${i} сек...`, true);
2207                await wait(1000);
2208            }
2209            
2210            const campaignsJson = await GM.getValue('bulkCampaigns', null);
2211            const currentIndex = await GM.getValue('bulkCurrentIndex', 0);
2212            const totalCampaigns = await GM.getValue('bulkTotalCampaigns', 0);
2213            
2214            if (campaignsJson) {
2215                const campaigns = JSON.parse(campaignsJson);
2216                const nextIndex = currentIndex + 1;
2217                
2218                console.log(`Обработано кампаний: ${nextIndex} из ${totalCampaigns}`);
2219                
2220                if (nextIndex < campaigns.length) {
2221                    await GM.setValue('bulkCurrentIndex', nextIndex);
2222                    console.log(`Переходим к кампании ${nextIndex + 1}: ${campaigns[nextIndex]}`);
2223                    // Просто перенаправляем текущую вкладку на следующую кампанию
2224                    window.location.href = campaigns[nextIndex];
2225                } else {
2226                    console.log('Все кампании обработаны');
2227                    await GM.deleteValue('bulkProcessingDRR');
2228                    await GM.deleteValue('bulkCampaigns');
2229                    await GM.deleteValue('bulkCurrentIndex');
2230                    await GM.deleteValue('bulkTotalCampaigns');
2231                    await GM.deleteValue('bulkApplyToClusters');
2232                    await GM.deleteValue('bulkHoldPosition');
2233                    
2234                    showStatus('✅ Все кампании обработаны!');
2235                    alert('✅ Все кампании обработаны!');
2236                }
2237            }
2238        }
2239    }
2240
2241    // Инициализация
2242    function init() {
2243        console.log('Инициализация расширения');
2244        
2245        if (window.location.href.includes('/advert/campaigns')) {
2246            console.log('Страница списка кампаний обнаружена');
2247            setTimeout(() => {
2248                if (document.body) {
2249                    createBulkUI();
2250                } else {
2251                    console.error('Body не найден');
2252                }
2253            }, 1000);
2254        } else if (window.location.href.includes('/campaigns/auto-campaigns/') && window.location.href.includes('/campaign')) {
2255            console.log('Страница кампании обнаружена');
2256            setTimeout(() => {
2257                if (document.body) {
2258                    createUI();
2259                } else {
2260                    console.error('Body не найден');
2261                }
2262            }, 1000);
2263        } else {
2264            console.log('Не на странице кампании, UI не создается');
2265        }
2266    }
2267
2268    // Запускаем инициализацию
2269    init();
2270
2271})();