//SCREEN-BOILERPLATE
//this boilerplate builds screens that are gonna be shown in the <div class='content'> tag of our main HTML.
//do not build app components with this boilerplate, only screens (reports)

define([
    'app',
    'js/templates-loader',
    'moment',
    'components/ag-grid/ag-grid-module',
    'modules/modal2',
],
    function (app, T, moment, AgGridModule, Modal) {

        var Screen = { Models: {}, Views: {}, Collections: {} };

        // -------------------------------------------------------------
        // Collection: loads rows and wraps the 3 stored procedures
        // (GetPrepurchasedEnergy / UpsertPrepurchasedEnergy / RemovePrepurchasedEnergy)
        // -------------------------------------------------------------
        Screen.Collections.Items = Backbone.Collection.extend({
            isFetching: false,

            fetch: function () {
                var that = this,
                    qp = new Core.Database.QueryParameters();

                this.isFetching = true;

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.PWR.GetPrepurchasedEnergy',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (resp && resp.Table) {
                                    that.set(resp.Table);
                                    that.trigger('fetch', that, resp.Table);
                                } else {
                                    var msg = (resp && resp.Message) ? resp.Message : 'SERVER_RESPONSE_NOT_VALID';
                                    app.views.topMessages.showMessage('CALL TO DATABASE FAILED', { stay: 5000 });
                                    console.error(new Error(msg).stack);
                                }
                            } catch (e) {
                                console.error((e.stack) ? e.stack : new Error(e).stack);
                            } finally {
                                that.isFetching = false;
                            }
                        },
                        onFailure: function (resp) {
                            console.error(resp);
                            that.isFetching = false;
                        },
                        Secured: true,
                        Async: true,
                    },
                    app.ConnectionStrings.app
                );

                return this;
            },

            upsertItem: function (row, success, error) {
                var that = this,
                    qp = new Core.Database.QueryParameters();

                qp.Add('@Year',     'INT',           row.Year);
                qp.Add('@MWHLimit', 'decimal(18,2)', row.MWHLimit);
                qp.Add('@Price',    'decimal(18,2)', row.Price);

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.PWR.UpsertPrepurchasedEnergy',
                    qp,
                    {
                        onSuccess: function (data) {
                            if (data && data.Table && data.Table.length > 0 && !data.Table[0].Message) {
                                if (_.isFunction(success)) success.call(that, that, data.Table[0]);
                            } else {
                                var msg = (data && data.Table && data.Table[0] && data.Table[0].Message)
                                    ? data.Table[0].Message
                                    : (data && data.Message) ? data.Message : null;
                                if (_.isFunction(error)) error.call(that, that, msg);
                            }
                        },
                        onFailure: function () {
                            if (_.isFunction(error)) error.call(that, that);
                        },
                        Secured: true,
                        Async: true,
                    },
                    app.ConnectionStrings.app
                );
            },

            removeItem: function (year, success, error) {
                var that = this,
                    qp = new Core.Database.QueryParameters();

                qp.Add('@Year', 'INT', year);

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.PWR.RemovePrepurchasedEnergy',
                    qp,
                    {
                        onSuccess: function (data) {
                            if (data && data.Table && data.Table.length > 0 && !data.Table[0].Message) {
                                if (_.isFunction(success)) success.call(that, that, data.Table[0]);
                            } else {
                                var msg = (data && data.Table && data.Table[0] && data.Table[0].Message)
                                    ? data.Table[0].Message
                                    : (data && data.Message) ? data.Message : null;
                                if (_.isFunction(error)) error.call(that, that, msg);
                            }
                        },
                        onFailure: function () {
                            if (_.isFunction(error)) error.call(that, that);
                        },
                        Secured: true,
                        Async: true,
                    },
                    app.ConnectionStrings.app
                );
            },
        });

        // -------------------------------------------------------------
        // Model
        // -------------------------------------------------------------
        Screen.Models.Main = Backbone.Epoxy.Model.extend({
            defaults: {
                hasData: false,
                isLoading: false,
                readOnlyPermission: true,
                rowCount: 0,
            },
            computeds: {
                rowCountLabel: {
                    deps: ['rowCount'],
                    get: function (count) {
                        var n = count || 0;
                        return n + (n === 1 ? ' entry' : ' entries');
                    },
                },
            },
        });

        // -------------------------------------------------------------
        // Formatters & renderers
        // -------------------------------------------------------------
        function moneyFormatter(params) {
            if (params.value == null || params.value === '') return '';
            var n = parseFloat(params.value);
            if (isNaN(n)) return params.value;
            return n.toFixed(2);
        }

        function totalFormatter(params) {
            if (!params.data) return '';
            var mwh = parseFloat(params.data.MWHLimit),
                price = parseFloat(params.data.Price);
            if (isNaN(mwh) || isNaN(price)) return '';
            var total = mwh * price;
            return '$' + total.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
        }

        function deleteCellRenderer(readOnly) {
            return function (params) {
                if (readOnly) return '';
                if (!params.data || params.data.Year == null) return '';
                return '<button class="action-delete-btn" title="Delete"><i class="fa fa-trash-o" aria-hidden="true"></i></button>';
            };
        }

        // Editor input is `number`; coerce any typed value back to a clean decimal.
        function numberValueParser(params) {
            if (params.newValue === '' || params.newValue == null) return null;
            var n = parseFloat(params.newValue);
            return isNaN(n) ? params.oldValue : Math.round(n * 100) / 100;
        }

        // -------------------------------------------------------------
        // Main View
        // -------------------------------------------------------------
        Screen.Views.Main = Backbone.Epoxy.View.extend({
            template: 'prepurchased-energy',
            id: 'prepurchased-energy',
            title: 'Prepurchased Energy',
            events: function () {
                return {
                    'click #refreshBtn': this.refreshBtn_click,
                    'click #addYearBtn': this.addYearBtn_click,
                    'click #exportExcelBtn': this.exportExcelBtn_click,
                };
            },
            bindings: 'data-bind',
            agGridModule: null,
            itemsColl: null,
            subviews: null,
            viewParams: null,

            initialize: function () {
                this.options.state = app.view_states.loading;
                this.options.onappend = (_.isFunction(this.options.onappend)) ? this.options.onappend : function () { };

                var that = this;

                if (!this.model) this.model = new Screen.Models.Main();

                this.itemsColl = new Screen.Collections.Items();
                this.subviews = {};

                this.getPermissions();

                var readOnly = this.model.get('readOnlyPermission');

                this.agGridModule = new AgGridModule({
                    columnDefs: this.buildColumnDefs(readOnly),
                    rowData: [],
                    fileName: 'prepurchased-energy',
                    screenTitle: this.title,
                    pagination: 'hidden',
                    allowMultipleSelection: false,
                    suppressRowClickSelection: true,
                    gridOptions: {
                        stopEditingWhenCellsLoseFocus: true,
                        singleClickEdit: false,
                        onCellValueChanged: function (event) {
                            that.onCellValueChanged(event);
                        },
                        onCellClicked: function (params) {
                            if (params.colDef && params.colDef.field === 'actions') {
                                var target = params.event && params.event.target;
                                if (target && target.closest && target.closest('.action-delete-btn')) {
                                    that.onDeleteClicked(params.data);
                                }
                            }
                        },
                    },
                });

                this.bindEvents();
            },

            // -------------------------------------------------------------
            // Columns — Year is read-only (PK); MWHLimit and Price are editable
            // -------------------------------------------------------------
            buildColumnDefs: function (readOnly) {
                return [
                    {
                        field: 'Year',
                        headerName: 'Year',
                        flex: 1,
                        minWidth: 90,
                        editable: false,
                        cellClass: 'text-center',
                        headerClass: 'ag-header-cell-center',
                    },
                    {
                        field: 'MWHLimit',
                        headerName: 'MWH Limit',
                        flex: 1,
                        minWidth: 110,
                        editable: !readOnly,
                        cellEditor: 'agNumberCellEditor',
                        valueParser: numberValueParser,
                        valueFormatter: moneyFormatter,
                        cellClass: function () {
                            return 'text-right-cell' + (readOnly ? '' : ' editable-cell');
                        },
                        headerClass: 'ag-header-cell-center',
                    },
                    {
                        field: 'Price',
                        headerName: 'Price ($ / MWh)',
                        flex: 1,
                        minWidth: 130,
                        editable: !readOnly,
                        cellEditor: 'agNumberCellEditor',
                        valueParser: numberValueParser,
                        valueFormatter: moneyFormatter,
                        cellClass: function () {
                            return 'text-right-cell' + (readOnly ? '' : ' editable-cell');
                        },
                        headerClass: 'ag-header-cell-center',
                    },
                    {
                        colId: 'total',
                        headerName: 'Total Value',
                        flex: 1,
                        minWidth: 130,
                        editable: false,
                        valueGetter: function (params) {
                            if (!params.data) return null;
                            var mwh = parseFloat(params.data.MWHLimit),
                                price = parseFloat(params.data.Price);
                            if (isNaN(mwh) || isNaN(price)) return null;
                            return mwh * price;
                        },
                        valueFormatter: totalFormatter,
                        cellClass: 'text-right-cell',
                        cellStyle: { color: '#374151', fontWeight: '600' },
                        headerClass: 'ag-header-cell-center',
                    },
                    {
                        field: 'actions',
                        headerName: 'Actions',
                        width: 80,
                        maxWidth: 90,
                        editable: false,
                        sortable: false,
                        filter: false,
                        resizable: false,
                        suppressMenu: true,
                        cellClass: 'text-center actions-cell',
                        headerClass: 'ag-header-cell-center',
                        cellRenderer: deleteCellRenderer(readOnly),
                    },
                ];
            },

            // -------------------------------------------------------------
            // Permissions — mirrors the legacy behavior
            // -------------------------------------------------------------
            getPermissions: function () {
                var canWrite = $.inArray('prepurchasedEnergy_readWrite', app.models.user.get('roles')) !== -1;
                this.model.set('readOnlyPermission', !canWrite);
            },

            bindEvents: function () {
                this.listenTo(this.itemsColl, 'fetch', this.processes_ready);
            },

            // -------------------------------------------------------------
            // Render: mount grid, wire data, kick off first fetch
            // -------------------------------------------------------------
            render: function (container, viewParams) {
                var that = this;

                this.viewParams = viewParams;

                var thatContainer = (this.options.container) ? this.options.container : container;
                this.options.container = thatContainer;

                var customPath = '/app/pages/mes/' + this.template + '/';

                T.render.call(
                    this,
                    this.template,
                    function (tmp) {
                        if (!that.options.i18n) that.options.i18n = {};

                        app.getI18NJed(
                            that,
                            that.template,
                            function (i18nJED) {
                                that.options.i18n[that.template] = i18nJED;
                                that.$el.html(tmp());
                                that.applyBindings();

                                that.agGridModule.render();
                                that.$el.find('.processes-grid-container').append(that.agGridModule.$el);

                                that.append(thatContainer, that.$el);

                                that._refresh();
                            },
                            true,
                            customPath
                        );
                    },
                    customPath
                );
            },

            _refresh: function () {
                this.model.set({ isLoading: true, hasData: false });
                this.agGridModule.showLoadingOverlay();
                this.itemsColl.fetch();
            },

            refreshBtn_click: function () {
                this._refresh();
            },

            // Export using AG Grid's native xlsx writer (no SP, no server roundtrip).
            // The right-click context menu still offers the same option.
            exportExcelBtn_click: function () {
                if (!this.agGridModule || !this.agGridModule.gridApi) return;
                this.agGridModule.exportToExcel(false);
            },

            processes_ready: function () {
                var that = this;
                try {
                    setTimeout(function () {
                        that.agGridModule.setRowDataAsCollection(that.itemsColl);
                        that.agGridModule.hideOverlay();
                        that.model.set({
                            hasData: (that.itemsColl.length > 0),
                            isLoading: false,
                            rowCount: that.itemsColl.length,
                        });
                    }, 50);
                } catch (e) {
                    console.error((e.stack) ? e.stack : new Error(e).stack);
                    this.model.set({ isLoading: false });
                    this.agGridModule.hideOverlay();
                }
            },

            // -------------------------------------------------------------
            // Inline edit: auto-save on cell change (matches legacy behavior)
            // -------------------------------------------------------------
            onCellValueChanged: function (event) {
                var that = this,
                    field = event.colDef && event.colDef.field;

                if (field !== 'MWHLimit' && field !== 'Price') return;
                if (event.newValue === event.oldValue) return;
                if (!event.data || event.data.Year == null) return;

                var year = parseInt(event.data.Year, 10);
                var mwh  = parseFloat(event.data.MWHLimit);
                var price = parseFloat(event.data.Price);

                if (isNaN(year) || isNaN(mwh) || isNaN(price)) {
                    app.views.topMessages.showMessage('Invalid numeric value. Change was not saved.', { stay: 4000 });
                    that._refresh();
                    return;
                }

                this.itemsColl.upsertItem(
                    { Year: year, MWHLimit: mwh, Price: price },
                    function () {
                        app.views.topMessages.showMessage('Saved.', { stay: 2000 });
                        // Refresh the Total cell for this row without a full reload
                        if (that.agGridModule.gridApi && event.node) {
                            that.agGridModule.gridApi.refreshCells({ rowNodes: [event.node], columns: ['total'], force: true });
                        }
                    },
                    function (coll, msg) {
                        app.views.topMessages.showMessage(msg || 'Save failed.', { stay: 5000 });
                        that._refresh();
                    }
                );
            },

            // -------------------------------------------------------------
            // Delete flow: confirm, call SP, refresh
            // -------------------------------------------------------------
            onDeleteClicked: function (row) {
                if (this.model.get('readOnlyPermission')) return;
                if (!row || row.Year == null) return;

                var that = this,
                    modal = new Modal.Views.Main({
                        focusOk: false,
                        focusSelector: '#btn-cancel',
                        title: app.translate([this, app], 'delete_item_modal_confirm_title'),
                        message: app.translate([this, app], 'delete_item_modal_confirm_message'),
                        buttons_type: 'CONTINUE-CANCEL',
                    });

                this.listenToOnce(modal, 'continue', function () {
                    that.itemsColl.removeItem(
                        row.Year,
                        function () {
                            app.views.topMessages.showMessage('Entry removed.', { stay: 2500 });
                            that._refresh();
                        },
                        function (coll, msg) {
                            app.views.topMessages.showMessage(msg || 'Remove failed.', { stay: 5000 });
                            that._refresh();
                        }
                    );
                });

                modal.show();
            },

            // -------------------------------------------------------------
            // Add Year flow: open modal, collect values, call Upsert
            // -------------------------------------------------------------
            addYearBtn_click: function () {
                if (this.model.get('readOnlyPermission')) return;

                var that = this,
                    existingYears = _.map(this.itemsColl.toJSON(), function (r) { return parseInt(r.Year, 10); }),
                    addView = new Screen.Views.AddYearModal({
                        existingYears: existingYears,
                        onAccept: function (row, onSuccess, onError) {
                            that.itemsColl.upsertItem(row, onSuccess, onError);
                        },
                        onSaved: function () {
                            app.views.topMessages.showMessage('Entry added.', { stay: 2500 });
                            that._refresh();
                        },
                    });

                this.subviews.addYearModal = addView;
                addView.show();
            },

            // -------------------------------------------------------------
            // Lifecycle boilerplate
            // -------------------------------------------------------------
            append: function (container, el) {
                el = (el != null && el != undefined) ? el : this.$el;

                if (this.options.state == app.view_states.loading
                    || this.options.state == app.view_states.shown) {
                    this.options.state = app.view_states.shown;
                    container.append(el);
                    this.options.onappend(this);
                }
                if (this.options.state == app.view_states.hidden) container.append(el);
                if (this.options.state == app.view_states.closed) return;
            },
            bindViewScopedEvents: function () { },
            unbindViewScopedEvents: function () { },
            close: function () {
                this.options.state = app.view_states.closed;
                if (this.agGridModule && this.agGridModule.destroy) this.agGridModule.destroy();
                this.closeSubviews();
                this.remove();
                this.unbindViewScopedEvents();
                this.unbind();
            },
            closeSubviews: function () {
                _.each(this.subviews, function (sview) { if (sview && sview.close) sview.close(); });
            },
            show: function () {
                this.options.state = app.view_states.shown;
                this.showSubviews();
                this.bindEvents();
                this.$el.show();
            },
            showSubviews: function () {
                _.each(this.subviews, function (sview) { if (sview && sview.show) sview.show(); });
            },
            hide: function () {
                this.options.state = app.view_states.hidden;
                this.hideSubviews();
                this.$el.hide();
                this.unbind();
                this.stopListening();
            },
            hideSubviews: function () {
                _.each(this.subviews, function (sview) { if (sview && sview.hide) sview.hide(); });
            },
            preRender: function () {
                app.models.subnavbar.set('subnavbar', false);
            },
            reRender: function () {
                try { this._refresh(); } catch (e) { }
            },
        });


        // -------------------------------------------------------------
        // Add Year Modal
        // -------------------------------------------------------------
        Screen.Views.AddYearModal = Backbone.Epoxy.View.extend({
            template: 'prepurchased-energy',
            id: 'add-year-modal',
            className: 'modal modal-add-year hide fade',

            events: function () {
                return {
                    'click #acceptAddYearBtn': this.acceptBtn_click,
                    'click #cancelAddYearBtn': this.cancelBtn_click,
                    'keypress #newYearInput': this.input_keypress,
                    'keypress #newMWHLimitInput': this.input_keypress,
                    'keypress #newPriceInput': this.input_keypress,
                    'hidden.bs.modal': this.modal_hidden,
                };
            },

            existingYears: null,
            onAccept: null,
            onSaved: null,
            isRendered: false,
            isSaving: false,

            initialize: function (options) {
                _.extend(this, options);
                this.existingYears = options.existingYears || [];
            },

            render: function () {
                var that = this,
                    customPath = '/app/pages/mes/prepurchased-energy/';

                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());
                        that.isRendered = true;
                        that.$el.modal({ keyboard: true, backdrop: 'static' });
                        setTimeout(function () { that.$el.find('#newYearInput').focus(); }, 150);
                    }, true, customPath);
                }, customPath, 'add_year_modal_template');
            },

            show: function () {
                if (!this.isRendered) this.render();
                else this.$el.modal({ keyboard: true, backdrop: 'static' });
                return this;
            },

            input_keypress: function (e) {
                if (e.keyCode === 13) this.acceptBtn_click();
            },

            showError: function (msg) {
                var $err = this.$el.find('#addYearError');
                if (msg) $err.text(msg).removeClass('hide');
                else $err.addClass('hide').text('');
            },

            acceptBtn_click: function () {
                if (this.isSaving) return;

                var yearRaw  = this.$el.find('#newYearInput').val(),
                    mwhRaw   = this.$el.find('#newMWHLimitInput').val(),
                    priceRaw = this.$el.find('#newPriceInput').val();

                var year  = parseInt(yearRaw, 10),
                    mwh   = parseFloat(mwhRaw),
                    price = parseFloat(priceRaw);

                if (isNaN(year) || year < 1900 || year > 2999) {
                    this.showError('Please enter a valid year between 1900 and 2999.');
                    return;
                }
                if (isNaN(mwh) || mwh < 0) {
                    this.showError('Please enter a valid MWH Limit (>= 0).');
                    return;
                }
                if (isNaN(price) || price < 0) {
                    this.showError('Please enter a valid Price (>= 0).');
                    return;
                }
                if (_.contains(this.existingYears, year)) {
                    this.showError('Year ' + year + ' already exists. Edit it directly in the grid.');
                    return;
                }
                this.showError(null);

                var that = this;
                this.isSaving = true;
                this.$el.find('#acceptAddYearBtn').prop('disabled', true).addClass('disabled');

                this.onAccept(
                    { Year: year, MWHLimit: Math.round(mwh * 100) / 100, Price: Math.round(price * 100) / 100 },
                    function () {
                        that.isSaving = false;
                        if (_.isFunction(that.onSaved)) that.onSaved();
                        that.$el.modal('hide');
                    },
                    function (coll, msg) {
                        that.isSaving = false;
                        that.$el.find('#acceptAddYearBtn').prop('disabled', false).removeClass('disabled');
                        that.showError(msg || 'Save failed. Try again.');
                    }
                );
            },

            cancelBtn_click: function () {
                this.$el.modal('hide');
            },

            modal_hidden: function () {
                this.close();
            },

            close: function () {
                this.stopListening();
                this.remove();
                this.unbind();
            },
        });


        // Required, return the module for AMD compliance.
        return Screen;
    });
