let _grid, _gridContainer, _dragGhostEl, _fileExplorerEl;
let _state, _cb, _onFolderDrop;
let _placeholder   = null;
let _dropTargetIdx = null;

let dragMode    = null;
let dragSrcIdx  = null;
let _hoveredTreeRow = null;

let autoScrollRAF   = null;
let autoScrollSpeed = 0;
let lastScrollTs    = null;

export function init({ grid, gridContainer, dragGhostEl, state, callbacks, fileExplorerEl, onFolderDrop }) {
  _grid           = grid;
  _gridContainer  = gridContainer;
  _dragGhostEl    = dragGhostEl;
  _state          = state;
  _cb             = callbacks;
  _fileExplorerEl = fileExplorerEl;
  _onFolderDrop   = onFolderDrop;

  _placeholder = document.createElement('div');
  _placeholder.className = 'card card-placeholder';
  const phLabel = document.createElement('div');
  phLabel.className = 'card-placeholder-label';
  _placeholder.appendChild(phLabel);
  _placeholder.addEventListener('dragover',  e => { e.preventDefault(); e.dataTransfer.dropEffect = 'move'; });
  _placeholder.addEventListener('dragenter', e => e.preventDefault());
  _placeholder.addEventListener('drop',      e => { e.preventDefault(); _performDrop(); });

  window.addEventListener('dragover', _onWindowDragOver);
  grid.addEventListener('dragover', _onGridDragOver);
  grid.addEventListener('drop',     _onGridDrop);

  if (fileExplorerEl) {
    fileExplorerEl.addEventListener('dragover',  _onExplorerDragOver);
    fileExplorerEl.addEventListener('dragleave', _onExplorerDragLeave);
    fileExplorerEl.addEventListener('drop',      _onExplorerDrop);
  }
}

export function setupCard(card) {
  card.addEventListener('dragstart', _onDragStart);
  card.addEventListener('dragover',  _onDragOver);
  card.addEventListener('dragenter', _onDragEnter);
  card.addEventListener('dragleave', _onDragLeave);
  card.addEventListener('drop',      _onDrop);
  card.addEventListener('dragend',   _onDragEnd);
}

// ── window-level dragover: 고스트 위치 + 자동 스크롤 ──

function _onWindowDragOver(e) {
  if (!dragMode) return;
  _moveGhost(e);
  _trackScroll(e.clientY);
}

// ── 카드 드래그 핸들러 ─────────────────────────────

function _onDragStart(e) {
  const idx = parseInt(this.dataset.idx);

  if (_state.selectedIdxs.has(idx) && _state.selectedIdxs.size > 1) {
    dragMode   = 'multi';
    dragSrcIdx = idx;

    const count  = _state.selectedIdxs.size;
    const toHide = [..._state.selectedIdxs].sort((a, b) => a - b);
    _placeholder.querySelector('.card-placeholder-label').textContent = `${count}개`;

    const img = new Image();
    img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
    e.dataTransfer.setDragImage(img, 0, 0);
    _showGhost(e, `📦 ${count}개 이동 중`);

    // 브라우저가 드래그 이미지를 캡처한 뒤 카드 숨기고 플레이스홀더 삽입
    requestAnimationFrame(() => {
      const firstCard = _getCardEl(toHide[0]);
      if (firstCard) _grid.insertBefore(_placeholder, firstCard);
      toHide.forEach(i => {
        const c = _getCardEl(i);
        if (c) c.classList.add('drag-hidden');
      });
    });
  } else {
    dragMode   = 'single';
    dragSrcIdx = idx;
    _placeholder.querySelector('.card-placeholder-label').textContent = '1개';
    _state.selectedIdxs.clear();
    _cb.refreshCardSelection();

    const srcCard = this;
    requestAnimationFrame(() => {
      _grid.insertBefore(_placeholder, srcCard);
      srcCard.classList.add('drag-hidden');
    });
  }

  e.dataTransfer.effectAllowed = 'move';
  e.dataTransfer.setData('text/plain', String(idx));
}

function _onDragOver(e) {
  e.preventDefault();
  e.dataTransfer.dropEffect = 'move';
}

function _onDragEnter(e) {
  e.preventDefault();
  const idx   = parseInt(this.dataset.idx);
  const isSrc = dragMode === 'single' ? idx === dragSrcIdx : _state.selectedIdxs.has(idx);
  if (isSrc) return;

  _dropTargetIdx = idx;

  // 플레이스홀더를 삽입될 위치로 이동
  if (dragMode === 'single' && dragSrcIdx < idx) {
    _grid.insertBefore(_placeholder, this.nextSibling); // 오른쪽으로 이동: 타겟 뒤
  } else {
    _grid.insertBefore(_placeholder, this);             // 왼쪽 이동 또는 multi: 타겟 앞
  }
}

function _onDragLeave() {
  // 플레이스홀더가 위치를 표시하므로 별도 처리 없음
}

function _onDrop(e) {
  e.preventDefault();
  _dropTargetIdx = parseInt(this.dataset.idx);
  _performDrop();
}

function _performDrop() {
  if (_dropTargetIdx === null) return;
  if (dragMode === 'single') {
    if (dragSrcIdx !== null && dragSrcIdx !== _dropTargetIdx) {
      _moveSingle(dragSrcIdx, _dropTargetIdx);
    }
  } else if (dragMode === 'multi') {
    if (!_state.selectedIdxs.has(_dropTargetIdx)) {
      _moveMulti(_dropTargetIdx);
    }
  }
}

function _onDragEnd() {
  _stopScroll();
  _hideGhost();
  _clearTreeHover();
  // 플레이스홀더 제거 및 숨긴 카드 복원 (_moveSingle/_moveMulti 에서 이미 처리했으면 no-op)
  if (_placeholder.parentNode) _placeholder.parentNode.removeChild(_placeholder);
  _dropTargetIdx = null;
  document.querySelectorAll('.card').forEach(c =>
    c.classList.remove('drag-hidden', 'drag-over')
  );
  dragMode   = null;
  dragSrcIdx = null;
}

// ── 폴더 탐색기 드롭 핸들러 ─────────────────────────

function _onExplorerDragOver(e) {
  if (!dragMode) return;
  e.preventDefault();
  e.dataTransfer.dropEffect = 'move';

  const row = e.target.closest('.tree-row');
  if (row !== _hoveredTreeRow) {
    _clearTreeHover();
    _hoveredTreeRow = row;
    if (_hoveredTreeRow) _hoveredTreeRow.classList.add('drop-target');
  }

  if (dragMode === 'single' && row && _dragGhostEl.style.display === 'none') {
    _showGhost(e, '📁 1개 폴더로 이동');
  }
  if (dragMode === 'multi' && row) {
    _dragGhostEl.textContent = `📁 ${_state.selectedIdxs.size}개 폴더로 이동`;
  }
}

function _onExplorerDragLeave(e) {
  if (!_fileExplorerEl.contains(e.relatedTarget)) {
    _clearTreeHover();
    if (dragMode === 'single') _hideGhost();
    if (dragMode === 'multi') _dragGhostEl.textContent = `📦 ${_state.selectedIdxs.size}개 이동 중`;
  }
}

function _onExplorerDrop(e) {
  e.preventDefault();
  const row = e.target.closest('.tree-row');
  _clearTreeHover();

  if (!row || !_onFolderDrop) return;
  const folderNode = row.closest('.tree-node');
  if (!folderNode) return;

  const targetPath = folderNode.dataset.path;
  const indices    = _getDraggedFileIndices();
  _onFolderDrop(targetPath, indices);
}

function _getDraggedFileIndices() {
  if (dragMode === 'multi') return [..._state.selectedIdxs];
  if (dragMode === 'single' && dragSrcIdx !== null) return [dragSrcIdx];
  return [];
}

function _clearTreeHover() {
  if (_hoveredTreeRow) {
    _hoveredTreeRow.classList.remove('drop-target');
    _hoveredTreeRow = null;
  }
}

// ── 그리드 빈 공간 드래그 핸들러 ─────────────────────

function _onGridDragOver(e) {
  if (!dragMode) return;
  if (e.target.closest('.card')) return;
  e.preventDefault();
  e.dataTransfer.dropEffect = 'move';

  _dropTargetIdx = _state.files.length;
  if (_grid.lastElementChild !== _placeholder) {
    _grid.appendChild(_placeholder);
  }
}

function _onGridDrop(e) {
  if (!dragMode) return;
  if (e.target.closest('.card')) return;
  e.preventDefault();
  _dropTargetIdx = _state.files.length;
  _performDrop();
}

// ── 이동 로직 ─────────────────────────────────────

function _moveSingle(srcIdx, targetIdx) {
  const [moved] = _state.files.splice(srcIdx, 1);
  _state.files.splice(targetIdx, 0, moved);

  // 플레이스홀더 제거 후 소스 카드 복원
  if (_placeholder.parentNode) _placeholder.parentNode.removeChild(_placeholder);
  const srcCard    = _getCardEl(srcIdx);
  const targetCard = _getCardEl(targetIdx);
  if (srcCard) srcCard.classList.remove('drag-hidden');

  if (srcCard) {
    if (targetCard) {
      if (srcIdx < targetIdx) {
        _grid.insertBefore(srcCard, targetCard.nextSibling);
      } else {
        _grid.insertBefore(srcCard, targetCard);
      }
    } else {
      _grid.appendChild(srcCard);
    }
  }

  Array.from(_grid.children).forEach((c, i) => { c.dataset.idx = i; });
  _cb.updateNumberBadges();
  _cb.updateNewNameLabels();
  _cb.pushHistory?.([moved.path]);
}

function _moveMulti(targetIdx) {
  const sorted     = [..._state.selectedIdxs].sort((a, b) => a - b);
  const movedFiles = sorted.map(i => _state.files[i]);

  const removedBefore  = sorted.filter(i => i < targetIdx).length;
  const adjustedTarget = targetIdx - removedBefore;

  for (let i = sorted.length - 1; i >= 0; i--) {
    _state.files.splice(sorted[i], 1);
  }
  _state.files.splice(adjustedTarget, 0, ...movedFiles);

  const newSel = new Set();
  for (let i = 0; i < movedFiles.length; i++) newSel.add(adjustedTarget + i);
  _state.selectedIdxs = newSel;

  // 플레이스홀더 제거, 숨긴 카드 복원 후 DOM 재정렬
  if (_placeholder.parentNode) _placeholder.parentNode.removeChild(_placeholder);
  const byPath = new Map();
  Array.from(_grid.children).forEach(c => {
    c.classList.remove('drag-hidden');
    byPath.set(c.dataset.filepath, c);
  });
  _grid.innerHTML = '';
  _state.files.forEach((f, idx) => {
    const c = byPath.get(f.path);
    if (c) { c.dataset.idx = idx; _grid.appendChild(c); }
  });

  _cb.updateNumberBadges();
  _cb.updateNewNameLabels();
  _cb.refreshCardSelection();
  _cb.updateSelCount();
  _cb.pushHistory?.(movedFiles.map(f => f.path));
}

// ── 자동 스크롤 ───────────────────────────────────

function _trackScroll(clientY) {
  const vh      = window.innerHeight;
  const topLine = vh * 0.1;
  const botLine = vh * 0.9;

  if (clientY < topLine) {
    const ratio = clientY / topLine;
    _startScroll(-vh * (1 - 0.8 * ratio));
  } else if (clientY > botLine) {
    const ratio = (clientY - botLine) / (vh * 0.1);
    _startScroll(vh * (0.2 + 0.8 * ratio));
  } else {
    _stopScroll();
  }
}

function _startScroll(speed) {
  autoScrollSpeed = speed;
  if (!autoScrollRAF) {
    lastScrollTs  = performance.now();
    autoScrollRAF = requestAnimationFrame(_tickScroll);
  }
}

function _stopScroll() {
  autoScrollSpeed = 0;
  if (autoScrollRAF) {
    cancelAnimationFrame(autoScrollRAF);
    autoScrollRAF = null;
  }
}

function _tickScroll(now) {
  if (!dragMode) { _stopScroll(); return; }
  const dt = (now - lastScrollTs) / 1000;
  lastScrollTs = now;
  _gridContainer.scrollTop += autoScrollSpeed * dt;
  autoScrollRAF = requestAnimationFrame(_tickScroll);
}

// ── 드래그 고스트 ─────────────────────────────────

function _showGhost(e, text) {
  _dragGhostEl.textContent = text;
  _dragGhostEl.style.display = 'block';
  _moveGhost(e);
}

function _moveGhost(e) {
  _dragGhostEl.style.left = (e.clientX + 16) + 'px';
  _dragGhostEl.style.top  = (e.clientY - 14) + 'px';
}

function _hideGhost() {
  _dragGhostEl.style.display = 'none';
}

function _getCardEl(idx) {
  return _grid.querySelector(`.card[data-idx="${idx}"]`);
}
