//SCREEN-BOILERPLATE
//Chemistry Summary - read-only AG Grid screen with date OR heat filtering.
//Replaces the legacy custom-screens/chemistry-summary (Backgrid) screen.

define([
    'app',
    'js/templates-loader',
    'moment',
    'components/ag-grid/ag-grid-module',
    'modules/eaf-process/eaf-process',

    'js/typeahead.extended/typeahead.extended',
],
    function (app, T, moment, AgGridModule, EafProcess) {

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

        // ---------------------------------------------------------------
        // Configuration
        // ---------------------------------------------------------------
        var AUTO_REFRESH_INTERVAL_SECONDS = 60;
        var AUTO_REFRESH_STORAGE_KEY = 'chemistry-summary.autoRefresh.enabled';

        // -------------------------------------------------------------
        // Cell renderers
        // -------------------------------------------------------------

        // Heat name → clickable link that navigates to eaf-heat-report
        function heatLinkRenderer(params) {
            if (!params.value) return '';
            return '<span class="heat-link">' + params.value + '</span>';
        }

        // Sample-count bullet: red×=0, yellow✓=1, green✓=2+
        function samplesBulletRenderer(params) {
            var v = Number(params.value);
            if (isNaN(v)) v = 0;
            var cls, icon, title;
            if (v === 0)      { cls = 'no-samples';  icon = 'fa-times'; title = 'No samples'; }
            else if (v === 1) { cls = 'one-sample';  icon = 'fa-check'; title = '1 sample (insufficient)'; }
            else              { cls = 'two-samples'; icon = 'fa-check'; title = v + ' samples'; }
            return '<span class="bullet ' + cls + '" title="' + title + '"><i class="fa ' + icon + '"></i></span>';
        }

        // -------------------------------------------------------------
        // Column definitions
        // -------------------------------------------------------------
        function buildColumnDefs() {
            var sampleCol = function (field, header) {
                return {
                    field: field, headerName: header,
                    flex: 0.8, minWidth: 70,
                    cellRenderer: samplesBulletRenderer,
                    cellClass: 'text-center',
                    headerClass: 'ag-header-cell-center',
                    sortable: false,
                };
            };

            return [
                {
                    field: 'HeatName', headerName: 'Heat',
                    pinned: 'left', width: 110,
                    cellRenderer: heatLinkRenderer,
                    cellClass: 'text-center',
                    headerClass: 'ag-header-cell-center',
                },
                {
                    field: 'GradeName', headerName: 'Grade',
                    flex: 1, minWidth: 90,
                    cellClass: 'text-center',
                    headerClass: 'ag-header-cell-center',
                },
                {
                    field: 'TimestampString', headerName: 'Start Tap',
                    flex: 1.2, minWidth: 140,
                    cellClass: 'text-center',
                    headerClass: 'ag-header-cell-center',
                },
                sampleCol('EafSamplesCount',     'EAF'),
                sampleCol('SlagEAFSamplesCount', 'EAF Slag'),
                sampleCol('LfSamplesCount',      'LF'),
                sampleCol('SlagLFSamplesCount',  'LF Slag'),
                sampleCol('LicoSamplesCount',    'LECO'),
                sampleCol('VtdSamplesCount',     'VTD'),
                sampleCol('CasterSamplesCount',  'Caster'),
            ];
        }

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

                // Heat picker state
                heatId: null,           // null = no heat filter (date range wins)
                heatSearch: '',         // current text in the heat input
                navigating: false,

                // Misc filters
                onlyMissing: false,
                eafChecked:     true,
                eafSlagChecked: true,
                lfChecked:      true,
                lfSlagChecked:  true,
                licoChecked:    true,
                vtdChecked:     true,
                casterChecked:  true,

                // UI state
                hasData: false,
                isLoading: false,

                // Auto refresh (countdown pattern — matches power-curtailment)
                autoRefreshEnabled: true,
                countdown: AUTO_REFRESH_INTERVAL_SECONDS,
                lastUpdatedText: '-',
            },
            computeds: {
                start$: {
                    deps: ['start'],
                    get: function (v) { return v; },
                    set: function (v) {
                        return { start: v ? new moment(v, app.translate(app, 'MM/DD/YYYY')).format('YYYY-MM-DD') : v };
                    },
                },
                end$: {
                    deps: ['end'],
                    get: function (v) { return v; },
                    set: function (v) {
                        return { end: v ? new moment(v, app.translate(app, 'MM/DD/YYYY')).format('YYYY-MM-DD') : v };
                    },
                },
                // Heat is "active" whenever heatId is a real id (>0 means a specific heat;
                // -1 means "current heat" — also active).
                heatActive: {
                    deps: ['heatId'],
                    get: function (heatId) {
                        return heatId != null && heatId !== '';
                    },
                },
                filterStatusText: {
                    deps: ['heatId', 'heatSearch', 'start', 'end'],
                    get: function (heatId, heatSearch, start, end) {
                        if (heatId != null && heatId !== '') {
                            var label = heatSearch && heatSearch !== '' ? heatSearch
                                      : (heatId === -1 || heatId === '-1' ? 'current heat' : '#' + heatId);
                            return 'Filtering by heat: ' + label;
                        }
                        var s = start ? new moment(start, 'YYYY-MM-DD').format('MM/DD') : '?';
                        var e = end   ? new moment(end,   'YYYY-MM-DD').format('MM/DD') : '?';
                        return 'Filtering by date: ' + s + ' – ' + e;
                    },
                },
            },
        });

        // -------------------------------------------------------------
        // Collection
        // -------------------------------------------------------------
        Screen.Collections.Items = Backbone.Collection.extend({
            fetch: function (params) {
                var that = this,
                    qp = new Core.Database.QueryParameters();

                qp.Add('@start',       'DATETIME', params.start);
                qp.Add('@end',         'DATETIME', params.end);
                qp.Add('@heatId',      'INT',      params.heatId);
                qp.Add('@onlyMissing', 'BIT',      params.onlyMissing);
                qp.Add('@eaf',         'BIT',      params.eafChecked);
                qp.Add('@eafSlag',     'BIT',      params.eafSlagChecked);
                qp.Add('@lf',          'BIT',      params.lfChecked);
                qp.Add('@lfSlag',      'BIT',      params.lfSlagChecked);
                qp.Add('@lico',        'BIT',      params.licoChecked);
                qp.Add('@vtd',         'BIT',      params.vtdChecked);
                qp.Add('@caster',      'BIT',      params.casterChecked);
                qp.Add('@timeZoneCode','CHAR',     app.models.user.get('timezoneCode'));

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.LAB.GetChemistriesSummary',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (resp && resp.Table) {
                                    that.set(resp.Table);
                                    that.trigger('fetch', that, resp.Table);
                                } 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;
            },
        });

        // -------------------------------------------------------------
        // View
        // -------------------------------------------------------------
        Screen.Views.Main = Backbone.Epoxy.View.extend({
            template: 'chemistry-summary',
            id: 'chemistry-summary',
            title: 'Chemistry Summary',

            events: function () {
                return {
                    'click #refreshBtn':         this.refreshBtn_click,
                    'click #excelBtn':           this.exportToExcel,
                    'click #calendarStartBtn':   this.calendarStartBtn_click,
                    'click #calendarEndBtn':     this.calendarEndBtn_click,
                    'click #getPreviousItemBtn': this.getPreviousItemBtn_click,
                    'click #getNextItemBtn':     this.getNextItemBtn_click,
                    'click #goToCurrentBtn':     this.goToCurrentBtn_click,
                    'click #clearHeatBtn':       this.clearHeatBtn_click,
                    'click #autoRefreshToggle':  this.autoRefreshToggle_click,
                    'keypress #heatSearchTbx':   this.heatSearch_keypress,
                };
            },
            bindings: 'data-bind',

            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.itemsColl = new Screen.Collections.Items();
                this.eafProcess = new EafProcess.Models.EafProcess();
                this.searchItems = {};
                this.subviews = {};

                this.autoRefresh = {
                    tickId: null,
                    remaining: AUTO_REFRESH_INTERVAL_SECONDS,
                };

                // Restore last user preference for auto-refresh from localStorage
                try {
                    var stored = localStorage.getItem(AUTO_REFRESH_STORAGE_KEY);
                    if (stored != null) this.model.set('autoRefreshEnabled', stored === 'true');
                } catch (e) {}

                this.bindEvents();
            },

            bindEvents: function () {
                this.listenTo(this.itemsColl, 'fetch', this.items_ready);
                this.listenTo(this.eafProcess, 'change:heatName', this.eafProcess_change_heatName);
                this.listenTo(this.model, 'change:heatId', this.heatId_change);
            },

            // -------------------------------------------------------------
            // 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/lab/' + 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.$el.find('.input-date').datepicker();

                                // Typeahead on heat search input
                                that.searchTbx = that.$el.find('#heatSearchTbx').typeaheadExtended({
                                    items: Infinity,
                                    minLength: 0,
                                    source: _.bind(that.getSearchControlSource, that),
                                    updater: function (item) {
                                        var match;
                                        try { match = that.selectItemFromSearchComboItem(item); }
                                        catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                                        return match ? match.heatName : item;
                                    },
                                });

                                // AG Grid module
                                that.agGridModule = new AgGridModule({
                                    columnDefs: buildColumnDefs(),
                                    rowData: [],
                                    fileName: 'Chemistry-Summary',
                                    screenTitle: that.title,
                                    gridOptions: {
                                        wrapHeaderText: true,
                                        autoHeaderHeight: true,
                                        onRowClicked: function (params) {
                                            if (params.data && params.data.HeatName) {
                                                app.router.navigate(
                                                    app.router.resolveURL('eaf-heat-report', { heatName: params.data.HeatName }, false),
                                                    { trigger: true }
                                                );
                                            }
                                        },
                                    },
                                });
                                that.agGridModule.render();
                                that.$el.find('.processes-grid-container').empty().append(that.agGridModule.$el);

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

                                // Apply URL params after render so we don't fight bindings
                                that.applyViewParams(viewParams || {});

                                // Wait for the grid to be ready, then fire the first refresh.
                                // Start the countdown tick — it self-gates on autoRefreshEnabled
                                // so the user can freely toggle without restarting timers.
                                that.agGridModule.gridReadyPromise.then(function () {
                                    that._refresh({ reset: true });
                                    that.startAutoRefreshTick();
                                });
                            },
                            true,
                            customPath
                        );
                    },
                    customPath
                );
            },

            // -------------------------------------------------------------
            // URL params → model
            // -------------------------------------------------------------
            applyViewParams: function (viewParams) {
                var fixed = {};

                // Heat takes priority if present in URL
                if (viewParams.heatId != null && viewParams.heatId !== '-' && viewParams.heatId !== '') {
                    fixed.heatId = parseInt(viewParams.heatId, 10);
                    fixed.heatSearch = '';
                }

                if (viewParams.start)
                    fixed.start = new moment(viewParams.start, 'YYYYMMDD').format('YYYY-MM-DD');
                if (viewParams.end)
                    fixed.end   = new moment(viewParams.end,   'YYYYMMDD').format('YYYY-MM-DD');

                if (typeof viewParams.onlyMissing !== 'undefined')
                    fixed.onlyMissing = String(viewParams.onlyMissing).toLowerCase() === 'true';

                _.each([
                    ['eaf',     'eafChecked'],
                    ['eafSlag', 'eafSlagChecked'],
                    ['lf',      'lfChecked'],
                    ['lfSlag',  'lfSlagChecked'],
                    ['lico',    'licoChecked'],
                    ['vtd',     'vtdChecked'],
                    ['caster',  'casterChecked'],
                ], function (pair) {
                    var k = pair[0], modelKey = pair[1];
                    if (typeof viewParams[k] !== 'undefined') {
                        fixed[modelKey] = String(viewParams[k]).toLowerCase() === 'true';
                    }
                });

                this.model.set(fixed);
            },

            refresh: function (viewParams) {
                this.applyViewParams(viewParams || {});
                this._refresh({ reset: true });
            },

            // -------------------------------------------------------------
            // Data refresh — Heat (when set) wins over Date range. The SP
            // ignores @start/@end when @heatId is not NULL.
            // Each manual refresh also resets the countdown so the user
            // gets a full interval before the next auto-tick.
            // -------------------------------------------------------------
            _refresh: function () {
                this.model.set({ hasData: false, isLoading: true });
                if (this.agGridModule && this.agGridModule.showLoadingOverlay) {
                    this.agGridModule.showLoadingOverlay();
                }

                this.itemsColl.reset();
                this.fetchItems();

                this.autoRefresh.remaining = AUTO_REFRESH_INTERVAL_SECONDS;
                this.model.set('countdown', AUTO_REFRESH_INTERVAL_SECONDS);
            },

            fetchItems: function () {
                var attrs = this.model.toJSON();
                var heatActive = attrs.heatId != null && attrs.heatId !== '';

                this.itemsColl.fetch({
                    start:       heatActive ? null : attrs.start,
                    end:         heatActive ? null : new moment(attrs.end, 'YYYY-MM-DD').add(1, 'days').format('YYYY-MM-DD'),
                    heatId:      heatActive ? attrs.heatId : null,
                    onlyMissing: heatActive ? false : attrs.onlyMissing,
                    eafChecked:     attrs.eafChecked,
                    eafSlagChecked: attrs.eafSlagChecked,
                    lfChecked:      attrs.lfChecked,
                    lfSlagChecked:  attrs.lfSlagChecked,
                    licoChecked:    attrs.licoChecked,
                    vtdChecked:     attrs.vtdChecked,
                    casterChecked:  attrs.casterChecked,
                });
            },

            items_ready: function () {
                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,
                        lastUpdatedText: new moment().format('HH:mm:ss'),
                    });
                }, 50);
            },

            // -------------------------------------------------------------
            // Heat navigation (Prev / Next / Current)
            // -------------------------------------------------------------
            getNextProcess: function (next) {
                var that = this;
                this.model.set('navigating', true);

                this.eafProcess.getNextProcess({
                    params: { next: next },
                    success: function (model, nextProcess) {
                        try {
                            if (nextProcess && nextProcess.heatId) {
                                that.model.set({ heatId: nextProcess.heatId, navigating: false });
                            } else {
                                that.model.set('navigating', false);
                                var msg = next
                                    ? app.translate([that, app], 'no_next_process')
                                    : app.translate([that, app], 'no_previous_process');
                                app.views.topMessages.showMessage(msg, { stay: 5 * 1000 });
                            }
                        } catch (error) {
                            console.error((error.stack) ? error.stack : new Error(error).stack);
                            that.model.set('navigating', false);
                        }
                    },
                    error: function () { that.model.set('navigating', false); },
                });
            },

            heatId_change: function () {
                // When the heat id changes, resolve it via EAF.GetProcesses so we
                // get the canonical HeatName (which then populates the input via
                // eafProcess_change_heatName). Legacy convention:
                //   heatId === -1  →  ask for the CURRENT process (id: -1, heatId: null)
                //   heatId  > 0    →  ask for that SPECIFIC heat   (id: null, heatId: <n>)
                var heatId = this.model.get('heatId');

                if (heatId == null || heatId === '') {
                    this._refresh();
                    return;
                }

                var that = this;
                this.eafProcess.fetch({
                    params: {
                        id:     (heatId === -1 || heatId === '-1') ? -1   : null,
                        heatId: (heatId === -1 || heatId === '-1') ? null : heatId,
                        timezoneCode: app.models.user.get('timezoneCode'),
                    },
                    success: function () { that._refresh(); },
                    error:   function () { that._refresh(); },
                });
            },

            eafProcess_change_heatName: function () {
                try { this.model.set('heatSearch', this.eafProcess.get('heatName') || ''); }
                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
            },

            getSearchControlSource: function (query, process) {
                var that = this,
                    opt = { params: {} };

                if (query) opt.params.search = query;

                EafProcess.Collections.EafProcesses.fetch(_.extend(opt, {
                    success: function (records) {
                        try {
                            that.searchItems = {};
                            var items = [];
                            if (records) {
                                _.each(records, function (obj) {
                                    var legend = obj.heatName;
                                    that.searchItems[legend] = obj;
                                    items.push(legend);
                                });
                            }
                            process(items);
                        } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                    },
                }));
            },

            selectItemFromSearchComboItem: function (value) {
                var item = this.searchItems[value];
                if (item) {
                    this.model.set({ heatId: item.heatId, heatSearch: item.heatName });
                }
                return item;
            },

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

            getPreviousItemBtn_click: function () { this.getNextProcess(false); },
            getNextItemBtn_click:     function () { this.getNextProcess(true); },
            goToCurrentBtn_click:     function () { this.model.set({ heatId: -1 }); },

            clearHeatBtn_click: function () {
                this.model.set({ heatId: null, heatSearch: '' });
            },

            heatSearch_keypress: function (e) {
                var keyCode = e.which || e.keyCode;
                if (keyCode !== 13) return;

                try {
                    var search = this.model.get('heatSearch');
                    if (!search) {
                        this.model.set({ heatId: null });
                        return;
                    }
                    var item = this.selectItemFromSearchComboItem(search);
                    if (!item) {
                        item = _.findWhere(this.searchItems, { heatName: search });
                        if (item) this.model.set({ heatId: item.heatId, heatSearch: item.heatName });
                        else app.views.topMessages.showMessage(app.translate([this, app], 'no_match'), { stay: 5 * 1000 });
                    }
                } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
            },

            refreshBtn_click: function () {
                try {
                    var p = this.model.toJSON();
                    var routeParams = {
                        start:       new moment(p.start, 'YYYY-MM-DD').format('YYYYMMDD'),
                        end:         new moment(p.end,   'YYYY-MM-DD').format('YYYYMMDD'),
                        heatId:      (p.heatId == null || p.heatId === '') ? '-' : p.heatId,
                        onlyMissing: p.onlyMissing ? 'true' : 'false',
                    };
                    app.router.navigate(
                        app.router.resolveURL(app.router.currentModule, routeParams, false),
                        { trigger: false }
                    );

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

            // -------------------------------------------------------------
            // Excel — native AG Grid export (uses agGridModule.exportToExcel)
            // -------------------------------------------------------------
            exportToExcel: function () {
                try {
                    if (this.agGridModule && this.agGridModule.exportToExcel) {
                        this.agGridModule.exportToExcel(false);
                    }
                } catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
            },

            // -------------------------------------------------------------
            // Auto-refresh — 1-second tick decrements the countdown; when
            // it reaches 0 the data refresh fires and the counter resets.
            // Same pattern as pages/mes/power-curtailment.
            // -------------------------------------------------------------
            startAutoRefreshTick: function () {
                var that = this;
                this.stopAutoRefreshTick();
                this.autoRefresh.remaining = AUTO_REFRESH_INTERVAL_SECONDS;
                this.model.set('countdown', AUTO_REFRESH_INTERVAL_SECONDS);

                this.autoRefresh.tickId = setInterval(function () {
                    if (!that.model.get('autoRefreshEnabled')) return;
                    if (that.model.get('isLoading')) return;

                    that.autoRefresh.remaining -= 1;
                    if (that.autoRefresh.remaining <= 0) {
                        that.autoRefresh.remaining = AUTO_REFRESH_INTERVAL_SECONDS;
                        that.model.set('countdown', AUTO_REFRESH_INTERVAL_SECONDS);
                        that._refresh();
                    } else {
                        that.model.set('countdown', that.autoRefresh.remaining);
                    }
                }, 1000);
            },
            stopAutoRefreshTick: function () {
                if (this.autoRefresh && this.autoRefresh.tickId != null) {
                    clearInterval(this.autoRefresh.tickId);
                    this.autoRefresh.tickId = null;
                }
            },
            autoRefreshToggle_click: function () {
                var enabled = !this.model.get('autoRefreshEnabled');
                this.model.set('autoRefreshEnabled', enabled);
                try { localStorage.setItem(AUTO_REFRESH_STORAGE_KEY, String(enabled)); } catch (e) {}

                // Reset countdown so the next interval is full whether the
                // user is enabling or disabling.
                this.autoRefresh.remaining = AUTO_REFRESH_INTERVAL_SECONDS;
                this.model.set('countdown', AUTO_REFRESH_INTERVAL_SECONDS);
            },

            // -------------------------------------------------------------
            // View lifecycle
            // -------------------------------------------------------------
            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;
                this.stopAutoRefreshTick();
                if (this.agGridModule && this.agGridModule.destroy) this.agGridModule.destroy();
                this.closeSubviews();
                this.remove();
                this.unbind();
            },
            closeSubviews: function () { _.each(this.subviews, function (s) { s.close(); }); },
            show: function () {
                this.options.state = app.view_states.shown;
                this.showSubviews();
                this.bindEvents();
                this.$el.show();
                this.startAutoRefreshTick();
            },
            showSubviews: function () { _.each(this.subviews, function (s) { s.show(); }); },
            hide: function () {
                this.options.state = app.view_states.hidden;
                this.hideSubviews();
                this.stopAutoRefreshTick();
                this.$el.hide();
                this.unbind();
                this.stopListening();
            },
            hideSubviews: function () { _.each(this.subviews, function (s) { s.hide(); }); },
            preRender: function () { app.models.subnavbar.set('subnavbar', false); },
            reRender: function (viewParams) {
                try { this.refresh(viewParams); } catch (Error) { }
            },
        });

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