// MNote filetree DND 运行时外置模块。
// 承接 filetree dragstart/dragover/drop/dragend 的业务逻辑，
// 不处理 page tree DND（留在 layout.rs）。
// inline script 保留完整 fallback。

// ─── 常量 ───────────────────────────────────────────────

var FILETREE_DRAG_MIME = 'application/x-mnote-file-tree';

// ─── 状态 ───────────────────────────────────────────────

var draggingFileTreeRowIds = [];
var activeFileTreeDropRow = null;

// ─── 纯 helper ─────────────────────────────────────────

function filetreeDragPayload(rowIds) {
  return JSON.stringify({
    type: 'mnote-file-tree-dnd',
    version: 1,
    rowIds: rowIds || draggingFileTreeRowIds,
  });
}

function filetreeDropDetail(targetRow, fileTree, deps) {
  deps = deps || {};
  var resolveWorkspaceId = deps.resolveWorkspaceId || function() { return ''; };
  var fileTreeRowLocalUploadTargetRelativePath = deps.fileTreeRowLocalUploadTargetRelativePath || function() { return ''; };
  return {
    workspaceId: resolveWorkspaceId(targetRow || fileTree),
    targetRowId: targetRow ? targetRow.getAttribute('data-row-id') : null,
    targetRowKind: targetRow ? targetRow.getAttribute('data-row-kind') : 'root',
    documentId: targetRow
      ? targetRow.getAttribute('data-document-id') || targetRow.getAttribute('data-doc-id')
      : null,
    assetId: targetRow ? targetRow.getAttribute('data-asset-id') : null,
    targetRelativePath: targetRow ? fileTreeRowLocalUploadTargetRelativePath(targetRow) : '',
    uploadIntent: 'filetree.folder.drop',
  };
}

function filetreeHasFiles(dataTransfer) {
  return dataTransfer && Array.prototype.indexOf.call(dataTransfer.types || [], 'Files') >= 0;
}

function filetreeHasInternalDrag(dataTransfer) {
  return dataTransfer && Array.prototype.indexOf.call(dataTransfer.types || [], FILETREE_DRAG_MIME) >= 0;
}

function parseFileTreeDragPayload(raw) {
  if (!raw) return [];
  try {
    var parsed = JSON.parse(raw);
    if (Array.isArray(parsed.rowIds)) return parsed.rowIds;
  } catch (_) {}
  return [];
}

function clearFileTreeDropFeedback() {
  if (activeFileTreeDropRow instanceof HTMLElement) {
    activeFileTreeDropRow.setAttribute('data-drop-target', 'false');
  }
  activeFileTreeDropRow = null;
}

function resetFileTreeDragState() {
  draggingFileTreeRowIds = [];
  clearFileTreeDropFeedback();
}

// ─── 文件树 DND 开始 ───────────────────────────────────

function startFileTreeDrag(fileRow, deps) {
  deps = deps || {};
  var selectedSidebarFileTreeRowIdsForDrag = deps.selectedSidebarFileTreeRowIdsForDrag || function(r) {
    return [r.getAttribute('data-row-id') || ''].filter(Boolean);
  };
  draggingFileTreeRowIds = selectedSidebarFileTreeRowIdsForDrag(fileRow);
  return {
    payload: filetreeDragPayload(draggingFileTreeRowIds),
    effectAllowed: 'copyMove',
  };
}

// ─── 文件树 DND 悬浮 ───────────────────────────────────

function handleFileTreeDragOver(event, deps) {
  deps = deps || {};
  var closestAction = deps.closestAction || function() { return null; };
  var fileTree = document.getElementById('sidebar-file-tree-root');
  if (!fileTree || !fileTree.contains(event.target)) return false;

  var hasFiles = filetreeHasFiles(event.dataTransfer);
  var hasInternal = filetreeHasInternalDrag(event.dataTransfer);
  if (!hasFiles && !hasInternal && draggingFileTreeRowIds.length === 0) return false;

  event.preventDefault();
  clearFileTreeDropFeedback();
  activeFileTreeDropRow = closestAction(event.target, '.tree-row[data-shell-mode="filetree"]') || fileTree;
  if (activeFileTreeDropRow instanceof HTMLElement) {
    activeFileTreeDropRow.setAttribute('data-drop-target', 'true');
  }
  if (event.dataTransfer) {
    var copyModifier = event.altKey || event.ctrlKey || event.metaKey;
    event.dataTransfer.dropEffect = hasFiles || copyModifier ? 'copy' : 'move';
  }
  return true;
}

// ─── 文件树 DND 释放 ───────────────────────────────────

function handleFileTreeDrop(event, deps) {
  deps = deps || {};
  var closestAction = deps.closestAction || function() { return null; };
  var resolveWorkspaceId = deps.resolveWorkspaceId || function() { return ''; };
  var fileTreeRowLocalUploadTargetRelativePath = deps.fileTreeRowLocalUploadTargetRelativePath
    || function() { return ''; };
  var ensureFileTreeWritableTarget = deps.ensureFileTreeWritableTarget || function() { return Promise.resolve(true); };
  var dispatchSidebarEvent = deps.dispatchSidebarEvent || function() {};
  var fileTree = document.getElementById('sidebar-file-tree-root');
  if (!fileTree || !fileTree.contains(event.target)) return;

  var targetRow = closestAction(event.target, '.tree-row[data-shell-mode="filetree"]');
  var files = event.dataTransfer ? Array.from(event.dataTransfer.files || []) : [];
  var raw = event.dataTransfer
    ? event.dataTransfer.getData(FILETREE_DRAG_MIME)
      || event.dataTransfer.getData('application/x-mnote-file-tree')
      || ''
    : '';
  var rowIds = draggingFileTreeRowIds.slice();
  if (raw) {
    rowIds = parseFileTreeDragPayload(raw);
  }
  if (!files.length && !rowIds.length) return;

  event.preventDefault();
  var detail = filetreeDropDetail(targetRow, fileTree, {
    resolveWorkspaceId: resolveWorkspaceId,
    fileTreeRowLocalUploadTargetRelativePath: fileTreeRowLocalUploadTargetRelativePath,
  });
  clearFileTreeDropFeedback();
  if (files.length) {
    dispatchSidebarEvent('tree.filetree.external-drop', Object.assign({}, detail, { files: files }));
  } else {
    var copyModifier = event.altKey === true || event.ctrlKey === true || event.metaKey === true;
    void Promise.resolve(ensureFileTreeWritableTarget('drop', targetRow, rowIds, copyModifier))
      .then(function(writable) {
        if (!writable) return;
        dispatchSidebarEvent('tree.filetree.internal-drop', Object.assign({}, detail, {
          rowIds: rowIds,
          copy: copyModifier,
        }));
      });
  }
  draggingFileTreeRowIds = [];
}

// ─── 导出 ───────────────────────────────────────────────

window.__mnoteFileTreeDndRuntime = {
  FILETREE_DRAG_MIME: FILETREE_DRAG_MIME,
  draggingFileTreeRowIds: draggingFileTreeRowIds,
  activeFileTreeDropRow: activeFileTreeDropRow,
  filetreeDragPayload: filetreeDragPayload,
  filetreeDropDetail: filetreeDropDetail,
  filetreeHasFiles: filetreeHasFiles,
  filetreeHasInternalDrag: filetreeHasInternalDrag,
  parseFileTreeDragPayload: parseFileTreeDragPayload,
  clearFileTreeDropFeedback: clearFileTreeDropFeedback,
  resetFileTreeDragState: resetFileTreeDragState,
  startFileTreeDrag: startFileTreeDrag,
  handleFileTreeDragOver: handleFileTreeDragOver,
  handleFileTreeDrop: handleFileTreeDrop,
};
