/* global window, document */
// AgentUI Prompt Manager UI extracted from editor.html
// Exposes window.PM.setupProviderCallPMUI(editor, id)
// Depends on DOM elements rendered by editor.html inspector:
//   #pm-list, #pm-editor, #pm-name, #pm-role, #pm-prompt, #pm-save, #pm-cancel
(function (w) {
  'use strict';

  function setupProviderCallPMUI(editor, id) {
    try {
      const n2 = editor.getNodeFromId(id);
      if (!n2) return;
      const d2 = n2.data || {};
      if (!Array.isArray(d2.blocks)) d2.blocks = [];

      // Ensure node.data and DOM __data always reflect latest blocks
      function syncNodeDataBlocks() {
        try {
          const n = editor.getNodeFromId(id);
          if (!n) return;
          // Готовим новые данные с глубокой копией blocks
          const newData = { ...(n.data || {}), blocks: Array.isArray(d2.blocks) ? d2.blocks.map(b => ({ ...b })) : [] };
          // 1) Обновляем внутреннее состояние Drawflow, чтобы export() возвращал актуальные данные
          try {
            if (w.AU && typeof w.AU.updateNodeDataAndDom === 'function') {
              w.AU.updateNodeDataAndDom(editor, id, newData);
            } else {
              editor.updateNodeDataFromId(id, newData);
              const el2 = document.querySelector(`#node-${id}`);
              if (el2) el2.__data = JSON.parse(JSON.stringify(newData));
            }
          } catch (e) {}
        } catch (e) {}
      }
      // Initial sync to attach blocks into __data for toPipelineJSON
      syncNodeDataBlocks();

      const listEl = document.getElementById('pm-list');
      const addBtn = document.getElementById('pm-add');
      const editorBox = document.getElementById('pm-editor');
      const nameInp = document.getElementById('pm-name');
      const roleSel = document.getElementById('pm-role');
      const promptTxt = document.getElementById('pm-prompt');
      const saveBtn = document.getElementById('pm-save');
      const cancelBtn = document.getElementById('pm-cancel');
      let editingId = null;

      // Безопасное экранирование HTML для вставок в UI
      function pmEscapeHtml(s) {
        const str = String(s ?? '');
        return str
          .replace(/&/g, '&amp;')
          .replace(/</g, '&lt;')
          .replace(/>/g, '&gt;')
          .replace(/"/g, '&quot;')
          .replace(/'/g, '&#39;');
      }

      // Изменения блока применяются только по кнопке «Сохранить» внутри редактора блока.

      // Drag&Drop через SortableJS (если доступен)
      if (w.Sortable && listEl && !listEl.__sortable) {
        listEl.__sortable = new w.Sortable(listEl, {
          animation: 150,
          handle: '.pm-handle',
          onEnd(evt) {
            const oldIndex = evt.oldIndex;
            const newIndex = evt.newIndex;
            if (oldIndex === newIndex) return;
            const moved = d2.blocks.splice(oldIndex, 1)[0];
            d2.blocks.splice(newIndex, 0, moved);
            d2.blocks.forEach((b, i) => b.order = i);
            syncNodeDataBlocks();
          }
        });
      }

      function sortAndReindex() {
        d2.blocks.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
        d2.blocks.forEach((b, i) => b.order = i);
      }

      function renderList() {
        sortAndReindex();
        if (!listEl) return;
        listEl.innerHTML = '';
        d2.blocks.forEach((b, i) => {
          const domId = b.id || ('b' + i);
          const li = document.createElement('li');
          li.draggable = true;
          li.dataset.id = domId;
          li.style.display = 'flex';
          li.style.alignItems = 'center';
          li.style.gap = '6px';
          li.style.padding = '4px 0';
          const nameDisp = pmEscapeHtml(b.name || ('Block ' + (i + 1)));
          const roleDisp = pmEscapeHtml(b.role || 'user');
          li.innerHTML = `
            <span class="pm-handle" style="cursor:grab;">☰</span>
            <input type="checkbox" class="pm-enabled" ${b.enabled !== false ? 'checked' : ''} title="enabled"/>
            <span class="pm-name" style="flex:1">${nameDisp}</span>
            <span class="pm-role" style="opacity:.8">${roleDisp}</span>
            <button class="pm-edit" title="Редактировать">✎</button>
            <button class="pm-del" title="Удалить">🗑</button>
          `;
          // DnD via HTML5 fallback as well (kept for compatibility)
          li.addEventListener('dragstart', e => { e.dataTransfer.setData('text/plain', domId); });
          li.addEventListener('dragover', e => { e.preventDefault(); });
          li.addEventListener('drop', e => {
            e.preventDefault();
            const srcId = e.dataTransfer.getData('text/plain');
            const tgtId = domId;
            if (!srcId || srcId === tgtId) return;
            const srcIdx = d2.blocks.findIndex(x => (x.id || '') === srcId);
            const tgtIdx = d2.blocks.findIndex(x => (x.id || '') === tgtId);
            if (srcIdx < 0 || tgtIdx < 0) return;
            const [moved] = d2.blocks.splice(srcIdx, 1);
            d2.blocks.splice(tgtIdx, 0, moved);
            sortAndReindex();
            renderList();
            syncNodeDataBlocks();
          });
          // toggle
          li.querySelector('.pm-enabled').addEventListener('change', ev => {
            b.enabled = ev.target.checked;
            syncNodeDataBlocks();
          });
          // edit
          li.querySelector('.pm-edit').addEventListener('click', () => {
            openEditor(b);
          });
          // delete
          li.querySelector('.pm-del').addEventListener('click', () => {
            const idx = d2.blocks.indexOf(b);
            if (idx >= 0) d2.blocks.splice(idx, 1);
            sortAndReindex();
            renderList();
            syncNodeDataBlocks();
            if (editingId && editingId === (b.id || null)) {
              if (editorBox) editorBox.style.display = 'none';
              editingId = null;
            }
          });
          listEl.appendChild(li);
        });
      }

      function openEditor(b) {
        // Гарантируем наличие id у редактируемого блока
        if (!b.id) {
          b.id = 'b' + Date.now().toString(36);
          syncNodeDataBlocks();
        }
        editingId = b.id;
        if (editorBox) editorBox.style.display = '';
        if (nameInp) nameInp.value = b.name || '';
        if (roleSel) roleSel.value = (b.role || 'user');
        if (promptTxt) promptTxt.value = b.prompt || '';
      }

      if (addBtn) {
        addBtn.addEventListener('click', () => {
          const idv = 'b' + Date.now().toString(36);
          const nb = { id: idv, name: 'New Block', role: 'system', prompt: '', enabled: true, order: d2.blocks.length };
          d2.blocks.push(nb);
          sortAndReindex();
          renderList();
          syncNodeDataBlocks();
          openEditor(nb);
        });
      }

      if (saveBtn) {
        saveBtn.addEventListener('click', () => {
          if (!editingId) { if (editorBox) editorBox.style.display = 'none'; return; }
          const b = d2.blocks.find(x => (x.id || null) === editingId);
          if (b) {
            b.name = nameInp ? nameInp.value : b.name;
            b.role = roleSel ? roleSel.value : b.role || 'user';
            b.prompt = promptTxt ? promptTxt.value : b.prompt;
            // Пересоберём массив, чтобы избежать проблем с мутацией по ссылке
            d2.blocks = d2.blocks.map(x => (x.id === b.id ? ({ ...b }) : x));
          }
          if (editorBox) editorBox.style.display = 'none';
          editingId = null;
          renderList();
          syncNodeDataBlocks();
          // попытка автосохранения пайплайна, если доступна глобальная функция
          try { (typeof w.savePipeline === 'function') && w.savePipeline(); } catch (e) {}
          try { (typeof w.status === 'function') && w.status('Блок сохранён в pipeline.json'); } catch (e) {}
        });
      }

      if (cancelBtn) {
        cancelBtn.addEventListener('click', () => {
          if (editorBox) editorBox.style.display = 'none';
          editingId = null;
        });
      }

      // Первичная отрисовка
      renderList();
    } catch (e) {}
  }

  w.PM = {
    setupProviderCallPMUI
  };
})(window);