llmApp.directive('bsKeyValueList',['PLUGIN_PATHS',function (PLUGIN_PATHS) {
    return {
        restrict: 'E',
        scope: {
            config: '=',
            mappingsArray: '@',
            description: '@',
            labelText: '@',
            buttonLabel: '@',
            keyPlaceholder: '@',
            valuePlaceholder: '@'
        },
        templateUrl: PLUGIN_PATHS.WEBAPP +'bs-key-value-list.html',
        link: function (scope, element) {
            // Initialize from config if available
            if (!scope.languageMappings) {
                scope.languageMappings = scope.config && scope.config[scope.mappingsArray] ? scope.config[scope.mappingsArray] : [];
            }

            scope.isArray = Array.isArray(scope.languageMappings);


            // Reference to container element
            var container = element[0].querySelector('.language-mappings-container');
            var draggedItem = null;
            var draggedIndex = null;

            // Watch for external changes to mappings
            scope.$watch('config[mappingsArray]', function (newValue) {
                if (newValue && Array.isArray(newValue)) {
                    scope.languageMappings = newValue;
                }
            });


            // Add proper event listeners to the container items
            function initDragHandlers() {
                var items = container.querySelectorAll('.language-mapping-item');

                items.forEach(function (item, index) {
                    // Set dragstart handler
                    item.addEventListener('dragstart', function (e) {
                        draggedItem = item;
                        draggedIndex = index;
                        e.dataTransfer.setData('text/plain', index);
                        e.dataTransfer.effectAllowed = 'move';
                        setTimeout(function () {
                            item.classList.add('dragging');
                            item.style.opacity = '0.5';
                        }, 0);
                    });

                    // Set dragend handler
                    item.addEventListener('dragend', function () {
                        cleanupStyling();
                        draggedItem = null;
                        draggedIndex = null;
                    });

                    // Set dragover handler
                    item.addEventListener('dragover', function (e) {
                        e.preventDefault();
                        e.dataTransfer.dropEffect = 'move';

                        if (item === draggedItem) return;

                        // Clear previous indicators
                        cleanupIndicators();

                        // Determine drop position
                        var rect = item.getBoundingClientRect();
                        var beforeTarget = e.clientY < rect.top + (rect.height / 2);

                        // Add visual indicator
                        if (beforeTarget) {
                            item.classList.add('drop-before');
                        } else {
                            item.classList.add('drop-after');
                        }
                    });

                    // Set drop handler
                    item.addEventListener('drop', function (e) {
                        e.preventDefault();
                        e.stopPropagation();

                        if (draggedItem === null) return;

                        var sourceIndex = draggedIndex;
                        var targetIndex = index;

                        // Determine drop position
                        var rect = item.getBoundingClientRect();
                        var beforeTarget = e.clientY < rect.top + (rect.height / 2);

                        // Calculate final position
                        var dropIndex = beforeTarget ? targetIndex : targetIndex + 1;

                        // Move the item in the array
                        scope.$applyAsync(function () {
                            moveItem(sourceIndex, dropIndex);
                        });

                        cleanupStyling();
                    });
                });
            }

            // Add drop handling to the container for empty state
            container.addEventListener('dragover', function (e) {
                e.preventDefault();
                e.dataTransfer.dropEffect = 'move';
            });

            container.addEventListener('drop', function (e) {
                // Only handle drops directly on the container (not on items)
                if (e.target === container) {
                    e.preventDefault();
                    e.stopPropagation();

                    if (draggedItem === null) return;

                    // Move to the end of the list
                    scope.$applyAsync(function () {
                        moveItem(draggedIndex, scope.languageMappings.length);
                    });

                    cleanupStyling();
                }
            });

            // Clean up styling and indicators
            function cleanupStyling() {
                var items = container.querySelectorAll('.language-mapping-item');
                items.forEach(function (item) {
                    item.classList.remove('drop-before');
                    item.classList.remove('drop-after');
                    item.classList.remove('dragging');
                    item.style.opacity = '1';
                });
            }

            function cleanupIndicators() {
                var items = container.querySelectorAll('.language-mapping-item');
                items.forEach(function (item) {
                    item.classList.remove('drop-before');
                    item.classList.remove('drop-after');
                });
            }

            // Move item in the array
            function moveItem(fromIndex, toIndex) {
                if (fromIndex === toIndex) return;

                var itemToMove = scope.languageMappings[fromIndex];
                var newMappings = scope.languageMappings.slice();

                // Remove from original position
                newMappings.splice(fromIndex, 1);

                // Adjust target position if needed
                if (toIndex > fromIndex) {
                    toIndex--;
                }

                // Insert at new position
                newMappings.splice(toIndex, 0, itemToMove);

                // Update the array
                scope.languageMappings = newMappings;
            }

            // Initialize drag handlers when the DOM updates
            scope.$watchCollection('languageMappings', function () {
                // Use timeout to ensure DOM has updated
                setTimeout(function () {
                    initDragHandlers();
                }, 0);
            });

            // Initialize handlers on load
            setTimeout(function () {
                initDragHandlers();
            }, 0);
        },
        controller: ['$scope', function ($scope) {
            $scope.addMapping = function () {
                if ($scope.isArray) {
                    $scope.languageMappings.push({from: '', to: ''});
                } else {
                    // Just add with empty key - user can edit it directly
                    $scope.languageMappings[''] = '';
                }
            };

            $scope.removeMapping = function (indexOrKey) {
                if ($scope.isArray) {
                    $scope.languageMappings.splice(indexOrKey, 1);
                } else {
                    delete $scope.languageMappings[indexOrKey];
                }
            };

            $scope.updateKey = function (oldKey, newKey) {
                // Skip if no change
                if (oldKey === newKey) return;

                // Validate new key
                if (!newKey || newKey.trim() === '') {
                    // If emptying an existing key, remove the mapping
                    if (oldKey !== '') {
                        delete $scope.languageMappings[oldKey];
                    }
                    return;
                }

                newKey = newKey.trim();

                // Prevent duplicate keys
                if ($scope.languageMappings.hasOwnProperty(newKey) && newKey !== oldKey) {
                    return; // Could show error message here
                }

                // Move the value to new key
                const value = $scope.languageMappings[oldKey];
                delete $scope.languageMappings[oldKey];
                $scope.languageMappings[newKey] = value;
            };
        }]

    };
}]);
