(function() {
    'use strict';

    window.IDVE = window.IDVE || {};

    IDVE.DragDrop = {
        dragging: null,
        placeholder: null,

        init: function() {
            var canvas = document.getElementById('idve-canvas');
            if (!canvas) return;

            canvas.addEventListener('dragstart', this.onDragStart.bind(this));
            canvas.addEventListener('dragover', this.onDragOver.bind(this));
            canvas.addEventListener('dragenter', this.onDragEnter.bind(this));
            canvas.addEventListener('dragleave', this.onDragLeave.bind(this));
            canvas.addEventListener('drop', this.onDrop.bind(this));
            canvas.addEventListener('dragend', this.onDragEnd.bind(this));
        },

        onDragStart: function(e) {
            var handle = e.target.closest('.idve-drag-handle');
            if (!handle) {
                e.preventDefault();
                return;
            }

            var draggable = handle.closest('[data-id]');
            if (!draggable) return;

            var id = draggable.getAttribute('data-id');
            var type = 'block';
            if (draggable.classList.contains('idve-editor-section')) type = 'section';
            else if (draggable.classList.contains('idve-editor-column')) type = 'column';

            this.dragging = { id: id, type: type, element: draggable };
            draggable.classList.add('idve-dragging');

            e.dataTransfer.effectAllowed = 'move';
            e.dataTransfer.setData('text/plain', JSON.stringify({ id: id, type: type }));
        },

        onDragOver: function(e) {
            if (!this.dragging) return;
            e.preventDefault();
            e.dataTransfer.dropEffect = 'move';

            var target = this.getDropTarget(e);
            if (!target) {
                this.removePlaceholder();
                return;
            }

            this.showPlaceholder(target.element, target.position);
        },

        onDragEnter: function(e) {
            if (!this.dragging) return;
            e.preventDefault();
        },

        onDragLeave: function(e) {
            // Only remove placeholder if leaving the canvas entirely
        },

        onDrop: function(e) {
            e.preventDefault();
            if (!this.dragging) return;

            var target = this.getDropTarget(e);
            if (!target) {
                this.cleanup();
                return;
            }

            var targetId = target.element.getAttribute('data-id');
            if (targetId === this.dragging.id) {
                this.cleanup();
                return;
            }

            IDVE.History.push();
            this.moveElement(this.dragging.id, this.dragging.type, targetId, target.type, target.position);
            IDVE.Editor.renderCanvas();
            IDVE.Editor.markDirty();
            this.cleanup();
        },

        onDragEnd: function() {
            this.cleanup();
        },

        cleanup: function() {
            if (this.dragging && this.dragging.element) {
                this.dragging.element.classList.remove('idve-dragging');
            }
            this.dragging = null;
            this.removePlaceholder();
        },

        getDropTarget: function(e) {
            if (!this.dragging) return null;

            var sourceType = this.dragging.type;
            var el;

            if (sourceType === 'section') {
                el = e.target.closest('.idve-editor-section');
                if (!el || el.getAttribute('data-id') === this.dragging.id) return null;
                var rect = el.getBoundingClientRect();
                var pos = (e.clientY - rect.top) < rect.height / 2 ? 'before' : 'after';
                return { element: el, type: 'section', position: pos };
            }

            if (sourceType === 'block') {
                // Try dropping on another block
                el = e.target.closest('.idve-editor-block');
                if (el && el.getAttribute('data-id') !== this.dragging.id) {
                    // Check if target is a group block and cursor is inside its content area
                    if (el.getAttribute('data-type') === 'group') {
                        var groupContent = el.querySelector('.idve-editor-group-content');
                        if (groupContent && groupContent.contains(e.target)) {
                            // Check if there's a deeper block inside the group
                            var innerBlock = e.target.closest('.idve-editor-block');
                            if (innerBlock && innerBlock !== el && innerBlock.getAttribute('data-id') !== this.dragging.id) {
                                var ibRect = innerBlock.getBoundingClientRect();
                                var ibPos = (e.clientY - ibRect.top) < ibRect.height / 2 ? 'before' : 'after';
                                return { element: innerBlock, type: 'block', position: ibPos };
                            }
                            // Drop inside the group itself
                            return { element: el, type: 'group', position: 'inside' };
                        }
                    }
                    var bRect = el.getBoundingClientRect();
                    var bPos = (e.clientY - bRect.top) < bRect.height / 2 ? 'before' : 'after';
                    return { element: el, type: 'block', position: bPos };
                }
                // Or on a column (empty column drop zone)
                el = e.target.closest('.idve-editor-column');
                if (el) {
                    return { element: el, type: 'column', position: 'inside' };
                }
            }

            if (sourceType === 'column') {
                el = e.target.closest('.idve-editor-column');
                if (!el || el.getAttribute('data-id') === this.dragging.id) return null;
                var cRect = el.getBoundingClientRect();
                var cPos = (e.clientX - cRect.left) < cRect.width / 2 ? 'before' : 'after';
                return { element: el, type: 'column', position: cPos };
            }

            return null;
        },

        showPlaceholder: function(targetEl, position) {
            this.removePlaceholder();
            var ph = document.createElement('div');
            ph.className = 'idve-drop-indicator';
            this.placeholder = ph;

            if (position === 'before') {
                targetEl.parentNode.insertBefore(ph, targetEl);
            } else if (position === 'after') {
                targetEl.parentNode.insertBefore(ph, targetEl.nextSibling);
            } else if (position === 'inside') {
                targetEl.appendChild(ph);
            }
        },

        removePlaceholder: function() {
            if (this.placeholder && this.placeholder.parentNode) {
                this.placeholder.parentNode.removeChild(this.placeholder);
            }
            this.placeholder = null;
        },

        moveElement: function(sourceId, sourceType, targetId, targetType, position) {
            var tree = IDVE.state.tree;

            // Find and remove source
            var source = this.findAndRemove(tree, sourceId, sourceType);
            if (!source) return;

            // Insert at target
            if (sourceType === 'section') {
                var targetIdx = -1;
                for (var i = 0; i < tree.sections.length; i++) {
                    if (tree.sections[i].id === targetId) {
                        targetIdx = i;
                        break;
                    }
                }
                if (targetIdx === -1) return;
                var insertIdx = position === 'before' ? targetIdx : targetIdx + 1;
                tree.sections.splice(insertIdx, 0, source);
            }

            if (sourceType === 'block') {
                if (position === 'inside') {
                    var container = IDVE.Editor.findElement(targetId);
                    if (container && container.element) {
                        if (!container.element.blocks) container.element.blocks = [];
                        container.element.blocks.push(source);
                    }
                } else {
                    this.insertNear(tree, targetId, source, position, 'blocks');
                }
            }

            if (sourceType === 'column') {
                this.insertNear(tree, targetId, source, position, 'columns');
            }
        },

        _removeFromBlocks: function(blocks, id) {
            for (var b = 0; b < blocks.length; b++) {
                if (blocks[b].id === id) {
                    return blocks.splice(b, 1)[0];
                }
                // Search inside group children
                if (blocks[b].type === 'group' && blocks[b].blocks) {
                    var found = this._removeFromBlocks(blocks[b].blocks, id);
                    if (found) return found;
                }
            }
            return null;
        },

        findAndRemove: function(tree, id, type) {
            if (type === 'section') {
                for (var i = 0; i < tree.sections.length; i++) {
                    if (tree.sections[i].id === id) {
                        return tree.sections.splice(i, 1)[0];
                    }
                }
            }
            if (type === 'block') {
                for (var s = 0; s < tree.sections.length; s++) {
                    var rows = tree.sections[s].rows || [];
                    for (var r = 0; r < rows.length; r++) {
                        var cols = rows[r].columns || [];
                        for (var c = 0; c < cols.length; c++) {
                            var found = this._removeFromBlocks(cols[c].blocks || [], id);
                            if (found) return found;
                        }
                    }
                }
            }
            if (type === 'column') {
                for (var s2 = 0; s2 < tree.sections.length; s2++) {
                    var rows2 = tree.sections[s2].rows || [];
                    for (var r2 = 0; r2 < rows2.length; r2++) {
                        var cols2 = rows2[r2].columns || [];
                        for (var c2 = 0; c2 < cols2.length; c2++) {
                            if (cols2[c2].id === id) {
                                return cols2.splice(c2, 1)[0];
                            }
                        }
                    }
                }
            }
            return null;
        },

        _insertInBlocks: function(blocks, targetId, source, position) {
            for (var b = 0; b < blocks.length; b++) {
                if (blocks[b].id === targetId) {
                    var idx = position === 'before' ? b : b + 1;
                    blocks.splice(idx, 0, source);
                    return true;
                }
                // Search inside group children
                if (blocks[b].type === 'group' && blocks[b].blocks) {
                    if (this._insertInBlocks(blocks[b].blocks, targetId, source, position)) return true;
                }
            }
            return false;
        },

        insertNear: function(tree, targetId, source, position, arrayKey) {
            for (var s = 0; s < tree.sections.length; s++) {
                var rows = tree.sections[s].rows || [];
                for (var r = 0; r < rows.length; r++) {
                    if (arrayKey === 'columns') {
                        var cols = rows[r].columns || [];
                        for (var c = 0; c < cols.length; c++) {
                            if (cols[c].id === targetId) {
                                var idx = position === 'before' ? c : c + 1;
                                cols.splice(idx, 0, source);
                                return;
                            }
                        }
                    }
                    if (arrayKey === 'blocks') {
                        var cols2 = rows[r].columns || [];
                        for (var c2 = 0; c2 < cols2.length; c2++) {
                            if (this._insertInBlocks(cols2[c2].blocks || [], targetId, source, position)) return;
                        }
                    }
                }
            }
        }
    };
})();
