function createController(settings) {
    var controller = adminApp.controller(
        settings.name,
        function (
            $scope,
            $http,
            $window,
            $element,
            $uibModal,
            $timeout,
            $sce,
            $q
        ) {
            $scope.controllerElement = $element;
            $scope.selectedItem = null;
            $scope.primaryKey = 'Id';
            $scope.parseInt = parseInt;
            $scope.canceler = null;


            if (settings.inlineEdit) {
                $scope.clickRow = function (item, $event, isEditButton) {
                    if (item === $scope.selectedItem) return;

                    // don't handle save button clicks, they are deselects
                    if (
                        !isEditButton &&
                        ($event.target.tagName.toLowerCase() === 'button' ||
                            $event.target.tagName.toLowerCase() === 'i' ||
                            $event.target.tagName.toLowerCase() === 'a')
                    )
                        return;

                    var tr = null;
                    if (item) {
                        tr = $($event.currentTarget);
                    }
                    if (isEditButton) {
                        tr = $($event.currentTarget).closest('tr');
                    }

                    if ($scope.selectedItem != null) {
                        $scope.cancel();
                        selectItem(item, tr);
                    } else {
                        selectItem(item, tr);
                    }
                };

                bindDeselectOnWindowClick();
            }

            if (settings.inlineAdd) {
                $scope.addRow = function () {
                    var item = {};
                    if (settings.setInitialValues) {
                        settings.setInitialValues(item);
                    }
                    var tr = null;
                    $scope.items.unshift(item);
                    if ($scope.selectedItem != null) {
                        saveSelectedItem(function () {
                            selectItem(item, tr);
                        });
                    } else {
                        selectItem(item, tr);
                    }
                };
            }

            function selectItem(item, tr) {
                if (item) {
                    $scope.selectedItem = item;
                    if (tr != null) {
                        var firstInput = tr.find('input');
                        firstInput.trigger('focus');
                    }
                    if (settings.onEditStarted) {
                        settings.onEditStarted();
                    }
                } else {
                    $scope.selectedItem = null;
                }
            }

            function bindDeselectOnWindowClick() {
                var w = angular.element($window);
                w.on('click', function (e) {
                    var clickInGrid = $($scope.controllerElement).has(
                        $(e.target)
                    ).length;
                    if (!clickInGrid) {
                        $scope.$apply(function () {
                            $scope.cancel();
                        });
                    }
                });
            }

            LocalStorageCacheKey = 'GridPaging-Admin';
            LocalStorageVersion = 1.0;

            function getSavedPageSize() {
                const cachedState = getCache(LocalStorageCacheKey);

                if (!cachedState) return;
                return cachedState.pageSize;
            }

            function saveCache(key, data) {
                const now = new Date();
                localStorage.setItem(
                    key,
                    JSON.stringify({
                        version: LocalStorageVersion,
                        timestamp:
                            now.getTime() + now.getTimezoneOffset() * 60000,
                        data: data,
                    })
                );
            }

            function getCache(key, updatedOn) {
                const cachedJson = localStorage.getItem(key);

                if (cachedJson) {
                    const cachedState = JSON.parse(cachedJson);
                    const updatedOnDate = Date.parse(updatedOn) || 0;

                    if (
                        cachedState.version === LocalStorageVersion &&
                        updatedOnDate < cachedState.timestamp
                    ) {
                        return cachedState.data;
                    }
                    // Cache invalidated. Changes from server are newer.
                    localStorage.removeItem(key);
                    return null;
                }
            }

            function initPage() {
                if (settings.primaryKey) {
                    $scope.primaryKey = settings.primaryKey;
                }
                $scope.pageCount = 0;
                $scope.filteredCount = 0;
                $scope.totalCount = 0;
                $scope.pageIndex = 1;
                $scope.pageSize = getSavedPageSize();

                if (!$scope.pageSize) {
                    if (settings.pageSize) {
                        $scope.pageSize = settings.pageSize.toString();
                    } else {
                        $scope.pageSize = $scope.getResource(
                            'DefaultGridPageSize'
                        );
                    }
                }
                $scope.pageSizeOptions = [15, 20, 25, 50, 100, 1000];
                $scope.paginatorSize = 8;
                $scope.pageCount = 10;
            }

            function showErrorMessage(errorMessage) {
                $('.notifications-main').html(
                    '<div class="alert alert-danger alert-dismissible fade show">' +
                    errorMessage +
                    '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-hidden="true"></button></div>'
                );
            }

            function refreshData() {
                $scope.canceler = $q.defer();
                var postData = {
                    command: {
                        current: $scope.pageIndex,
                        rowcount: $scope.pageSize,
                        searchPhrase: '',
                    },
                };

                if (settings.getAdditionalPostdata) {
                    var additionalPostData = {
                        model: settings.getAdditionalPostdata(),
                    };
                    postData = angular.merge(postData, additionalPostData);
                    var searchPhrase = postData.model.SearchProductName;
                    if (
                        searchPhrase != null &&
                        searchPhrase !== '' &&
                        searchPhrase.length < 3
                    ) {
                        return;
                    }
                }

                const httpOptions = {
                    headers: {
                        __RequestVerificationToken: $(
                            'input[name=__RequestVerificationToken]'
                        ).val(),
                    },
                    timeout: $scope.canceler.promise,
                };

                $http
                    .post(settings.listUrl, postData, httpOptions)
                    .then(function (res) {
                        if (res && res.data) {
                            var data = res.data;
                            $scope.items = data.Rows;
                            $scope.pageSize = data.RowCount;
                            $scope.pageIndex = data.Current;
                            $scope.filteredCount = data.Total;
                            $scope.totalCount = data.Total;
                            $scope.pageCount = Math.ceil(
                                data.Total / data.RowCount
                            );
                            pendingRequest = false;
                            deferredRequest = $q.defer();

                            if (data.Total === 0) {
                                $($element).find('.no-items').fadeIn();
                            } else {
                                $($element).find('.no-items').hide();
                            }
                            if (settings.onLoaded) {
                                settings.onLoaded();
                            }
                        }
                    })
                    .catch(function (data) {
                        // If the status === -1 it has been canceled
                        if (data && data.status !== -1) {
                            console.error(
                                `Error with request to ${data.config.url}`
                            );
                        }
                    });
            }

            $scope.updatePagesize = function () {
                saveCache(LocalStorageCacheKey, { pageSize: $scope.pageSize });
                if ($scope.canceler) {
                    $scope.canceler.resolve('Canceled');
                }
                refreshData();
            };

            $scope.isAdding = function () {
                var isIdKey =
                    $scope.primaryKey.indexOf(
                        'Id',
                        $scope.primaryKey.length - 'Id'.length
                    ) !== -1;

                if (!isIdKey) {
                    return !(
                        !$scope.selectedItem ||
                        $scope.selectedItem[$scope.primaryKey].length > 0
                    );
                } else {
                    return !(
                        !$scope.selectedItem ||
                        $scope.selectedItem[$scope.primaryKey] > 0
                    );
                }
            };

            $scope.refreshData = refreshData;

            function saveSelectedItem(success) {
                if (!$scope.selectedItem) {
                    if (success) success();
                    return;
                }

                $scope.saveItem($scope.selectedItem, success);
            }

            $scope.saveItem = function (item, success) {
                if (!success) {
                    success = function () { };
                }

                var url;
                if (!$scope.isAdding()) {
                    url = settings.saveUrl;
                } else {
                    url = settings.insertUrl;
                    success = function () {
                        $scope.cancel();
                        if ($scope.canceler) {
                            $scope.canceler.resolve('Canceled');
                        }
                        $scope.refreshData();
                    };
                }
                if (success) {
                    success();
                }

                $http({
                    method: 'POST',
                    url: url,
                    data: { model: item },
                    headers: {
                        'Content-Type': 'application/json',
                        __RequestVerificationToken: $(
                            'input[name=__RequestVerificationToken]'
                        ).val(),
                    },
                }).then(function () {
                    showSaveSuccess(item);
                    if ($scope.canceler) {
                        $scope.canceler.resolve('Canceled');
                    }
                    $scope.refreshData();
                });
            };

            function showSaveSuccess(item) {
                item.issavesuccess = true;
                $timeout(function () {
                    item.issavesuccess = false;
                }, 5000);
            }

            function setOnTargetWindow(
                targetWindow,
                openerId,
                nameId,
                btnId,
                name,
                id,
                itemMap,
                item
            ) {
                if (!targetWindow) return;
                try {
                    var inputNode = targetWindow.document.getElementById(
                        openerId
                    );
                    var nameNode = targetWindow.document.getElementById(nameId);
                    var buttonNode = targetWindow.document.getElementById(
                        btnId
                    );
                    if (inputNode) inputNode.value = id;
                    if (nameNode) nameNode.innerText = name;
                    if (buttonNode) buttonNode.click();
                    if ('postMessage' in window) {
                        targetWindow.postMessage(
                            {
                                openerId: openerId,
                                nameId: nameId,
                                item: itemMap,
                                rawItem: item,
                            },
                            location.origin
                        );
                    }
                    window.close();
                } catch (e) {
                    console.error(e);
                }
            }

            $scope.selectRequiredProduct = function (item, openerId, btnId) {
                try {
                    var currentValue = window.opener.document.getElementById(
                        openerId
                    ).value;
                    if (currentValue) {
                        //add comma
                        window.opener.document.getElementById(openerId).value +=
                            ', ';
                    }
                    window.opener.document.getElementById(openerId).value +=
                        item.Id;
                    window.opener.document.getElementById(btnId).click();
                    window.close();
                } catch (e) { }
                try {
                    var currentValue = window.parent.document.getElementById(
                        openerId
                    ).value;
                    if (currentValue) {
                        //add comma
                        window.parent.document.getElementById(openerId).value +=
                            ', ';
                    }
                    window.parent.document.getElementById(openerId).value +=
                        item.Id;
                    window.parent.document.getElementById(btnId).click();
                } catch (e) {
                    console.error(e);
                }
                parent.$.fancybox.close();
            };

            $scope.selectRequiredProductWithName = function (
                item,
                openerId,
                btnId,
                productNameId
            ) {
                var name = item.Name || item.Title;
                var itemMap = {
                    id: item.Id,
                    name: name,
                    sku: item.Sku,
                    price: item.Price,
                };
                setOnTargetWindow(
                    window.opener,
                    openerId,
                    productNameId,
                    btnId,
                    name,
                    item.Id,
                    itemMap,
                    item
                );
                setOnTargetWindow(
                    window.parent,
                    openerId,
                    productNameId,
                    btnId,
                    name,
                    item.Id,
                    itemMap,
                    item
                );
                window.parent.$.fancybox.close();
            };
            $scope.selectRequiredUserWithName = function (
                item,
                openerId,
                btnId,
                topicNameId
            ) {
                var name = item.FirstName + ' ' + item.LastName;
                var itemMap = {
                    id: item.Id,
                    name: name,
                };
                setOnTargetWindow(
                    window.opener,
                    openerId,
                    topicNameId,
                    btnId,
                    name,
                    item.Id,
                    itemMap,
                    item
                );
                setOnTargetWindow(
                    window.parent,
                    openerId,
                    topicNameId,
                    btnId,
                    name,
                    item.Id,
                    itemMap,
                    item
                );
                window.parent.$.fancybox.close();
            };

            $scope.selectRequiredTopicWithName = function (
                item,
                openerId,
                btnId,
                topicNameId
            ) {
                var name = item.SystemName + ' - ' + item.Title;
                var itemMap = {
                    id: item.Id,
                    name: name,
                };
                setOnTargetWindow(
                    window.opener,
                    openerId,
                    topicNameId,
                    btnId,
                    name,
                    item.Id,
                    itemMap,
                    item
                );
                setOnTargetWindow(
                    window.parent,
                    openerId,
                    topicNameId,
                    btnId,
                    name,
                    item.Id,
                    itemMap,
                    item
                );
                window.parent.$.fancybox.close();
            };

            $scope.windowOpen = function (id) {
                var newUrl = settings.editUrl.replace('{{item.Id}}', id);
                $window.open(newUrl, 'New Window', settings.popupOptions);
            };

            $scope.windowOpenFancybox = function (id) {
                var newUrl = settings.editUrl.replace('{{item.Id}}', id);

                $.fancybox.open({
                    src: newUrl,
                    type: 'iframe',
                    opts: {
                        iframe: {
                            css: {
                                width: 800,
                                height: 600,
                            },
                        },
                    },
                });
            };

            $scope.rawHtml = function (value) {
                return $sce.trustAsHtml(value);
            };

            $scope.openWindowInline = function ($event) {
                var url = $($event.target).data('url');
                $window.open(
                    url,
                    'New Window',
                    'width=800,height=350,resizable=1'
                );
                return false;
            };

            $scope.setPage = function (pageNo) {
                $scope.pageIndex = pageNo * $scope.pageSize;
            };

            $scope.pageChanged = function () {
                if ($scope.canceler) {
                    $scope.canceler.resolve('Canceled');
                }
                refreshData();
            };

            $scope.save = function () {
                saveSelectedItem(function () {
                    selectItem(null, null);
                });
            };

            $scope.cancel = function () {
                if ($scope.isAdding()) {
                    var index = $scope.items.indexOf($scope.selectedItem);
                    $scope.items.splice(index, 1);
                }

                $scope.selectedItem = null;
            };

            $scope.delete = function (id) {
                // remove from angular grid before removing from database and refreshing grid
                for (i = 0; i < $scope.items.length; i++) {
                    var item = $scope.items[i];
                    if (item.Id === id) {
                        $scope.items.splice(i, 1);
                        break;
                    }
                }

                $http
                    .post(
                        settings.deleteUrl,
                        { id: id },
                        {
                            headers: {
                                __RequestVerificationToken: $(
                                    'input[name=__RequestVerificationToken]'
                                ).val(),
                            },
                        }
                    )
                    .then(function () {
                        if (
                            $scope.selectedItem &&
                            $scope.selectedItem.Id === id
                        ) {
                            $scope.cancel();
                        }

                        if ($scope.canceler) {
                            $scope.canceler.resolve('Canceled');
                        }
                        refreshData();
                        if (settings.afterDelete) {
                            settings.afterDelete(id);
                        }
                    });
            };

            $scope.getSelectedItemsForAction = function () {
                var selectedItemsForAction = [];
                angular.forEach($scope.items, function (item, key) {
                    if (item.selectedForAction) {
                        selectedItemsForAction.push(item.Id);
                    }
                });
                return selectedItemsForAction;
            };

            $scope.deleteSelected = function () {
                $http
                    .post(
                        settings.deleteAllUrl,
                        { selectedIds: $scope.getSelectedItemsForAction() },
                        {
                            headers: {
                                __RequestVerificationToken: $(
                                    'input[name=__RequestVerificationToken]'
                                ).val(),
                            },
                        }
                    )
                    .then(
                        function successCallback() {
                            refreshData();
                        },
                        function errorCallback(response) {
                            showErrorMessage(response.data.Message);
                            refreshData();
                        }
                    );
            };

            $scope.publishSelected = function () {
                $http
                    .post(
                        settings.publishAllUrl,
                        { selectedIds: $scope.getSelectedItemsForAction() },
                        {
                            headers: {
                                __RequestVerificationToken: $(
                                    'input[name=__RequestVerificationToken]'
                                ).val(),
                            },
                        }
                    )
                    .then(
                        function successCallback() {
                            refreshData();
                        },
                        function errorCallback(response) {
                            showErrorMessage(response.data.Message);
                            refreshData();
                        }
                    );
            };

            $scope.unpublishSelected = function () {
                $http
                    .post(
                        settings.unpublishAllUrl,
                        { selectedIds: $scope.getSelectedItemsForAction() },
                        {
                            headers: {
                                __RequestVerificationToken: $(
                                    'input[name=__RequestVerificationToken]'
                                ).val(),
                            },
                        }
                    )
                    .then(
                        function successCallback() {
                            refreshData();
                        },
                        function errorCallback(response) {
                            showErrorMessage(response.data.Message);
                            refreshData();
                        }
                    );
            };

            $scope.restartUrl = settings.restartUrl;
            $scope.editUrl = settings.editUrl;
            $scope.editUrlExtra = settings.editUrlExtra;
            $scope.viewUrl = settings.viewUrl;
            $scope.resources = loadAngularSettings();
            $scope.getResource = function (key) {
                return $scope.resources[key];
            };

            $scope.confirmdelete = function (id) {
                $scope.confirmDeleteId = id;
                var modalInstance = $uibModal.open({
                    animation: $scope.animationsEnabled,
                    templateUrl: 'ModalContentDelete.html',
                    resolve: {
                        items: function () {
                            return $scope.items;
                        },
                    },
                    controller: 'DeleteConfirmModalController',
                    scope: $scope,
                });
                $scope.$modalInstance = modalInstance;
            };

            $scope.confirmrestart = function (id) {
                $scope.confirmId = id;
                var modalInstance = $uibModal.open({
                    animation: $scope.animationsEnabled,
                    templateUrl: 'ModalContentRestart.html',
                    resolve: {
                        items: function () {
                            return $scope.items;
                        },
                    },
                    controller: 'RestartConfirmModalController',
                    scope: $scope,
                });
            };

            $scope.LogError = {
                id: null,
                errors: []
            };

            $scope.getError = async function (id) {
                if(id===$scope.LogError.id){
                    $scope.LogError.id = null;
                    $scope.LogError.errors = [];
                    return;
                }
                $http
                    .get(`/import/ErrorLog?importId=${id}`).then((res) => {
                        if (res && res.data.length > 0)
                            $scope.LogError = { id: id, errors: res.data }
                    })

            }
            $scope.ExportErroredId = -1;

            $scope.getExportError=function(id){

                if($scope.ExportErroredId===-1 || id!==$scope.ExportErroredId){

                    $scope.ExportErroredId=id;
                } else{

                    $scope.ExportErroredId=-1;
                }

                }



            $scope.mapImportLogsResponse = function (response) {
                var data = response.data;
                $scope.items = data.Rows;
                $scope.pageSize = data.RowCount;
                $scope.pageIndex = data.Current;
                $scope.filteredCount = data.Total;
                $scope.totalCount = data.Total;
                $scope.pageCount = Math.ceil(data.Total / data.RowCount);
                pendingRequest = false;
                deferredRequest = $q.defer();

                if (data.Total === 0) {
                    $($element).find('.no-items').fadeIn();
                } else {
                    $($element).find('.no-items').hide();
                }
                if (settings.onLoaded) {
                    settings.onLoaded();
                }
            };

            $scope.getRequestVerificationToken = function () {
                return (httpOptions = {
                    headers: {
                        __RequestVerificationToken: $(
                            'input[name=__RequestVerificationToken]'
                        ).val(),
                    },
                    timeout: $scope.canceler.promise,
                });
            };

            $scope.getAddtionalPostData = function () {
                postData = {
                    command: {
                        current: $scope.pageIndex,
                        rowcount: $scope.pageSize,
                        searchPhrase: '',
                    },
                };
                if (settings.getAdditionalPostdata) {
                    var additionalPostData = {
                        model: settings.getAdditionalPostdata(),
                    };
                    postData = angular.merge(
                        {
                            command: {
                                current: $scope.pageIndex,
                                rowcount: $scope.pageSize,
                                searchPhrase: '',
                            },
                        },
                        additionalPostData
                    );
                    var searchPhrase = postData.model.SearchProductName;
                    if (
                        searchPhrase != null &&
                        searchPhrase !== '' &&
                        searchPhrase.length < 3
                    ) {
                        return;
                    }
                }

                return postData;
            };

            $scope.getScheduledLogs = function () {
                $scope.canceler = $q.defer();
                var postData = $scope.getAddtionalPostData({});

                $http
                    .post(
                        settings.scheduledImportLogList,
                        postData,
                        $scope.getRequestVerificationToken()
                    )
                    .then(function (res) {
                        if (res && res.data) {
                            $scope.mapImportLogsResponse(res);
                        }
                        settings.listUrl = settings.scheduledImportLogList;
                        initPage();
                    })
                    .catch(function (data) {
                        // If the status === -1 it has been canceled
                        if (data && data.status !== -1) {
                            console.error(
                                `Error with request to ${data.config.url}`
                            );
                        }
                    });
            };

            $scope.getManualLogs = function () {
                $scope.canceler = $q.defer();
                var postData = $scope.getAddtionalPostData({});
                $http
                    .post(
                        settings.manualImportLogList,
                        postData,
                        $scope.getRequestVerificationToken()
                    )
                    .then(function (res) {
                        if (res && res.data) {
                            $scope.mapImportLogsResponse(res);
                        }
                        settings.listUrl = settings.manualImportLogList;
                        initPage();
                    })
                    .catch(function (data) {
                        // If the status === -1 it has been canceled
                        if (data && data.status !== -1) {
                            console.error(
                                `Error with request to ${data.config.url}`
                            );
                        }
                    });
            };

            $scope.restart = function (id) {
                // remove from angular grid before removing from database and refreshing grid
                for (i = 0; i < $scope.items.length; i++) {
                    var item = $scope.items[i];
                    if (item.Id === id) {
                        $scope.items.splice(i, 1);
                        break;
                    }
                }

                $http
                    .post(
                        settings.restartUrl,
                        { id: id },
                        {
                            headers: {
                                __RequestVerificationToken: $(
                                    'input[name=__RequestVerificationToken]'
                                ).val(),
                            },
                        }
                    )
                    .then(function (res) {
                        try {
                            if (!res.Result) {
                                $('.notifications-main').html(
                                    '<div class="alert alert-danger alert-dismissible fade show">' +
                                    object.Message +
                                    '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-hidden="true"></button></div>'
                                );
                            }
                        } catch (error) { }
                        if (
                            $scope.selectedItem &&
                            $scope.selectedItem.Id === id
                        ) {
                            $scope.cancel();
                        }

                        if ($scope.canceler) {
                            $scope.canceler.resolve('Canceled');
                        }
                        refreshData();
                        if (settings.afterRestart) {
                            settings.afterRestart(id);
                        }
                    });
            };

            initPage();
            if (!settings.async) {
                if ($scope.canceler) {
                    $scope.canceler.resolve('Canceled');
                }
                refreshData();
            }
        }
    );

    return controller;
}

adminApp.controller(
    'DeleteConfirmModalController',
    function ($scope, $uibModalInstance) {
        $scope.cancel = function () {
            $uibModalInstance.close();
        };

        $scope.confirm = function () {
            $uibModalInstance.close();
            $scope.delete($scope.confirmDeleteId);
        };
    }
);

adminApp.controller(
    'RestartConfirmModalController',
    function ($scope, $uibModalInstance) {
        $scope.cancel = function () {
            $uibModalInstance.close();
        };

        $scope.confirm = function () {
            $uibModalInstance.close();
            $scope.restart($scope.confirmId);
        };
    }
);
