/*
 * DAZY — GC PROCESS TOOLS LAUNCHER v0.2.2
 *
 * Архитектура аналогична Dashboard Tools Launcher:
 * - этот файл содержит только лаунчер;
 * - Fast Editor находится в отдельном файле темы;
 * - Minimap находится в отдельном файле темы;
 * - на странице подключается только этот Launcher.
 */

(function () {
  'use strict';

  try {
    var TOOL_KEY = 'gcProcessToolsLauncherV02';
    var STORAGE_KEY =
      'gc-process-tools-launcher-v02:collapsed';

    var TARGET_PAGE = {
      origin: 'https://matricentre.ru',
      pathname: '/pl/tasks/mission/process',
      processId: '2519014'
    };

    var ACCESS_CONFIG = {
      enabled: true,

      allowedUserIds: [
        427328640, 425987389, 355017780, 509682978, 509084284
      ],

      allowedAccountIds: [
        842325, 60520, 936662
      ],

      silentDeny: true
    };

    /*
      Текущий файл уже создан по адресу:
      https://matricentre.ru/pl/layout/96070/0/DAZY-GC-Process-Tools-Launcher.js

      Добавляй следующие файлы темы строго в таком порядке:

      1. GC-Process-Fast-Editor
         ожидаемый URL: https://matricentre.ru/pl/layout/96070/2/DAZY-GC-Process-Fast-Editor.js

      2. GC-Process-Minimap
         ожидаемый URL: https://matricentre.ru/pl/layout/96070/1/DAZY-GC-Process-Minimap.js
    */
    var SCRIPT_URLS = {
      fastEditor:
        'https://matricentre.ru/pl/layout/96070/2/' +
        'DAZY-GC-Process-Fast-Editor.js',

      minimap:
        'https://matricentre.ru/pl/layout/96070/1/' +
        'DAZY-GC-Process-Minimap.js'
    };

    var GLOBAL_KEYS = {
      fastEditor: 'gcProcessFastEditorV129',
      minimap: 'gcProcessMinimapV03'
    };

    var READY_KEYS = {
      fastEditor: '__DAZY_PROCESS_FAST_EDITOR_READY_V129__',
      minimap: '__DAZY_PROCESS_MINIMAP_READY_V03__'
    };

    var currentUrl = new URL(window.location.href);

    var isAllowedTestPage =
      currentUrl.origin === TARGET_PAGE.origin &&
      currentUrl.pathname === TARGET_PAGE.pathname &&
      currentUrl.searchParams.get('id') ===
        TARGET_PAGE.processId;

    if (!isAllowedTestPage) {
      console.info(
        '[DAZY Process Tools] Тестовый запуск пропущен.',
        {
          current: currentUrl.href,
          allowed:
            TARGET_PAGE.origin +
            TARGET_PAGE.pathname +
            '?id=' +
            TARGET_PAGE.processId
        }
      );
      return;
    }

    function toNumber(value) {
      var number = Number(value);
      return Number.isFinite(number) ? number : null;
    }

    function includesNumber(list, value) {
      value = toNumber(value);

      if (value === null) {
        return false;
      }

      return list
        .map(function (item) {
          return Number(item);
        })
        .indexOf(value) !== -1;
    }

    function hasAccessVars() {
      return (
        typeof window.accountUserId !== 'undefined' ||
        typeof window.accountId !== 'undefined'
      );
    }

    function getAccessInfo() {
      return {
        userId: toNumber(window.accountUserId),
        accountId: toNumber(window.accountId),
        userName: window.accountSafeUserName || ''
      };
    }

    function isAccessAllowed() {
      if (!ACCESS_CONFIG.enabled) {
        return true;
      }

      var info = getAccessInfo();

      if (
        ACCESS_CONFIG.allowedAccountIds.length &&
        !includesNumber(
          ACCESS_CONFIG.allowedAccountIds,
          info.accountId
        )
      ) {
        return false;
      }

      if (
        ACCESS_CONFIG.allowedUserIds.length &&
        !includesNumber(
          ACCESS_CONFIG.allowedUserIds,
          info.userId
        )
      ) {
        return false;
      }

      return true;
    }

    function cleanupKnownLauncher() {
      [
        'gcProcessToolsLauncherV01',
        'gcProcessToolsLauncherV02'
      ].forEach(function (key) {
        if (
          window[key] &&
          typeof window[key].destroy === 'function'
        ) {
          try {
            window[key].destroy();
          } catch (_) {}
        }
      });

      document
        .querySelectorAll(
          '#gcptl-panel, #gcptl-styles'
        )
        .forEach(function (element) {
          element.remove();
        });
    }

    function destroyTool(toolName) {
      var globalKey = GLOBAL_KEYS[toolName];
      var tool = window[globalKey];

      if (tool && typeof tool.destroy === 'function') {
        try {
          tool.destroy();
        } catch (error) {
          console.warn(
            '[DAZY Process Tools] Ошибка остановки ' +
              toolName +
              ':',
            error
          );
        }
      }
    }

    function denyAccess() {
      cleanupKnownLauncher();
      destroyTool('fastEditor');
      destroyTool('minimap');

      var info = getAccessInfo();

      window[TOOL_KEY] = {
        accessDenied: true,
        allowed: false,
        userId: info.userId,
        accountId: info.accountId
      };

      console.warn(
        '[DAZY Process Tools] Доступ запрещён.',
        info
      );

      if (!ACCESS_CONFIG.silentDeny) {
        alert(
          'DAZY Process Tools недоступен для текущего пользователя.'
        );
      }
    }

    function waitForEditorReady(timeoutMs) {
      timeoutMs = Number(timeoutMs) || 60000;

      return new Promise(function (resolve, reject) {
        var startedAt = Date.now();

        (function tick() {
          var flowchart =
            document.getElementById('flowchart');

          var plugin = null;

          try {
            if (flowchart && window.jQuery) {
              plugin =
                window.jQuery(flowchart)
                  .data('gc-flowchartPlugin') ||
                window.jQuery(flowchart)
                  .data('flowchartPlugin') ||
                null;
            }
          } catch (_) {}

          if (flowchart && plugin) {
            resolve(plugin);
            return;
          }

          if (Date.now() - startedAt >= timeoutMs) {
            reject(
              new Error(
                'Редактор процесса GetCourse не загрузился.'
              )
            );
            return;
          }

          setTimeout(tick, 150);
        })();
      });
    }

    function waitForGlobal(toolName, timeoutMs) {
      timeoutMs = Number(timeoutMs) || 20000;

      var globalKey = GLOBAL_KEYS[toolName];
      var readyKey = READY_KEYS[toolName];

      return new Promise(function (resolve, reject) {
        var startedAt = Date.now();

        (function tick() {
          if (window[globalKey]) {
            resolve(window[globalKey]);
            return;
          }

          var readyPromise = window[readyKey];

          if (
            readyPromise &&
            typeof readyPromise.then === 'function'
          ) {
            readyPromise
              .then(function () {
                if (window[globalKey]) {
                  resolve(window[globalKey]);
                }
              })
              .catch(reject);
          }

          if (Date.now() - startedAt >= timeoutMs) {
            reject(
              new Error(
                'Инструмент ' +
                  toolName +
                  ' не зарегистрировался.'
              )
            );
            return;
          }

          setTimeout(tick, 100);
        })();
      });
    }

    function loadExternalScript(src, toolName) {
      return new Promise(function (resolve, reject) {
        var script = document.createElement('script');

        script.src = src;
        script.async = false;
        script.dataset.dazyProcessTool = toolName;

        script.onload = function () {
          waitForGlobal(toolName)
            .then(resolve)
            .catch(reject);
        };

        script.onerror = function () {
          reject(
            new Error(
              'Не удалось загрузить файл: ' + src
            )
          );
        };

        document.head.appendChild(script);
      });
    }

    function startLauncher() {
      cleanupKnownLauncher();

      var state = {
        panel: null,
        status: null,
        collapsed: false,
        loading: {
          fastEditor: null,
          minimap: null
        },
        allowed: true,
        accessInfo: getAccessInfo()
      };

      window[TOOL_KEY] = state;

      function log() {
        console.log.apply(console, arguments);
      }

      function readCollapsedState() {
        try {
          return (
            localStorage.getItem(STORAGE_KEY) === '1'
          );
        } catch (_) {
          return false;
        }
      }

      function saveCollapsedState() {
        try {
          localStorage.setItem(
            STORAGE_KEY,
            state.collapsed ? '1' : '0'
          );
        } catch (_) {}
      }

      function setStatus(text, tone) {
        if (!state.status) {
          return;
        }

        state.status.textContent = text;
        state.status.dataset.tone = tone || 'normal';
      }

      function isToolLoaded(toolName) {
        return Boolean(
          window[GLOBAL_KEYS[toolName]]
        );
      }

      function loadTool(toolName) {
        if (isToolLoaded(toolName)) {
          updateActiveButtons();

          return Promise.resolve(
            window[GLOBAL_KEYS[toolName]]
          );
        }

        if (state.loading[toolName]) {
          return state.loading[toolName];
        }

        if (!isAccessAllowed()) {
          return Promise.reject(
            new Error(
              'Доступ к инструментам запрещён.'
            )
          );
        }

        setStatus(
          'Загружаю ' + toolName + '…',
          'warning'
        );

        state.loading[toolName] =
          waitForEditorReady()
            .then(function () {
              return loadExternalScript(
                SCRIPT_URLS[toolName],
                toolName
              );
            })
            .then(function (tool) {
              setStatus(
                toolName + ' запущен.',
                'success'
              );

              updateActiveButtons();
              return tool;
            })
            .catch(function (error) {
              setStatus(
                error.message || String(error),
                'error'
              );

              console.error(
                '[DAZY Process Tools] Ошибка запуска ' +
                  toolName +
                  ':',
                error
              );

              throw error;
            })
            .finally(function () {
              state.loading[toolName] = null;
              updateActiveButtons();
            });

        return state.loading[toolName];
      }

      function stopTool(toolName) {
        destroyTool(toolName);

        setTimeout(function () {
          setStatus(
            isToolLoaded(toolName)
              ? toolName +
                  ' не удалось полностью остановить.'
              : toolName + ' остановлен.',
            isToolLoaded(toolName)
              ? 'error'
              : 'normal'
          );

          updateActiveButtons();
        }, 0);
      }

      function restartTool(toolName) {
        stopTool(toolName);

        return new Promise(function (resolve) {
          setTimeout(resolve, 100);
        }).then(function () {
          return loadTool(toolName);
        });
      }

      function toggleTool(toolName) {
        if (isToolLoaded(toolName)) {
          stopTool(toolName);
          return Promise.resolve(null);
        }

        return loadTool(toolName);
      }

      function startAll() {
        return loadTool('fastEditor')
          .then(function () {
            return loadTool('minimap');
          });
      }

      function stopAll() {
        stopTool('fastEditor');
        stopTool('minimap');
      }

      function updateActiveButtons() {
        if (!state.panel) {
          return;
        }

        [
          'fastEditor',
          'minimap'
        ].forEach(function (toolName) {
          var button = state.panel.querySelector(
            '[data-gcptl-action="' +
              toolName +
              '"]'
          );

          if (!button) {
            return;
          }

          var loaded = isToolLoaded(toolName);
          var loading = Boolean(
            state.loading[toolName]
          );

          button.classList.toggle(
            'is-active',
            loaded
          );

          button.disabled = loading;

          button.textContent =
            toolName === 'fastEditor'
              ? loaded
                ? 'Остановить Fast Editor'
                : 'Запустить Fast Editor'
              : loaded
                ? 'Остановить мини-карту'
                : 'Запустить мини-карту';
        });
      }

      function injectStyles() {
        var style = document.createElement('style');
        style.id = 'gcptl-styles';

        style.textContent =
          '#gcptl-panel{' +
            'position:fixed;' +
            'left:18px;' +
            'bottom:18px;' +
            'z-index:2147483646;' +
            'width:320px;' +
            'padding:12px;' +
            'border-radius:14px;' +
            'background:#202326;' +
            'color:#fff;' +
            'font:13px/1.4 Arial,sans-serif;' +
            'box-shadow:0 12px 38px rgba(0,0,0,.38);' +
          '}' +

          '#gcptl-panel *{' +
            'box-sizing:border-box;' +
          '}' +

          '#gcptl-panel .gcptl-head{' +
            'display:flex;' +
            'align-items:center;' +
            'justify-content:space-between;' +
            'gap:8px;' +
          '}' +

          '#gcptl-panel .gcptl-title{' +
            'font-weight:700;' +
          '}' +

          '#gcptl-panel .gcptl-collapse{' +
            'width:28px;' +
            'height:26px;' +
            'padding:0;' +
            'border:0;' +
            'border-radius:8px;' +
            'background:#3b4653;' +
            'color:#fff;' +
            'cursor:pointer;' +
          '}' +

          '#gcptl-panel .gcptl-body{' +
            'margin-top:9px;' +
          '}' +

          '#gcptl-panel.is-collapsed{' +
            'width:214px;' +
          '}' +

          '#gcptl-panel.is-collapsed ' +
          '.gcptl-body{' +
            'display:none;' +
          '}' +

          '#gcptl-panel .gcptl-status{' +
            'margin-bottom:8px;' +
            'padding:7px 8px;' +
            'border-radius:8px;' +
            'background:rgba(255,255,255,.07);' +
            'color:#d4dade;' +
            'font-size:12px;' +
          '}' +

          '#gcptl-panel .gcptl-status' +
          '[data-tone="success"]{' +
            'background:rgba(34,197,94,.16);' +
            'color:#bbf7d0;' +
          '}' +

          '#gcptl-panel .gcptl-status' +
          '[data-tone="warning"]{' +
            'background:rgba(245,158,11,.16);' +
            'color:#fde68a;' +
          '}' +

          '#gcptl-panel .gcptl-status' +
          '[data-tone="error"]{' +
            'background:rgba(239,68,68,.18);' +
            'color:#fecaca;' +
          '}' +

          '#gcptl-panel .gcptl-actions{' +
            'display:grid;' +
            'gap:7px;' +
          '}' +

          '#gcptl-panel .gcptl-actions button{' +
            'border:0;' +
            'border-radius:8px;' +
            'padding:8px 9px;' +
            'background:#3b4653;' +
            'color:#fff;' +
            'font-weight:700;' +
            'cursor:pointer;' +
          '}' +

          '#gcptl-panel .gcptl-actions ' +
          'button.is-active{' +
            'background:#81373e;' +
          '}' +

          '#gcptl-panel .gcptl-actions ' +
          'button:disabled{' +
            'opacity:.5;' +
            'cursor:default;' +
          '}' +

          '#gcptl-panel .gcptl-close-all{' +
            'background:#5a3337!important;' +
          '}';

        document.head.appendChild(style);
      }

      function applyCollapsedState() {
        if (!state.panel) {
          return;
        }

        state.panel.classList.toggle(
          'is-collapsed',
          state.collapsed
        );

        var button = state.panel.querySelector(
          '.gcptl-collapse'
        );

        if (button) {
          button.textContent =
            state.collapsed ? '+' : '−';
        }
      }

      function toggleCollapsed() {
        state.collapsed = !state.collapsed;
        saveCollapsedState();
        applyCollapsedState();
      }

      function createPanel() {
        var panel = document.createElement('div');
        panel.id = 'gcptl-panel';

        panel.innerHTML =
          '<div class="gcptl-head">' +
            '<span class="gcptl-title">' +
              'DAZY Process Tools' +
            '</span>' +
            '<button ' +
              'type="button" ' +
              'class="gcptl-collapse"' +
            '>−</button>' +
          '</div>' +

          '<div class="gcptl-body">' +
            '<div ' +
              'class="gcptl-status" ' +
              'data-tone="normal"' +
            '>Лаунчер готов.</div>' +

            '<div class="gcptl-actions">' +
              '<button ' +
                'type="button" ' +
                'data-gcptl-action="fastEditor"' +
              '>Запустить Fast Editor</button>' +

              '<button ' +
                'type="button" ' +
                'data-gcptl-action="minimap"' +
              '>Запустить мини-карту</button>' +

              '<button ' +
                'type="button" ' +
                'class="gcptl-close-all" ' +
                'data-gcptl-action="stopAll"' +
              '>Остановить все инструменты</button>' +
            '</div>' +
          '</div>';

        document.body.appendChild(panel);

        state.panel = panel;
        state.status = panel.querySelector(
          '.gcptl-status'
        );

        panel
          .querySelector(
            '[data-gcptl-action="fastEditor"]'
          )
          .addEventListener(
            'click',
            function () {
              toggleTool('fastEditor')
                .catch(function () {});
            }
          );

        panel
          .querySelector(
            '[data-gcptl-action="minimap"]'
          )
          .addEventListener(
            'click',
            function () {
              toggleTool('minimap')
                .catch(function () {});
            }
          );

        panel
          .querySelector(
            '[data-gcptl-action="stopAll"]'
          )
          .addEventListener(
            'click',
            stopAll
          );

        panel
          .querySelector('.gcptl-collapse')
          .addEventListener(
            'click',
            toggleCollapsed
          );

        state.collapsed = readCollapsedState();
        applyCollapsedState();
        updateActiveButtons();
      }

      function destroy(options) {
        options = options || {};

        if (options.stopTools === true) {
          stopAll();
        }

        var panel =
          document.getElementById('gcptl-panel');

        var style =
          document.getElementById('gcptl-styles');

        if (panel) {
          panel.remove();
        }

        if (style) {
          style.remove();
        }

        document
          .querySelectorAll(
            'script[data-dazy-process-tool]'
          )
          .forEach(function (script) {
            script.remove();
          });

        try {
          delete window[TOOL_KEY];
        } catch (_) {
          window[TOOL_KEY] = null;
        }

        log(
          '[DAZY Process Tools Launcher v0.2.2] Закрыт'
        );
      }

      function init() {
        injectStyles();
        createPanel();

        state.destroy = destroy;
        state.loadFastEditor = function () {
          return loadTool('fastEditor');
        };
        state.stopFastEditor = function () {
          return stopTool('fastEditor');
        };
        state.restartFastEditor = function () {
          return restartTool('fastEditor');
        };
        state.loadMinimap = function () {
          return loadTool('minimap');
        };
        state.stopMinimap = function () {
          return stopTool('minimap');
        };
        state.restartMinimap = function () {
          return restartTool('minimap');
        };
        state.startAll = startAll;
        state.stopAll = stopAll;
        state.isFastEditorLoaded = function () {
          return isToolLoaded('fastEditor');
        };
        state.isMinimapLoaded = function () {
          return isToolLoaded('minimap');
        };
        state.getSettings = function () {
          return {
            targetPage: TARGET_PAGE,
            scriptUrls: SCRIPT_URLS,
            accessInfo: state.accessInfo,
            collapsed: state.collapsed
          };
        };

        startAll().catch(function (error) {
          console.warn(
            '[DAZY Process Tools] Автозапуск завершился с ошибкой:',
            error
          );
        });

        log(
          '[DAZY Process Tools Launcher v0.2.2] Запущен'
        );
      }

      if (document.readyState === 'loading') {
        document.addEventListener(
          'DOMContentLoaded',
          init,
          { once: true }
        );
      } else {
        init();
      }
    }

    function bootWhenUserReady() {
      var attempts = 0;
      var maxAttempts = 50;

      (function tick() {
        if (
          !hasAccessVars() &&
          attempts < maxAttempts
        ) {
          attempts += 1;
          setTimeout(tick, 100);
          return;
        }

        if (!isAccessAllowed()) {
          denyAccess();
          return;
        }

        startLauncher();
      })();
    }

    bootWhenUserReady();
  } catch (error) {
    console.error(
      '[DAZY Process Tools Launcher v0.2.2] Fatal error:',
      error
    );

    alert(
      'Ошибка запуска DAZY Process Tools. ' +
      'Подробности находятся в консоли.'
    );
  }
})();
