define([
    'app',
    'js/templates-loader',
    'backbone',
    'agGrid',
    'moment'
], function (app,T, Backbone, agGrid, moment) {

    var AgGridModule = Backbone.View.extend({
        className: 'ag-grid-module',
        // template: '<div id="<%= id %>" class="ag-theme-alpine w-full" style="height: 75vh;"></div>',
        template: 'ag-grid-module',
        initialize: function (options) {
            this.gridReadyPromise = new Promise((resolve) => { this.resolveGridReady = resolve; });
            this.columnDefs = options.columnDefs || [];
            this.rowData = options.rowData || [];
            this.fileName = options.fileName || 'export';
            this.screenTitle = options.screenTitle || 'Unknown';
            this.isPageLoading = options.isPageLoading || false;
            this.onChange = options.onChange || function () { };
            this.onRemove = options.onRemove || function () { };
            this.pagination = options.pagination || true;

            // New property for row selection
            const allowMultipleSelection = options.allowMultipleSelection !== false; // Default is true
            const suppressRowClickSelection = options.suppressRowClickSelection === null 
            ? false 
            : options.suppressRowClickSelection;

         
            this.formatColumnDefs(options.columnDefs);
            this.gridOptions = {
                columnDefs: this.columnDefs,
                defaultColDef: {
                    sortable: true,
                    resizable: true,
                    filter:false,
                    cellStyle: { textAlign: 'center' },
                    headerClass: 'ag-header-cell-center',
                    suppressMenu: true,
                    suppressMenuHide: true,
                    menuTabs: [],
                    icons: {
                        menu: null,
                        columns: null
                    },
                },
                pagination: options.pagination ==='hidden' ? false : true,
                paginationPageSize: 20,
                paginationPageSizeSelector: [10, 15, 20, 50, 100],
                paginationNumberFormatter: function (params) {
                    return '[' + params.value.toLocaleString() + ']';
                },
                onCellValueChanged: this.onChange,
                onGridReady: this.onGridReady.bind(this),
                // Enterprise features
                enableRangeSelection: true,
                enableExcelExport: true,
                allowContextMenuWithControlKey: true,
                getContextMenuItems: this.getContextMenuItems.bind(this),
                // New option for loading overlay
                loading: false,
                // Row selection configurations
                rowSelection: allowMultipleSelection ? 'multiple' : 'single',
                suppressRowClickSelection:  suppressRowClickSelection,//true,//options.suppressRowClickSelection != null ? false : options.suppressRowClickSelection,
                onRowClicked: this.onRowClicked.bind(this),
                onSelectionChanged: this.onSelectionChanged.bind(this),
                onCellClicked: this.onCellClicked.bind(this),
                
                ...options.gridOptions 
            };
            this.gridId = 'agGrid_' + Math.random().toString(36).slice(2, 11);

        },
        onCellClicked: function(params) {
            if (params.column.colDef.fieldType === 'edit') {
                // Allow default selection to occur
                setTimeout(() => {
                    // Deselect the row
                    params.node.setSelected(false);
                    // Clear any cell selection
                    this.gridApi.clearRangeSelection();
                    // Remove focus from the cell
                    this.gridApi.clearFocusedCell();
                }, 50); // 50ms delay, adjust if needed
            }
        },

        formatColumnDefsRecursive: function(columnDefs) {
            var self = this;
            return (columnDefs || []).map(function(colDef) {
                if (colDef.children && colDef.children.length) {
                    return _.extend({}, colDef, { children: self.formatColumnDefsRecursive(colDef.children) });
                }
                var updatedColDef = _.extend({}, colDef, { filter: colDef.showFilter === true });
                if (colDef.fieldType === 'edit') {
                    updatedColDef.cellRenderer = function(params) {
                        return '<i class="fa fa-pencil edit-icon edit-button" style="cursor: pointer; color: #007bff;" data-row-id="' + params.node.id + '" data-row="' + encodeURIComponent(JSON.stringify(params.data)) + '"></i>';
                    };
                    updatedColDef.suppressCellSelection = true;
                }
                return updatedColDef;
            });
        },
        formatColumnDefs: function(columnDefs) {
            this.columnDefs = this.formatColumnDefsRecursive(columnDefs);
            this.gridReadyPromise.then(() => {
                // AG Grid >= 31 removed setColumnDefs in favor of setGridOption.
                if (this.gridApi && typeof this.gridApi.setGridOption === 'function') {
                    this.gridApi.setGridOption('columnDefs', this.columnDefs);
                } else if (this.gridApi && typeof this.gridApi.setColumnDefs === 'function') {
                    this.gridApi.setColumnDefs(this.columnDefs);
                }
            }).catch(() => {});
        },
        
        render: function (container) {
            var that = this;
            var customPath = '/app/components/ag-grid/';
            T.render.call(this, this.template, function (tmp) {
                if (!that.i18n) that.i18n = {};
                app.getI18NJed(that, that.template, function (i18nJED) {
                    that.i18n[that.template] = i18nJED;
                    // that.$el.html(tmp({ id: that.gridId }));
                    that.$el.html(tmp({ 
                        id: that.gridId,
                        screenTitle: that.screenTitle,
                        isPageLoading: that.isPageLoading
                    }));
                    setTimeout(function() {
                        that.createGrid();
                    }, 0);
                    that.isRendered = true;
                    that.trigger("render");
                }, true, customPath);
            }, customPath, "ag-grid-module");
            
            return this; // This is crucial for chaining
        },
        createGrid: function () {
            var gridElement = this.el.querySelector('#' + this.gridId);
        
            // Initialize the grid using createGrid, which returns an object with the gridApi and columnApi
            const gridInfo = agGrid.createGrid(gridElement, this.gridOptions);
        },
        
        
        onGridReady: function(params) {
            this.gridApi = params.api;
            this.columnApi = params.columnApi;
            this.resolveGridReady();

            if (this.rowData && this.rowData.length > 0) {
                this.gridOptions.api.setRowData(this.rowData);
            }
        
            
        },
        getGridApi: function () {
            return this.gridApi;
        },
    
        getColumnApi: function () {
            return this.columnApi;
        },

        onRowClicked: function(params) {
            // This function will be called when a row is clicked
            var selectedRows = params.api.getSelectedRows();
            // You can add custom logic here, such as triggering an event or updating other parts of your application
          
            this.trigger('rows:selected', selectedRows);
        },

        onSelectionChanged: function(event) {
            var selectedRows = this.gridApi.getSelectedRows();
            this.trigger('selection:changed', selectedRows);
        },

        // Excel and Context menu
        getContextMenuItems: function (params) {
            var self = this;
            return [
                'copy',
                {
                    name: 'Copy Selected with Headers',
                    action: function() {
                        self.copySelectedToClipboard(true);
                    }
                },
                'separator',
                {
                    name: 'Export All to Excel',
                    action: function() {
                        self.exportToExcel(false);
                    }
                },
                {
                    name: 'Export Selected to Excel',
                    action: function() {
                        self.exportToExcel(true);
                    }
                }
            ];
        },

        getExportFileName: function() {
            var timestamp = moment().format('YYYY-MM-DD_HH-mm-ss');
            return `${this.fileName}_${timestamp}.xlsx`;
        },

        exportToExcel: function(onlySelected) {
            if (!this.gridApi) {
                console.error('Grid API is not available');
                return;
            }

            var params = {
                fileName: this.getExportFileName(),
                onlySelected: onlySelected
            };
            this.gridApi.exportDataAsExcel(params);
        },

        copySelectedToClipboard: function(includeHeaders = true) {
            if (!this.gridApi) {
                console.error('Grid API is not available');
                return;
            }

            var params = {
                includeHeaders: includeHeaders,
                onlySelected: true,
                columnKeys: this.getVisibleColumnKeys()
            };
            this.gridApi.copySelectedRowsToClipboard(params);
        },

        getVisibleColumnKeys: function() {
            if (!this.gridApi) {
                console.error('Grid API is not available');
                return [];
            }

            return this.gridApi.getColumnDefs()
                .filter(colDef => !colDef.hide)
                .map(colDef => colDef.field || colDef.colId);
        },
     


        getLeafColumnDefs: function (columnDefs) {
            var leaves = [];
            if (!columnDefs || !columnDefs.length) return leaves;
            columnDefs.forEach(function (colDef) {
                if (colDef.children && colDef.children.length) {
                    leaves = leaves.concat(this.getLeafColumnDefs(colDef.children));
                } else if (colDef.field) {
                    leaves.push(colDef);
                }
            }.bind(this));
            return leaves;
        },
        // Set Row Data and column definition      
        setRowData: function (rowData) {
            if (this.gridApi && this.gridApi.setGridOption) {
                var leafColDefs = this.getLeafColumnDefs(this.columnDefs);
                const formattedRowData = rowData.map(row => {
                    const formattedRow = { ...row };
                    leafColDefs.forEach(colDef => {
                        if (colDef.fieldType === 'Datetime' && colDef.format) {
                            const fieldValue = row[colDef.field];
                            if (fieldValue) {
                                formattedRow[colDef.field] = moment(fieldValue).format(colDef.format);
                            } else {
                                formattedRow[colDef.field] = null;
                            }
                        }
                        if (colDef.fieldType === 'Float' && colDef.decimals !== undefined) {
                            const fieldValue = row[colDef.field];
                            if (fieldValue !== null && fieldValue !== undefined) {
                                const floatValue = parseFloat(fieldValue);
                                if (!isNaN(floatValue)) {
                                    formattedRow[colDef.field] = floatValue.toFixed(colDef.decimals);
                                } else {
                                    formattedRow[colDef.field] = fieldValue; // Keep original value if not a valid number
                                }
                            } else {
                                formattedRow[colDef.field] = null;
                            }
                        }
                        if (colDef.fieldType === 'Seconds') {
                            const fieldValue = row[colDef.field];
                            if (fieldValue !== null && fieldValue !== undefined) {
                                const seconds = parseInt(fieldValue, 10);
                                if (!isNaN(seconds)) {
                                    const hours = Math.floor(seconds / 3600);
                                    const minutes = Math.floor((seconds % 3600) / 60);
                                    const remainingSeconds = seconds % 60;
                                    
                                    if (hours > 0) {
                                        formattedRow[colDef.field] = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(remainingSeconds).padStart(2, '0')}`;
                                    } else {
                                        formattedRow[colDef.field] = `${String(minutes).padStart(2, '0')}:${String(remainingSeconds).padStart(2, '0')}`;
                                    }
                                } else {
                                    formattedRow[colDef.field] = fieldValue; // Keep original value if not a valid number
                                }
                            } else {
                                formattedRow[colDef.field] = null;
                            }
                        }
                    });
                    return formattedRow;
                });

                this.gridApi.setGridOption('rowData', formattedRowData);
                this.updateOverlayAndLoading();
            } else if (this.gridOptions) {
                this.gridOptions.rowData = rowData;
            } else {
                console.warn('Grid API not initialized and gridOptions not available');
                this.rowData = rowData;
            }
        },
        convertCollection: function (backboneCollection) {
            return backboneCollection.map(model => {
                return model.attributes;
            });
        },
        setRowDataAsCollection: function (collectionData) {
            const rowData = this.convertCollection(collectionData);
            this.setRowData(rowData);
        },

        // Loading

        showLoadingOverlay: function () {
            if (this.gridApi) {
                this.gridApi.setGridOption('loading', true);
            }
        },

        hideOverlay: function () {
            if (this.gridApi) {
                this.gridApi.setGridOption('loading', false);
                this.updateOverlayAndLoading();
            }
        },

        updateOverlayAndLoading: function () {
            if (this.gridApi) {
                const rowCount = this.gridApi.getDisplayedRowCount();
                this.gridApi.setGridOption('loading', false);
                
                if (rowCount === 0) {
                    this.gridApi.showNoRowsOverlay();
                } else {
                    this.gridApi.hideOverlay();
                }
            } else {
                console.warn("Grid API not available in updateOverlayAndLoading");
            }
        },
        
      
        checkAndShowNoRowsOverlay: function () {
            if (this.gridApi) {
                const rowCount = this.gridApi.getDisplayedRowCount();
                if (rowCount === 0) {
                    this.gridApi.showNoRowsOverlay();
                } else {
                    this.gridApi.hideOverlay();
                }
            }
        },
        
        // destroy
        destroy: function () {
            if (this.gridApi) {
                this.gridApi.destroy();
            }
            this.onRemove();
            Backbone.View.prototype.remove.call(this);
        }
    });
    return AgGridModule;
});