llmApp.directive('bsObjectList', ['PythonService', 'ParamsHelperService', 'DescParamsService', 'PLUGIN_PATHS', 'SharedPromiseService', function (PythonService, ParamsHelperService, DescParamsService, PLUGIN_PATHS, SharedPromiseService) {
    return {
        restrict: 'E',
        templateUrl: PLUGIN_PATHS.WEBAPP + 'bs-object-list-template.html',
        scope: {
            config: '=',
            formName: '=',
            configProperty: '@',
            rootModel: '=',
            collapsableContentIds: '=',
            // opt-in features (used only in Enterprise Agents)
            headerParam: '@?',         // e.g. "agent_id" or "augmented_llm_id"
            hideHeaderField: '=?',     // hide the headerParam field inside the row
            anchorPrefix: '@?',        // stable DOM id prefix (ea-agent / ea-rag)
            collapsible: '=?',         // enable collapse/expand
            collapseByDefault: '=?',   // initial collapsed state
            onRemove: '&?',           // callback when a row is deleted
            buttonLabel: '@?',         // label for the "Add" button (default: "Add Item")
            description: '@?',
            headerLabel :'@?'
        },
        controller: ['$scope', '$compile', function ($scope, $compile) {
            $scope.fieldConfig = DescParamsService.getParamConfigByName($scope.configProperty);

            // flags
            $scope.anchorPrefix = $scope.anchorPrefix || ($scope.configProperty || 'row');
            $scope.collapsible = !!$scope.collapsible;
            $scope.collapseByDefault = !!$scope.collapseByDefault;
            $scope._collapsed = [];

            $scope.getCollapsableContentDivs = function (param, item) {
                const ids = $scope.collapsableContentIds;
                if (!ids || !Array.isArray(ids) || !ids.includes(param.name)) return {};
                const visibleHeaderFields = $scope.fieldConfig.subParams.filter(p =>
                    ids.includes(p.name) && $scope.isFieldVisible(p, item)
                );
                if (visibleHeaderFields.length === 0) return {};
                const headerIndex = visibleHeaderFields.findIndex(p => p.name === param.name);
                if (headerIndex === -1) return {};
                const isFirst = (headerIndex === 0);
                const isLast = (headerIndex === visibleHeaderFields.length - 1);
                return {'!bg-zinc-50': true, '!p-4': true, '!rounded-t-lg': isFirst, '!rounded-b-lg': isLast};
            };

            // header label (choices)
            const _headerChoicesByValue = {};

            function loadHeaderChoicesIfNeeded() {
                if (!$scope.headerParam) return;
                const headerDef = $scope.fieldConfig.subParams.find(p => p.name === $scope.headerParam);
                if (!headerDef || !headerDef.getChoicesFromPython) return;
                ParamsHelperService.do({
                    parameterName: $scope.headerParam,
                    rootModel: $scope.rootModel || $scope.config
                })
                    .then(function (res) {
                        const arr = (res && res.choices) ? res.choices : [];
                        arr.forEach(function (c) {
                            if (c && c.value) _headerChoicesByValue[c.value] = c.label || c.value;
                        });
                    }).catch(function () {
                });
            }

            $scope.getHeaderLabel = function (item) {
                if (!$scope.headerParam) return null;
                const val = item && item[$scope.headerParam];
                if (val == null) return null;
                return _headerChoicesByValue[val] || ('' + val);
            };

            // anchors & collapse
            $scope.rowAnchorId = function (index) {
                return ($scope.anchorPrefix || 'row') + '-' + index;
            };
            $scope.isRowCollapsed = function (index) {
                return !!$scope._collapsed[index];
            };
            $scope.toggleRow = function (index) {
                if ($scope.collapsible) $scope._collapsed[index] = !$scope._collapsed[index];
            };

            // mapping
            const FIELD_TYPE_MAPPING = {
                'SELECT': 'bs-select',
                'TEXTAREA': 'bs-textarea',
                'LLM': 'bs-llm-select',
                'ARRAY': 'bs-array',
                'SEPARATOR': null
            };
            $scope.getDirectiveName = function (fieldType) {
                return FIELD_TYPE_MAPPING[fieldType];
            };

            $scope.initializeTriggerParameters = function () {
                if ($scope.fieldConfig.triggerParameters && $scope.fieldConfig.triggerParameters.length > 0) {
                    $scope.triggerParametersArray = [];
                    $scope.fieldConfig.triggerParameters.forEach(function (param) {
                        const sourceModel = $scope.rootModel || $scope.config;
                        $scope.triggerParametersArray.push({
                            get value() {
                                return sourceModel[param];
                            }
                        });
                    });
                } else {
                    $scope.triggerParametersArray = null;
                }
            };
            $scope.isFieldVisible = function (param, item) {
                const condition = param.visibilityCondition;
                if (!condition) return true;
                try {
                    return $scope.$eval(condition, {model: item});
                } catch (e) {
                    console.warn('Visibility error:', e);
                    return false;
                }
            };

            $scope.initializeList = function () {
                if (!$scope.config[$scope.configProperty]) $scope.config[$scope.configProperty] = [];
            };

            $scope.createNewObject = function () {
                const newObject = {};
                $scope.fieldConfig.subParams.forEach(function (param) {
                    if (param.type !== 'SEPARATOR') {
                        switch (param.type) {
                            case 'STRING':
                                newObject[param.name] = '';
                                break;
                            case 'SELECT':
                            case 'LLM':
                                newObject[param.name] = null;
                                break;
                            case 'TEXTAREA':
                                newObject[param.name] = '';
                                break;
                            case 'BOOLEAN':
                                newObject[param.name] = false;
                                break;
                            case 'ARRAY':
                                newObject[param.name] = [];
                                break;
                            default:
                                newObject[param.name] = null;
                        }
                    }
                });
                if ($scope.collapsible) $scope._collapsed.push($scope.collapseByDefault);
                return newObject;
            };

            $scope.addModel = function () {
                $scope.config[$scope.configProperty].push($scope.createNewObject());
            };

            $scope.removeModel = function (index) {
                const removed = $scope.config[$scope.configProperty][index];
                $scope.config[$scope.configProperty].splice(index, 1);
                if ($scope.collapsible) $scope._collapsed.splice(index, 1);
                if ($scope.onRemove) {
                    try {
                        $scope.onRemove({item: removed, index: index});
                    } catch (e) {
                    }
                }
            };

            $scope.hasValidationErrors = function () {
                const list = $scope.config[$scope.configProperty];
                if (!list || list.length === 0) return false;
                return list.some(function (item) {
                    return $scope.fieldConfig.subParams.some(function (param) {
                        if (!param.mandatory) return false;
                        const value = item[param.name];
                        if (param.type === 'ARRAY') {
                            return !value || value.length === 0;
                        }
                        return !value || (typeof value === 'string' && value.trim() === '');
                    });
                });
            };

            $scope.getValidationMessage = function () {
                if ($scope.hasValidationErrors()) {
                    const mandatoryFields = $scope.fieldConfig.subParams.filter(p => p.mandatory).map(p => p.label).join(', ');
                    return `Please fill in all required fields: ${mandatoryFields}`;
                }
                return "";
            };

            $scope.isVisible = function () {
                if (!$scope.fieldConfig.visibilityCondition) return true;
                try {
                    return $scope.$eval($scope.fieldConfig.visibilityCondition, {model: $scope.rootModel || $scope.config});
                } catch (e) {
                    console.warn('Visibility condition error:', e);
                    return true;
                }
            };

            $scope.getFieldAttributes = function (param) {
                const attributes = {
                    'config': 'item',
                    'form-name': 'formName',
                    'config-property': param.name,
                    'label-text': param.label,
                    'field-required': param.mandatory || false
                };
                if (param.description) attributes['description'] = param.description;
                if ($scope.fieldConfig.triggerParameters && $scope.fieldConfig.triggerParameters.length > 0) {
                    const triggerArray = $scope.fieldConfig.triggerParameters.map(function (t) {
                        return 'config.' + t;
                    });
                    attributes['trigger-parameter'] = triggerArray;
                }
                switch (param.type) {
                    case 'SELECT':
                        if (param.getChoicesFromPython) attributes['get-choices-from-python'] = 'true';
                        attributes['root-model'] = 'rootModel || config';
                        break;
                    case 'TEXTAREA':
                        attributes['initial-width'] = '100%';
                        attributes['initial-height'] = '120px';
                        if (param.placeholder) attributes['placeholder'] = param.placeholder;
                        break;
                    case 'LLM':
                        break;
                }
                return attributes;
            };

            $scope.getTriggerParameters = function () {
                if ($scope.fieldConfig.triggerParameters && $scope.fieldConfig.triggerParameters.length > 0) {
                    return $scope.fieldConfig.triggerParameters.map(function (param) {
                        return 'config.' + param;
                    });
                }
                return null;
            };

            if ($scope.fieldConfig.triggerParameters) {
                $scope.fieldConfig.triggerParameters.forEach(function (param) {
                    $scope.$watch(function () {
                        return $scope.rootModel ? $scope.rootModel[param] : $scope.config[param];
                    }, function (newValue, oldValue) {
                        if (newValue !== oldValue) {
                            $scope.$broadcast('triggerParameterChanged', param, newValue);
                            loadHeaderChoicesIfNeeded();
                        }
                    }, true);
                });
            }

            // init
            $scope.initializeList();
            $scope.initializeTriggerParameters();
            loadHeaderChoicesIfNeeded();
            if ($scope.collapsible && $scope.config[$scope.configProperty]) {
                $scope._collapsed = $scope.config[$scope.configProperty].map(function () {
                    return $scope.collapseByDefault;
                });
            }
        }]
    };
}]);
