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

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

        // ---------------------------------------------------------------
        // Column Definitions
        // ---------------------------------------------------------------
        function heatLinkRenderer(params) {
            if (!params.value) return '';
            return '<span class="vtd-heat-link">' + params.value + '</span>';
        }

        function floatFormatter(decimals) {
            return function (params) {
                if (params.value == null || params.value === '') return '';
                var val = parseFloat(params.value);
                return isNaN(val) ? params.value : val.toFixed(decimals);
            };
        }

        function getColumnDefs(that) {
            var t = function (key) { return app.translate([that, app], key); };
            // All columns use flex so they fill the full grid width with no blank space.
            // minWidth prevents columns from collapsing too much on narrow viewports.
            function fw(min) { return { flex: 1, minWidth: min, resizable: true }; }
            var fmt1 = floatFormatter(1);

            return [
                { field: 'HeatName', headerName: t('Heat'), pinned: 'left', cellRenderer: heatLinkRenderer, width: 90, resizable: true },
                _.extend({ field: 'ShiftName', headerName: t('Shift') }, fw(50)),
                _.extend({ field: 'CrewId', headerName: t('Crew') }, fw(50)),
                _.extend({ field: 'TankCode', headerName: t('Tank') }, fw(50)),
                _.extend({ field: 'LadleId', headerName: t('Ladle') }, fw(55)),
                _.extend({ field: 'StartLocal', headerName: t('Start') }, fw(120)),
                _.extend({ field: 'EndLocal', headerName: t('End') }, fw(120)),
                _.extend({ field: 'TotalTime', headerName: t('Total Time') }, fw(80)),
                _.extend({ field: 'Treatment', headerName: t('Treatment') }, fw(70)),
                _.extend({ field: 'MinimumTorr', headerName: 'Min\nTorr', headerClass: 'header-two-lines' }, fw(60)),
                _.extend({ field: 'MinTorrTime', headerName: 'Min Torr\nTime', headerClass: 'header-two-lines' }, fw(70)),
                _.extend({ field: 'VacTime', headerName: 'Vacuum\nTime', headerClass: 'header-two-lines' }, fw(70)),
                _.extend({ field: 'MeltOrder', headerName: t('Melt Order') }, fw(95)),
                _.extend({ field: 'GradeName', headerName: t('Grade') }, fw(75)),
                _.extend({ field: 'Temperature', headerName: t('Temp.'), fieldType: 'Float', decimals: 1 }, fw(65)),
                { headerName: 'Wire Additions', children: [
                    _.extend({ field: 'Aluminum', headerName: t('Al'), valueFormatter: fmt1 }, fw(50)),
                    _.extend({ field: 'CaSi', headerName: t('CaSi'), valueFormatter: fmt1 }, fw(50)),
                    _.extend({ field: 'FeB', headerName: t('FeB'), valueFormatter: fmt1 }, fw(50)),
                    _.extend({ field: 'FeTi', headerName: t('FeTi'), valueFormatter: fmt1 }, fw(50)),
                    _.extend({ field: 'Sulphur', headerName: t('Sulfur'), valueFormatter: fmt1 }, fw(55)),
                ]},
                { headerName: 'Hand Additions', children: [
                    _.extend({ field: 'MAluminum', headerName: t('Al'), valueFormatter: fmt1, colId: 'MAluminum' }, fw(50)),
                    _.extend({ field: 'MCaSi', headerName: t('CaSi'), valueFormatter: fmt1, colId: 'MCaSi' }, fw(50)),
                    _.extend({ field: 'MFeB', headerName: t('FeB'), valueFormatter: fmt1, colId: 'MFeB' }, fw(50)),
                    _.extend({ field: 'MFeTi', headerName: t('FeTi'), valueFormatter: fmt1, colId: 'MFeTi' }, fw(50)),
                    _.extend({ field: 'MSulphur', headerName: t('Sulfur'), valueFormatter: fmt1, colId: 'MSulphur' }, fw(55)),
                ]},
                {
                    field: 'isFoamed', headerName: 'Heat\nFoamed', headerClass: 'header-two-lines',
                    flex: 1, minWidth: 80, resizable: true, sortable: false,
                    cellRenderer: function (params) {
                        var checked = params.value ? 'checked' : '';
                        var disabled = !that.model.get('hasPermission') ? 'disabled' : '';
                        return '<input type="checkbox" class="vtd-checkbox vtd-foamed-checkbox" ' + checked + ' ' + disabled + ' />';
                    },
                    suppressCellSelection: true,
                },
                {
                    field: 'isStirredWell', headerName: 'Ladle\nStirred Well', headerClass: 'header-two-lines',
                    flex: 1, minWidth: 90, resizable: true, sortable: false,
                    cellRenderer: function (params) {
                        var checked = params.value ? 'checked' : '';
                        var disabled = !that.model.get('hasPermission') ? 'disabled' : '';
                        return '<input type="checkbox" class="vtd-checkbox vtd-stirred-checkbox" ' + checked + ' ' + disabled + ' />';
                    },
                    suppressCellSelection: true,
                },
                {
                    colId: 'handAdditions', headerName: 'Hand\nAdditions', headerClass: 'header-two-lines',
                    pinned: 'right', width: 80, resizable: false, sortable: false,
                    cellRenderer: function () {
                        return '<button class="vtd-hand-addition-btn"><i class="fa fa-pencil-square-o" aria-hidden="true"></i></button>';
                    },
                    suppressCellSelection: true,
                },
            ];
        }

        // ---------------------------------------------------------------
        // Custom AG Grid Module
        // ---------------------------------------------------------------
        var CustomAgGridModule = AgGridModule.extend({
            initialize: function (options) {
                this.mainView = options.mainView;
                this.columnDefs = options.columnDefs || [];
                options.columnDefs = this.columnDefs;
                var gridOpts = options.gridOptions || {};
                gridOpts.getContextMenuItems = this.getContextMenuItems.bind(this);
                options.gridOptions = gridOpts;
                AgGridModule.prototype.initialize.call(this, options);
            },
            getContextMenuItems: function (params) {
                var self = this;
                var mainView = this.mainView;
                if (!mainView || !params || !params.node) {
                    return AgGridModule.prototype.getContextMenuItems.call(this, params);
                }
                return [
                    {
                        name: 'Go To Heat Report',
                        icon: '<i class="fa fa-bar-chart"></i>',
                        action: function () {
                            var heatName = params.node.data.HeatName;
                            var treatment = params.node.data.Treatment;
                            if (heatName) {
                                app.router.navigate(
                                    app.router.resolveURL('vtd-heat-report', { heatName: heatName, treatmentNumber: treatment }, false),
                                    { trigger: true }
                                );
                            }
                        }
                    },
                    'separator',
                    '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); }
                    }
                ];
            },
            onCellClicked: function (params) {
                var mainView = this.mainView;
                if (!params || !params.data) return;

                var target = params.event && params.event.target;
                if (!target) return;

                // Handle checkbox: isFoamed
                if (target.classList.contains('vtd-foamed-checkbox')) {
                    params.event.preventDefault();
                    mainView.onFoamedCheckboxClick(params.data, target);
                    return;
                }

                // Handle checkbox: isStirredWell
                if (target.classList.contains('vtd-stirred-checkbox')) {
                    params.event.preventDefault();
                    mainView.onStirredCheckboxClick(params.data, target);
                    return;
                }

                // Handle Hand Additions button
                if (target.classList.contains('vtd-hand-addition-btn') || target.closest('.vtd-hand-addition-btn')) {
                    mainView.onHandAdditionsClick(params.data);
                    return;
                }

                // Default: navigate to heat report on row click (skip if checkbox/button area)
                if (params.column && params.column.colDef.field !== 'isFoamed'
                    && params.column.colDef.field !== 'isStirredWell'
                    && params.column.colDef.colId !== 'handAdditions') {
                    mainView.navigateToHeatReport(params.data);
                }

                AgGridModule.prototype.onCellClicked.call(this, params);
            }
        });

        // ---------------------------------------------------------------
        // Model
        // ---------------------------------------------------------------
        Screen.Models.Main = Backbone.Epoxy.Model.extend({
            defaults: {
                start: new moment().subtract(2, 'days').format('YYYY-MM-DD'),
                end: new moment().format('YYYY-MM-DD'),

                tankCode: null,
                tanks: [{ label: '1', value: 1 }, { label: '2', value: 2 }],

                crewId: null,
                crews: [{ label: 'A', value: 'A' }, { label: 'B', value: 'B' }, { label: 'C', value: 'C' }, { label: 'D', value: 'D' }],

                shiftId: null,
                shifts: [{ label: 'D', value: 1 }, { label: 'N', value: '2' }],

                hasData: false,
                isLoading: false,
                hasPermission: false,
                hideShowHandAdditionToggle: false,
            },
            computeds: {
                start$: {
                    deps: ['start'],
                    get: function (value) { return value; },
                    set: function (value) {
                        return { start: (value) ? new moment(value, app.translate(app, 'MM/DD/YYYY')).format('YYYY-MM-DD') : value };
                    },
                },
                end$: {
                    deps: ['end'],
                    get: function (value) { return value; },
                    set: function (value) {
                        return { end: (value) ? new moment(value, app.translate(app, 'MM/DD/YYYY')).format('YYYY-MM-DD') : value };
                    },
                },
            },
        });

        // ---------------------------------------------------------------
        // View
        // ---------------------------------------------------------------
        Screen.Views.Main = Backbone.Epoxy.View.extend({
            template: 'vtd-production',
            id: 'vtd-production',
            title: 'VTD Production',
            events: function () {
                return {
                    'click #refreshBtn': this.refreshBtn_click,
                    'click .btn-export-to-excel': this.exportToExcel,
                    'click #closeHandAdditionModal': this.refreshBtn_click,
                    'click .handAddToggle': this.hideShowHandAddition,
                    'click #calendarStartBtn': this.calendarStartBtn_click,
                    'click #calendarEndBtn': this.calendarEndBtn_click,
                };
            },
            bindings: 'data-bind',
            bindingSources: null,
            grids: 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 () { };

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

                this.grids = {};
                this.itemsColl = new Screen.Collections.Items();
                this.bindingSources = {};
                this.subviews = {};
                this.autoRefresh = {
                    enabled: null,
                    toid: null,
                    every: 5 * 1000
                };

                this.bindEvents();
                this.getPermissions();
            },

            getPermissions: function () {
                var write = $.inArray('vtdp_w', app.models.user.get('roles'));
                this.model.set('hasPermission', write !== -1);
            },

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

            // ---- Calendar button handlers ----
            calendarStartBtn_click: function () {
                this.$el.find('#dateStartTbx').datepicker('show');
            },
            calendarEndBtn_click: function () {
                this.$el.find('#dateEndTbx').datepicker('show');
            },

            // ---- Row click navigation ----
            navigateToHeatReport: function (rowData) {
                try {
                    if (rowData && rowData.HeatName) {
                        app.router.navigate(
                            app.router.resolveURL('vtd-heat-report', {
                                heatName: rowData.HeatName,
                                treatmentNumber: rowData.Treatment,
                            }, false),
                            { trigger: true }
                        );
                    }
                } catch (Error) { console.error(Error.stack); }
            },

            // ---- Checkbox: isFoamed ----
            onFoamedCheckboxClick: function (rowData, checkbox) {
                var that = this;
                if (!this.model.get('hasPermission')) return;

                var newChecked = checkbox.checked;
                var actionOnCheck = newChecked ? 'Check' : 'Uncheck';

                var modal = new Modal.Views.Main({
                    focusOk: false,
                    focusSelector: '#btn-cancel',
                    title: 'Profiles Screen Role',
                    message: 'Are you sure you want to ' + actionOnCheck + ' Foamed for Heat: ' + rowData.HeatName + '?',
                    buttons_type: 'CONTINUE-CANCEL',
                });

                this.listenToOnce(modal, 'continue', function () {
                    try {
                        var params = { option: 'F', processId: rowData.Id, enabled: newChecked };
                        that.itemsColl.updateFoamedStirredWell(params);
                    } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                });

                this.listenToOnce(modal, 'cancel', function () {
                    try {
                        checkbox.checked = !newChecked;
                    } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                });

                modal.show();
            },

            // ---- Checkbox: isStirredWell ----
            onStirredCheckboxClick: function (rowData, checkbox) {
                var that = this;
                if (!this.model.get('hasPermission')) return;

                var newChecked = checkbox.checked;
                var actionOnCheck = newChecked ? 'Check' : 'Uncheck';

                var modal = new Modal.Views.Main({
                    focusOk: false,
                    focusSelector: '#btn-cancel',
                    title: 'Profiles Screen Role',
                    message: 'Are you sure you want to ' + actionOnCheck + ' Stirred for Heat: ' + rowData.HeatName + '?',
                    buttons_type: 'CONTINUE-CANCEL',
                });

                this.listenToOnce(modal, 'continue', function () {
                    try {
                        var params = { option: 'S', processId: rowData.Id, enabled: newChecked };
                        that.itemsColl.updateFoamedStirredWell(params);
                    } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                });

                this.listenToOnce(modal, 'cancel', function () {
                    try {
                        checkbox.checked = !newChecked;
                    } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                });

                modal.show();
            },

            // ---- Hand Additions button ----
            onHandAdditionsClick: function (rowData) {
                this.showHandAdditionsModal(rowData);
            },

            showHandAdditionsModal: function (rowData) {
                var that = this;
                var params = { ProcessId: rowData.Id };
                var handAdditionAndMat = this.getHandAdditions(params);
                var handAdditions = handAdditionAndMat.handAdditions;
                var materials = handAdditionAndMat.materials;

                // We keep the Backgrid-based modal grid as-is (modals not refactored)
                var CustomRow = Backgrid.Row.extend({
                    render: function () {
                        Backgrid.Row.prototype.render.apply(this, arguments);
                        this.$el.append('<td class="save-button-cell align-center-cell renderable"><button class="save-action-button" style="visibility:hidden;"><i class="fa fa-check-square" aria-hidden="true"></i></button></td>');
                        return this;
                    }
                });

                var DeleteCell = Backgrid.Cell.extend({
                    className: 'delete-cell align-center-cell',
                    events: { 'click .delete-button': 'deleteRow' },
                    render: function () {
                        this.$el.html('<button class="delete-button"><i class="fa fa-minus-circle" aria-hidden="true"></i></button>');
                        return this;
                    },
                    deleteRow: function (e) {
                        var rowElement = $(e.currentTarget).closest('tr');
                        var row = gridAlloys.body.rows.find(function (r) { return r.el === rowElement[0]; });

                        e.preventDefault();
                        $('#handAdditions').addClass('blur');
                        var modal = new Modal.Views.Main({
                            focusOk: false,
                            focusSelector: '#btn-cancel',
                            title: 'Remove Addition',
                            message: 'Are you sure you want to delete the Addition?',
                            buttons_type: 'CONTINUE-CANCEL',
                        });
                        that.listenToOnce(modal, 'continue', function () {
                            try {
                                var removeParams = { HandAdditionId: row.model.get('Id') };
                                var removed = that.removeHandAddition(removeParams);
                                if (removed) {
                                    row.model.collection.remove(row.model);
                                    app.views.topMessages.showMessage('Addition Removed', { stay: 5000 });
                                } else {
                                    app.views.topMessages.showMessage('Error Removing Addition', { stay: 5000 });
                                }
                                $('#handAdditions').removeClass('blur');
                            } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                        });
                        that.listenToOnce(modal, 'cancel', function () {
                            try { $('#handAdditions').removeClass('blur'); }
                            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                        });
                        modal.show();
                    }
                });

                var MaterialSelectCell = Backgrid.SelectCell.extend({
                    className: 'select-cell align-center-cell',
                    initialize: function (options) {
                        Backgrid.SelectCell.prototype.initialize.apply(this, arguments);
                        this.optionValues = materials.map(function (material) {
                            return [material.get('Name'), material.get('Id')];
                        });
                        this.listenTo(this.model, 'change:Material', this.render);
                    },
                    render: function () {
                        var materialName = this.model.get('Material');
                        if (materialName == 'Sulphur') materialName = 'Sulfur';
                        var material = materials.find(function (m) { return m.get('Name') === materialName; });
                        if (material) {
                            this.$el.html('<select>' + this.optionValues.map(function (option) {
                                return '<option value="' + option[1] + '"' + (option[1] === material.get('Id') ? ' selected' : '') + '>' + option[0] + '</option>';
                            }).join('') + '</select>');
                        }
                        this.$el.find('select').on('change', this.updateModel.bind(this));
                        return this;
                    },
                    updateModel: function (e) {
                        var selectedId = this.$el.find('select').val();
                        var selectedMaterial = materials.find(function (material) { return material.get('Id') == selectedId; });
                        if (selectedMaterial) {
                            this.model.set({ 'Material': selectedMaterial.get('Name'), 'MaterialId': selectedId });
                        }
                    }
                });

                var gridAlloys = new Backgrid.Grid({
                    className: 'backgrid table table-hover table-condensed production-table',
                    columns: [
                        { name: 'Material', label: 'Material', cell: MaterialSelectCell, editable: false, sortable: false },
                        {
                            name: 'WeightValue', label: 'Weight',
                            cell: Backgrid.NumberCell.extend({ className: 'number-cell align-center-cell' }),
                            editable: true, sortable: false
                        },
                        {
                            name: 'WeightSetpoint', label: 'Weight SP',
                            cell: Backgrid.StringCell.extend({ className: 'string-cell align-center-cell' }),
                            editable: true, sortable: false
                        },
                        { name: 'Delete', label: '', cell: DeleteCell, editable: false, sortable: false }
                    ],
                    collection: handAdditions,
                    row: CustomRow
                });

                $(".hand-additions-items-grid-container").empty().append(gridAlloys.render().el);

                gridAlloys.body.$el.on('click', '.save-action-button', function (e) {
                    e.preventDefault();
                    var rowElement = $(e.currentTarget).closest('tr');
                    var row = gridAlloys.body.rows.find(function (r) { return r.el === rowElement[0]; });

                    if (row.model.get('NewAddition')) {
                        row.$('.highlight-missing-value').removeClass('highlight-missing-value');
                        var missingValue = false;
                        var requiredFields = ['Material', 'WeightValue', 'WeightSetpoint', 'SourceCode'];
                        requiredFields.forEach(function (field) { if (!row.model.get(field)) missingValue = true; });
                        if (missingValue) {
                            app.views.topMessages.showMessage('Please fill in all required fields', { stay: 5000 });
                            return;
                        }
                        var insertParams = {
                            ProcessId: rowData.Id,
                            MaterialId: materials.filter(function (x) { return x.get('Name') == row.model.get('Material'); })[0].get('Id'),
                            Weight: row.model.get('WeightValue'),
                            WeightSP: row.model.get('WeightSetpoint'),
                            Comments: ''
                        };
                        var inserted = that.insertHandAddition(insertParams);
                        if (inserted) {
                            row.$('.save-action-button').css('visibility', 'hidden');
                            app.views.topMessages.showMessage('New Addition Created', { stay: 5000 });
                        } else {
                            app.views.topMessages.showMessage('Error Creating new Addition', { stay: 5000 });
                        }
                    } else {
                        var updateParams = {
                            AdditionId: row.model.get('Id'),
                            MaterialId: materials.filter(function (x) { return x.get('Name') == row.model.get('Material'); })[0].get('Id'),
                            Weight: row.model.get('WeightValue'),
                            WeightSP: row.model.get('WeightSetpoint'),
                            Comments: ' '
                        };
                        var updated = that.updateHandAddition(updateParams);
                        if (updated) {
                            row.$('.save-action-button').css('visibility', 'hidden');
                            app.views.topMessages.showMessage('Addition Updated', { stay: 5000 });
                        } else {
                            app.views.topMessages.showMessage('Error Updating Addition', { stay: 5000 });
                        }
                    }
                });

                $('#addHandAdditionBtn').on('click', function (e) {
                    e.preventDefault();
                    var newHandAddition = new Backbone.Model({
                        Timestamp: '',
                        Material: 'CaSi    ',
                        WeightValue: null,
                        WeightSetpoint: null,
                        SourceCode: 'W',
                        NewAddition: true
                    });
                    handAdditions.add(newHandAddition);
                });

                handAdditions.on('change', function (model) {
                    var row = gridAlloys.body.rows.find(function (r) { return r.model === model; });
                    if (row) { row.$('.save-action-button').css('visibility', 'visible'); }
                });

                $('#handAdditions').modal('show');
            },

            // ---- Data access helpers for Hand Additions (unchanged) ----
            getHandAdditions: function (params) {
                var qp = new Core.Database.QueryParameters();
                var handAdditions = new Screen.Collections.ItemsCollection();
                var materials = new Screen.Collections.ItemsCollection();

                var fixedParameters = [
                    { Name: '@processId', Type: 'INT', Value: params.ProcessId },
                ];
                _.each(fixedParameters, function (qpParams) { qp.Add(qpParams.Name, qpParams.Type, qpParams.Value); });

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.VTD.GetHandAdditionsByProcessId', qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (resp && resp.Table) {
                                    handAdditions.setDataColl(resp.Table);
                                    materials.setDataColl(resp.Table1);
                                } else {
                                    if (resp && resp.Message) console.error(new Error(resp.Message).stack);
                                    else console.error(new Error('SERVER_RESPONSE_NOT_VALID').stack);
                                }
                            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        onFailure: function (resp) { console.error(resp); },
                        Secured: false,
                        Async: false,
                    },
                    app.ConnectionStrings.app
                );

                return { handAdditions: handAdditions, materials: materials };
            },

            removeHandAddition: function (params) {
                var qp = new Core.Database.QueryParameters();
                var removed = false;
                var fixedParameters = [
                    { Name: '@id', Type: 'INT', Value: params.HandAdditionId },
                    { Name: '@comment', Type: 'VARCHAR', Value: ' ' },
                ];
                _.each(fixedParameters, function (qpParams) { qp.Add(qpParams.Name, qpParams.Type, qpParams.Value); });

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.VTD.RemoveAdditionManually', qp,
                    {
                        onSuccess: function (resp) {
                            try { if (resp && resp.Table) removed = true; }
                            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        onFailure: function (resp) { console.error(resp); },
                        Secured: false,
                        Async: false,
                    },
                    app.ConnectionStrings.app
                );
                return removed;
            },

            updateHandAddition: function (params) {
                var qp = new Core.Database.QueryParameters();
                var updated = false;
                var fixedParameters = [
                    { Name: '@id', Type: 'INT', Value: params.AdditionId },
                    { Name: '@materialId', Type: 'INT', Value: params.MaterialId },
                    { Name: '@weight', Type: 'FLOAT', Value: params.Weight },
                    { Name: '@weightSP', Type: 'FLOAT', Value: params.WeightSP },
                    { Name: '@comment', Type: 'VARCHAR', Value: ' ' },
                ];
                _.each(fixedParameters, function (qpParams) { qp.Add(qpParams.Name, qpParams.Type, qpParams.Value); });

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.VTD.UpdateAdditionManually', qp,
                    {
                        onSuccess: function (resp) {
                            try { if (resp && resp.Table) updated = true; }
                            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        onFailure: function (resp) { console.error(resp); },
                        Secured: false,
                        Async: false,
                    },
                    app.ConnectionStrings.app
                );
                return updated;
            },

            insertHandAddition: function (params) {
                var qp = new Core.Database.QueryParameters();
                var inserted = false;
                var fixedParameters = [
                    { Name: '@processId', Type: 'INT', Value: params.ProcessId },
                    { Name: '@materialId', Type: 'INT', Value: params.MaterialId },
                    { Name: '@weight', Type: 'FLOAT', Value: params.Weight },
                    { Name: '@weightSP', Type: 'FLOAT', Value: params.WeightSP },
                    { Name: '@comment', Type: 'VARCHAR', Value: ' ' },
                    { Name: '@dumpStart', Type: 'VARCHAR', Value: params.Timestamp },
                ];
                _.each(fixedParameters, function (qpParams) { qp.Add(qpParams.Name, qpParams.Type, qpParams.Value); });

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.VTD.InsertAdditionManually', qp,
                    {
                        onSuccess: function (resp) {
                            try { if (resp && resp.Table) inserted = true; }
                            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        onFailure: function (resp) { console.error(resp); },
                        Secured: false,
                        Async: false,
                    },
                    app.ConnectionStrings.app
                );
                return inserted;
            },

            // ---- Hand Additions toggle (show/hide columns dynamically) ----
            hideShowHandAddition: function (e) {
                var visible = e.target.checked;
                this.model.set('hideShowHandAdditionToggle', visible);
                this.toggleHandAdditionColumns(visible);
            },

            toggleHandAdditionColumns: function (visible) {
                if (this.agGridModule && this.agGridModule.gridApi) {
                    var handAddCols = ['MAluminum', 'MCaSi', 'MFeB', 'MFeTi', 'MSulphur'];
                    this.agGridModule.gridApi.setColumnsVisible(handAddCols, visible);
                }
            },

            // ---- Refresh logic ----
            _refresh: function (opt) {
                this.itemsColl.reset();

                this.model.set({
                    hasData: false,
                    isLoading: true,
                });

                if (this.agGridModule && this.agGridModule.showLoadingOverlay) {
                    this.agGridModule.showLoadingOverlay();
                }

                if (this.autoRefresh.toid != null) {
                    clearTimeout(this.autoRefresh.toid);
                    this.autoRefresh.toid = null;
                }

                this.refreshProcesses(opt);

                if (this.autoRefresh.enabled == true) {
                    var that = this;
                    this.autoRefresh.toid = setTimeout(
                        function () { that._refresh(); },
                        this.autoRefresh.every
                    );
                }
            },

            refresh: function (viewParams) {
                var fixedParams = _.extend({}, Screen.Models.Main.prototype.defaults, viewParams);

                if (viewParams.start)
                    fixedParams.start = new moment(fixedParams.start, 'YYYYMMDD').format('YYYY-MM-DD');
                if (viewParams.end)
                    fixedParams.end = new moment(fixedParams.end, 'YYYYMMDD').format('YYYY-MM-DD');
                if (viewParams.tankCode)
                    fixedParams.tankCode = (viewParams.tankCode != '-' && viewParams.tankCode != null) ? parseInt(viewParams.tankCode, 10) : null;
                if (viewParams.crewId)
                    fixedParams.crewId = (viewParams.crewId != '-' && viewParams.crewId != null) ? viewParams.crewId : null;
                if (viewParams.shiftId)
                    fixedParams.shiftId = (viewParams.shiftId != '-' && viewParams.shiftId != null) ? parseInt(viewParams.shiftId, 10) : null;

                this.model.set(fixedParams);

                this._refresh({
                    reset: true,
                    params: _.extend({}, fixedParams, {}),
                });
            },

            // ---- Render ----
            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/vtd/' + 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.$('.handAddToggle').prop('checked', that.model.get('hideShowHandAdditionToggle'));

                                // Create AG Grid module
                                that.agGridModule = new CustomAgGridModule({
                                    columnDefs: getColumnDefs(that),
                                    mainView: that,
                                    rowData: [],
                                    fileName: 'VTD-Production',
                                    gridOptions: {
                                        wrapHeaderText: true,
                                        autoHeaderHeight: true,
                                    }
                                });
                                that.agGridModule.render();
                                that.$el.find('.processes-grid-container').empty().append(that.agGridModule.$el);

                                that.$el.find('.input-date').datepicker();

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

                                // Set model with view params
                                var fixedParams = _.extend({}, viewParams);

                                if (fixedParams.start)
                                    fixedParams.start = new moment(fixedParams.start, 'YYYYMMDD').format('YYYY-MM-DD');
                                if (fixedParams.end)
                                    fixedParams.end = new moment(fixedParams.end, 'YYYYMMDD').format('YYYY-MM-DD');
                                if (viewParams.tankCode)
                                    fixedParams.tankCode = (viewParams.tankCode != '-' && viewParams.tankCode != null) ? parseInt(viewParams.tankCode, 10) : null;
                                if (viewParams.crewId)
                                    fixedParams.crewId = (viewParams.crewId != '-' && viewParams.crewId != null) ? viewParams.crewId : null;
                                if (viewParams.shiftId)
                                    fixedParams.shiftId = (viewParams.shiftId != '-' && viewParams.shiftId != null) ? parseInt(viewParams.shiftId, 10) : null;

                                that.model.set(fixedParams);

                                // Wait for grid to be ready, then refresh + toggle columns
                                var params = that.model.toJSON();
                                that.agGridModule.gridReadyPromise.then(function () {
                                    // Hide hand addition columns if toggle is off
                                    that.toggleHandAdditionColumns(that.model.get('hideShowHandAdditionToggle'));

                                    that._refresh({
                                        reset: true,
                                        params: _.extend({}, params, {}),
                                    });
                                });
                            },
                            true,
                            customPath
                        );
                    },
                    customPath
                );
            },

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

            // ---- Fetch data ----
            refreshProcesses: function (options) {
                var attrs = this.model.toJSON(),
                    opt = _.extend({}, options, { params: {} });

                if ((opt.refresh == true) || (opt.reset == true)) {
                    this.model.set('isLoading', true);
                    if (this.agGridModule && this.agGridModule.showLoadingOverlay) {
                        this.agGridModule.showLoadingOverlay();
                    }
                }

                this.itemsColl.fetch({
                    start: attrs.start,
                    end: attrs.end,
                    crewId: (attrs.crewId == '') ? null : attrs.crewId,
                    shiftId: (attrs.shiftId == '') ? null : attrs.shiftId,
                    refresh: true,
                    tankCode: attrs.tankCode ? attrs.tankCode : null,
                });
            },

            // ---- Excel export (server-side, unchanged) ----
            exportToExcel: function () {
                var that = this,
                    params = this.model.toJSON();

                var qpParams = [
                    { Name: '@start', Type: 'DATETIME', Value: params.start },
                    { Name: '@end', Type: 'DATETIME', Value: params.end },
                    { Name: '@crewId', Type: 'CHAR', Value: (params.crewId != '' && params.crewId != '-') ? params.crewId : null },
                    { Name: '@shiftId', Type: 'INT', Value: (params.shiftId != '' && params.shiftId != '-') ? params.shiftId : null },
                    { Name: '@tankCode', Type: 'INT', Value: (params.tankCode != '' && params.tankCode != '-') ? params.tankCode : null },
                    { Name: '@TimeZoneCode', Type: 'CHAR', Value: app.models.user.get('timezoneCode') },
                ];
                var QP = new QueryParameters();
                _.each(qpParams, function (p) { QP.Add(p.Name, p.Type, p.Value); });

                var data = {
                    Data: [],
                    ConnectionStringName: 'APP',
                    ExportMethod: 3,
                    FileName: 'VTD-Production',
                    TemplateFileFullPath: 'generic.xls',
                    SQLDataSources: [{
                        Name: 'data',
                        DatabaseParameters: {
                            DBEngine: 'SQLSERVER',
                            Procedure: app.DatabaseNames.MES + '.VTD.GetProcesses',
                            QueryParameters: QP,
                        },
                    }]
                };

                data.Data.push({
                    SheetName: 'Data',
                    RowsData: [{
                        CellsData: [
                            { Column: 'A', Value: 'Heat' },
                            { Column: 'B', Value: 'Shift' },
                            { Column: 'C', Value: 'Crew' },
                            { Column: 'D', Value: 'Tank' },
                            { Column: 'E', Value: 'Ladle' },
                            { Column: 'F', Value: 'Start' },
                            { Column: 'G', Value: 'End' },
                            { Column: 'H', Value: 'Total Time' },
                            { Column: 'I', Value: 'Treatment' },
                            { Column: 'J', Value: 'Minimum Torr' },
                            { Column: 'K', Value: 'Minimum Torr Time' },
                            { Column: 'L', Value: 'Wire Additions' },
                            { Column: 'M', Value: 'Vaccum Time' },
                            { Column: 'N', Value: 'Melt Order' },
                            { Column: 'O', Value: 'Grade' },
                            { Column: 'P', Value: 'Temperature' },
                            { Column: 'Q', Value: 'Wired-Al' },
                            { Column: 'R', Value: 'Wired-CaSi' },
                            { Column: 'S', Value: 'Wired-FeB' },
                            { Column: 'T', Value: 'Wired-FeTi' },
                            { Column: 'U', Value: 'Wired-Sulfur' },
                            { Column: 'V', Value: 'Manual-Al' },
                            { Column: 'W', Value: 'Manual-CaSi' },
                            { Column: 'X', Value: 'Manual-FeB' },
                            { Column: 'Y', Value: 'Manual-FeTi' },
                            { Column: 'Z', Value: 'Manual-Sulfur' },
                            { Column: 'AA', Value: 'Heat Foamed' },
                            { Column: 'AB', Value: 'Ladle Stirred Well' },
                        ],
                    }],
                    StartRowIndex: 1,
                });

                data.Data.push({
                    SheetName: 'Data',
                    RowsData: [],
                    StartRowIndex: 2,
                    DataSourceName: 'data',
                    DataSourceTableIndex: 0,
                    SQLCellsData: [
                        { ExcelColumnName: 'A', SQLDataColumnName: 'HeatName', DataType: 'String' },
                        { ExcelColumnName: 'B', SQLDataColumnName: 'ShiftName', DataType: 'String' },
                        { ExcelColumnName: 'C', SQLDataColumnName: 'CrewId', DataType: 'String' },
                        { ExcelColumnName: 'D', SQLDataColumnName: 'TankCode', DataType: 'String' },
                        { ExcelColumnName: 'E', SQLDataColumnName: 'LadleId', DataType: 'String' },
                        { ExcelColumnName: 'F', SQLDataColumnName: 'StartLocal', DataType: 'String' },
                        { ExcelColumnName: 'G', SQLDataColumnName: 'EndLocal', DataType: 'String' },
                        { ExcelColumnName: 'H', SQLDataColumnName: 'TotalTime', DataType: 'String' },
                        { ExcelColumnName: 'I', SQLDataColumnName: 'Treatment', DataType: 'String' },
                        { ExcelColumnName: 'J', SQLDataColumnName: 'MinimumTorr', DataType: 'String' },
                        { ExcelColumnName: 'K', SQLDataColumnName: 'MinTorrTime', DataType: 'String' },
                        { ExcelColumnName: 'L', SQLDataColumnName: 'WireAdditions', DataType: 'String' },
                        { ExcelColumnName: 'M', SQLDataColumnName: 'VacTime', DataType: 'String' },
                        { ExcelColumnName: 'N', SQLDataColumnName: 'MeltOrder', DataType: 'String' },
                        { ExcelColumnName: 'O', SQLDataColumnName: 'GradeName', DataType: 'String' },
                        { ExcelColumnName: 'P', SQLDataColumnName: 'Temperature', DataType: 'String' },
                        { ExcelColumnName: 'Q', SQLDataColumnName: 'Aluminum', DataType: 'String' },
                        { ExcelColumnName: 'R', SQLDataColumnName: 'CaSi', DataType: 'String' },
                        { ExcelColumnName: 'S', SQLDataColumnName: 'FeB', DataType: 'String' },
                        { ExcelColumnName: 'T', SQLDataColumnName: 'FeTi', DataType: 'String' },
                        { ExcelColumnName: 'U', SQLDataColumnName: 'Sulphur', DataType: 'String' },
                        { ExcelColumnName: 'V', SQLDataColumnName: 'MAluminum', DataType: 'String' },
                        { ExcelColumnName: 'W', SQLDataColumnName: 'MCaSi', DataType: 'String' },
                        { ExcelColumnName: 'X', SQLDataColumnName: 'MFeB', DataType: 'String' },
                        { ExcelColumnName: 'Y', SQLDataColumnName: 'MFeTi', DataType: 'String' },
                        { ExcelColumnName: 'Z', SQLDataColumnName: 'MSulphur', DataType: 'String' },
                        { ExcelColumnName: 'AA', SQLDataColumnName: 'isFoamed', DataType: 'String' },
                        { ExcelColumnName: 'AB', SQLDataColumnName: 'isStirredWell', DataType: 'String' },
                    ],
                });

                Core.Export.Excel(
                    data,
                    function (resp) {
                        try {
                            if (resp && resp.Success == true && resp.Data) {
                                location.href = app.foldersRoot + '/excel/' + resp.Data;
                            } else {
                                if (resp && resp.Message) console.error(resp.Message);
                                else console.error('Server response not valid.');
                            }
                        } catch (Error) { console.error(Error); }
                    },
                    function (resp) {
                        console.error(resp);
                    }
                );
            },

            // ---- Refresh button ----
            refreshBtn_click: function (e) {
                try {
                    var params = this.model.toJSON();
                    app.router.navigate(
                        app.router.resolveURL(
                            app.router.currentModule,
                            _.extend({}, params, {
                                start: new moment(params.start, 'YYYY-MM-DD').format('YYYYMMDD'),
                                end: new moment(params.end, 'YYYY-MM-DD').format('YYYYMMDD'),
                                tankCode: (params.tankCode == null || params.tankCode == '') ? '-' : params.tankCode,
                                crewId: (params.crewId == null || params.crewId == '') ? '-' : params.crewId,
                                shiftId: (params.shiftId == null || params.shiftId == '') ? '-' : params.shiftId,
                            }),
                            false
                        ),
                        { trigger: false }
                    );

                    this._refresh({
                        reset: true,
                        params: _.extend({}, params, {}),
                    });

                    window.scrollTo(0, 0);
                } catch (Error) { console.error(Error.stack); }
            },

            // ---- Common view lifecycle methods ----
            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;
                }
            },
            close: function () {
                this.options.state = app.view_states.closed;
                if (this.agGridModule && this.agGridModule.destroy) {
                    this.agGridModule.destroy();
                }
                this.closeSubviews();
                this.remove();
                this.unbind();
            },
            closeSubviews: function () {
                _.each(this.subviews, function (sview) { 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) { 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) { sview.hide(); });
            },
            preRender: function () {
                app.models.subnavbar.set('subnavbar', false);
            },
            reRender: function (viewParams) {
                try { this.refresh(viewParams); } catch (Error) { }
            },
        });

        // ---------------------------------------------------------------
        // Collection: Main items (VTD Processes)
        // ---------------------------------------------------------------
        Screen.Collections.Items = Backbone.Collection.extend({
            isFetching: false,
            currentPage: 1,
            pageSize: 100,
            fixedParameters: [],

            fetch: function (params) {
                var that = this,
                    qp = new Core.Database.QueryParameters(),
                    options = params ? _.clone(params) : {};

                if (options.refresh) {
                    this.resetPagination(true);
                    this.fixedParameters = [
                        { Name: '@Start', Type: 'DATETIME', Value: params.start },
                        { Name: '@End', Type: 'DATETIME', Value: params.end },
                        { Name: '@CrewId', Type: 'CHAR', Value: params.crewId != '-' ? params.crewId : null },
                        { Name: '@ShiftId', Type: 'INT', Value: params.shiftId != '-' ? params.shiftId : null },
                        { Name: '@TimeZoneCode', Type: 'CHAR', Value: app.models.user.get('timezoneCode') },
                        { Name: '@TankCode', Type: 'INT', Value: params.tankCode },
                    ];
                }
                this.isFetching = true;

                _.each(this.fixedParameters, function (qpParams) {
                    qp.Add(qpParams.Name, qpParams.Type, qpParams.Value);
                });

                if (!options.refresh) {
                    qp.Add('@fromRow', 'INT', (this.currentPage - 1) * this.pageSize + 1);
                    qp.Add('@rowsToFetch', 'INT', this.pageSize - 1);
                } else {
                    qp.Add('@fromRow', 'INT', 0);
                    qp.Add('@toRow', 'INT', this.currentPage * this.pageSize);
                    qp.Add('@rowsToFetch', 'INT', this.pageSize);
                }

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.VTD.GetProcesses', qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (resp && resp.Table) {
                                    var newColl = resp.Table;
                                    var method = (options.refresh) ? 'set' : 'add';
                                    that[method](newColl);
                                    that.trigger('fetch', that, newColl);
                                    if (newColl.length == 0 && method == 'add') that.currentPage--;
                                    that.isFetching = false;
                                } else {
                                    if (resp && resp.Message) {
                                        console.error(new Error(resp.Message).stack);
                                        app.views.topMessages.showMessage('CALL TO DATABASE FAILED', { stay: 5000 });
                                    } else {
                                        app.views.topMessages.showMessage('SERVER RESPONSE NOT VALID', { stay: 5000 });
                                        console.error(new Error('SERVER_RESPONSE_NOT_VALID').stack);
                                    }
                                }
                            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        onFailure: function (resp) { console.error(resp); },
                        Secured: true,
                        Async: true,
                    },
                    app.ConnectionStrings.app
                );
                return this;
            },

            updateFoamedStirredWell: function (params) {
                var qp = new Core.Database.QueryParameters();
                var fixedParameters = [
                    { Name: '@Option', Type: 'CHAR', Value: params.option },
                    { Name: '@ProcessId', Type: 'INT', Value: params.processId },
                    { Name: '@Enabled', Type: 'BIT', Value: params.enabled },
                ];
                _.each(fixedParameters, function (qpParams) {
                    qp.Add(qpParams.Name, qpParams.Type, qpParams.Value);
                });

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.VTD.UpdateFoamedStirredWell', qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (resp) {
                                    app.views.topMessages.showMessage('Updated successfully', { stay: 3000 });
                                } else {
                                    if (resp && resp.Message) {
                                        console.error(new Error(resp.Message).stack);
                                        app.views.topMessages.showMessage('CALL TO DATABASE FAILED', { stay: 5000 });
                                    } else {
                                        app.views.topMessages.showMessage('SERVER RESPONSE NOT VALID', { stay: 5000 });
                                        console.error(new Error('SERVER_RESPONSE_NOT_VALID').stack);
                                    }
                                }
                            } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        onFailure: function (resp) { console.error(resp); },
                        Secured: true,
                        Async: true,
                    },
                    app.ConnectionStrings.app
                );
                return this;
            },

            getNextPage: function (options) {
                if (!this.isFetching) {
                    this.currentPage++;
                    options = (_.isObject(options)) ? options : {};
                    this.fetch(options);
                }
            },

            resetPagination: function (force) {
                if (!this.isFetching || force == true) {
                    this.currentPage = 1;
                } else {
                    _.delay(this.resetPagination, 100);
                }
            },
        });

        // ---------------------------------------------------------------
        // Collection: Generic items (for Hand Additions modal)
        // ---------------------------------------------------------------
        Screen.Collections.ItemsCollection = Backbone.Collection.extend({
            setDataColl: function (data) {
                var newColl,
                    that = this;
                newColl = data;
                that.set(newColl).trigger('fetch', that, data);
            },
        });

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