(function () {
    if (typeof Vue === 'undefined') return;
    var el = document.getElementById('allMappingsApp');
    if (!el) return;

    var PLATFORM_ROUTES = {
        sitecore: '/Sitecore',
        sharepoint: '/SharePoint',
        umbraco: '/Umbraco',
        wordpress: '/WordPress',
        sitefinity: '/Sitefinity',
        sitefinitysource: '/SitefinitySource',
        custom: '/Custom'
    };

    function pick(obj, camel, pascal) {
        if (!obj) return undefined;
        if (obj[camel] !== undefined) return obj[camel];
        return obj[pascal];
    }

    function normalizeMapping(row) {
        return {
            id: pick(row, 'id', 'Id'),
            name: pick(row, 'name', 'Name') || '',
            description: pick(row, 'description', 'Description') || '',
            connectionId: pick(row, 'connectionId', 'ConnectionId'),
            nodeId: pick(row, 'nodeId', 'NodeId') || '',
            importMode: pick(row, 'importMode', 'ImportMode'),
            childrenSelection: pick(row, 'childrenSelection', 'ChildrenSelection') || 'Immediate',
            culture: pick(row, 'culture', 'Culture'),
            platformType: pick(row, 'platformType', 'PlatformType'),
            sourcePlatformType: pick(row, 'sourcePlatformType', 'SourcePlatformType'),
            connectionName: pick(row, 'connectionName', 'ConnectionName'),
            typeBindingCount: pick(row, 'typeBindingCount', 'TypeBindingCount') || 0
        };
    }

    new Vue({
        el: el,
        data: function () {
            return {
                mappings: [],
                loading: false,
                loadError: null,
                filterPlatform: '',
                filterConnectionId: '',
                filterText: '',
                globalRunningImports: [],
                importMappingStatusById: {},
                importLogVisible: false,
                importLogMapping: null,
                importLogRows: [],
                importLogLoading: false,
                _longRunningUnsub: null
            };
        },
        computed: {
            platformOptions: function () {
                var set = {};
                this.mappings.forEach(function (m) {
                    var p = m.sourcePlatformType || m.platformType;
                    if (p) set[p] = true;
                });
                return Object.keys(set).sort();
            },
            connectionOptions: function () {
                var map = {};
                this.mappings.forEach(function (m) {
                    if (m.connectionId == null) return;
                    if (!map[m.connectionId]) {
                        map[m.connectionId] = {
                            id: m.connectionId,
                            name: m.connectionName || ('Connection #' + m.connectionId),
                            platform: m.sourcePlatformType || m.platformType || ''
                        };
                    }
                });
                return Object.values(map).sort(function (a, b) {
                    return (a.name || '').localeCompare(b.name || '');
                });
            },
            filteredMappings: function () {
                var self = this;
                var q = (self.filterText || '').trim().toLowerCase();
                return self.mappings.filter(function (m) {
                    if (self.filterPlatform && (m.sourcePlatformType || m.platformType) !== self.filterPlatform) return false;
                    if (self.filterConnectionId && String(m.connectionId) !== String(self.filterConnectionId)) return false;
                    if (!q) return true;
                    var hay = [
                        m.name,
                        m.description,
                        m.nodeId,
                        m.connectionName,
                        m.sourcePlatformType,
                        m.platformType
                    ].join(' ').toLowerCase();
                    return hay.indexOf(q) !== -1;
                });
            },
            mappingIdsForOpsPoll: function () {
                return this.mappings.map(function (m) { return m.id; }).filter(function (id) { return id != null; });
            }
        },
        mounted: function () {
            this.loadMappings();
            this.startLongRunningPolling();
        },
        beforeDestroy: function () {
            this.stopLongRunningPolling();
        },
        methods: {
            loadMappings: async function () {
                this.loading = true;
                this.loadError = null;
                try {
                    var res = await fetch('/api/SitefinityConnectivity/GetAllMappings');
                    if (!res.ok) throw new Error(await res.text() || res.statusText);
                    var json = await res.json();
                    var list = (json && json.result) || [];
                    this.mappings = list.map(normalizeMapping);
                    if (typeof LongRunningOps !== 'undefined') {
                        await LongRunningOps.forceRefresh(function () { return this.mappingIdsForOpsPoll; }.bind(this));
                        this.applyLongRunningSnapshot(LongRunningOps.getSnapshot());
                    }
                } catch (e) {
                    console.error('GetAllMappings', e);
                    this.loadError = (e && e.message) ? e.message : 'Could not load mappings.';
                    this.mappings = [];
                } finally {
                    this.loading = false;
                }
            },
            importModeLabel: function (mapping) {
                var mode = (mapping.importMode || '').toString();
                if (mode.toLowerCase() === 'templateplan') {
                    var n = mapping.typeBindingCount || 0;
                    return 'Template plan' + (n ? ' (' + n + ' types)' : '');
                }
                return 'Classic';
            },
            platformRoute: function (platformType) {
                var key = (platformType || '').toString().toLowerCase().replace(/\s+/g, '');
                return PLATFORM_ROUTES[key] || null;
            },
            openInSourceHref: function (mapping) {
                var platform = mapping.sourcePlatformType || mapping.platformType;
                var route = this.platformRoute(platform);
                if (!route || !mapping.nodeId) return null;
                var qs = new URLSearchParams();
                qs.set('id', mapping.nodeId);
                qs.set('tab', 'imports');
                return route + '?' + qs.toString();
            },
            applyLongRunningSnapshot: function (snap) {
                if (!snap) return;
                this.globalRunningImports = snap.runningImports || [];
                var statuses = snap.mappingStatuses || {};
                var self = this;
                Object.keys(statuses).forEach(function (k) {
                    self.$set(self.importMappingStatusById, parseInt(k, 10), statuses[k]);
                });
            },
            startLongRunningPolling: function () {
                if (typeof LongRunningOps === 'undefined') return;
                var self = this;
                this._longRunningUnsub = LongRunningOps.subscribe(function (snap) {
                    self.applyLongRunningSnapshot(snap);
                }, function () { return self.mappingIdsForOpsPoll; });
            },
            stopLongRunningPolling: function () {
                if (this._longRunningUnsub) {
                    this._longRunningUnsub();
                    this._longRunningUnsub = null;
                }
            },
            isMappingImportRunning: function (mapping) {
                if (!mapping) return false;
                var mid = mapping.id;
                var g = (this.globalRunningImports || []).find(function (r) {
                    return (r.mappingId != null ? r.mappingId : r.MappingId) === mid;
                });
                if (g) return true;
                var s = this.importMappingStatusById[mid];
                if (!s) return false;
                return (s.isRunning !== undefined ? s.isRunning : s.IsRunning) === true;
            },
            isRunImportDisabled: function () {
                return this.globalRunningImports && this.globalRunningImports.length > 0;
            },
            runImportDisabledTitle: function (mapping) {
                if (!this.globalRunningImports || !this.globalRunningImports.length) return '';
                if (this.isMappingImportRunning(mapping)) return 'An import is already running for this mapping';
                return 'Another import is in progress.';
            },
            mappingRunningRunId: function (mapping) {
                if (!mapping) return null;
                var mid = mapping.id;
                var g = (this.globalRunningImports || []).find(function (r) {
                    return (r.mappingId != null ? r.mappingId : r.MappingId) === mid;
                });
                if (g) {
                    var id = g.id != null ? g.id : g.Id;
                    return id != null ? id : null;
                }
                var s = this.importMappingStatusById[mid];
                if (!s) return null;
                return s.runningRunId != null ? s.runningRunId : s.RunningRunId;
            },
            globalRunningRunId: function () {
                var gr0 = this.globalRunningImports && this.globalRunningImports[0];
                if (!gr0) return null;
                var id = gr0.id != null ? gr0.id : gr0.Id;
                return id != null ? id : null;
            },
            mappingStatusLine: function (mapping) {
                if (!mapping) return '';
                var s = this.importMappingStatusById[mapping.id];
                if (!s) return '';
                var lr = s.lastRun != null ? s.lastRun : s.LastRun;
                if (!lr) return '';
                if (this.isMappingImportRunning(mapping)) {
                    var proc = lr.processedItems != null ? lr.processedItems : lr.ProcessedItems;
                    var tot = lr.totalItems != null ? lr.totalItems : lr.TotalItems;
                    return 'Import running…' + (proc != null && tot != null ? ' ' + proc + ' / ' + tot : '');
                }
                var st = lr.status != null ? lr.status : lr.Status;
                return st ? 'Last run: ' + st : '';
            },
            runImport: async function (mapping) {
                if (this.isRunImportDisabled(mapping)) {
                    Helpers.showNotification(this.runImportDisabledTitle(mapping) || 'There is already a running import.', 'warning');
                    return;
                }
                var payload = {
                    connectionId: mapping.connectionId,
                    sourceItemId: mapping.nodeId,
                    mappingId: mapping.id,
                    name: mapping.name
                };
                try {
                    var res = await fetch('/api/Import/StartImport', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify(payload)
                    });
                    if (res.status === 400) {
                        var errMsg = await res.text();
                        Helpers.showNotification('Error starting import: ' + errMsg, 'error');
                    } else if (!res.ok) {
                        Helpers.showNotification('Error starting import', 'error');
                    } else {
                        Helpers.showNotification('Import started successfully', 'success');
                        if (typeof LongRunningOps !== 'undefined') {
                            await LongRunningOps.forceRefresh(function () { return this.mappingIdsForOpsPoll; }.bind(this));
                            this.applyLongRunningSnapshot(LongRunningOps.getSnapshot());
                        }
                    }
                } catch (e) {
                    console.error('StartImport', e);
                    Helpers.showNotification('Error starting import', 'error');
                }
            },
            forceStopImport: async function (mapping) {
                var rid = this.mappingRunningRunId(mapping);
                if (rid == null) {
                    Helpers.showNotification('No active run id for this mapping.', 'warning');
                    return;
                }
                await this.forceStopImportByRunId(rid);
            },
            forceStopImportByRunId: async function (runId) {
                if (runId == null) return;
                if (!confirm('Force stop this import?')) return;
                try {
                    var r = await fetch('/api/Import/ForceStopImport?runId=' + encodeURIComponent(runId), { method: 'POST' });
                    if (!r.ok) throw new Error(await r.text() || r.statusText);
                    Helpers.showNotification('Stop requested.', 'success');
                    if (typeof LongRunningOps !== 'undefined') {
                        await LongRunningOps.forceRefresh(function () { return this.mappingIdsForOpsPoll; }.bind(this));
                        this.applyLongRunningSnapshot(LongRunningOps.getSnapshot());
                    }
                } catch (e) {
                    console.error('ForceStopImport', e);
                    Helpers.showNotification('Could not stop import.', 'error');
                }
            },
            deleteMapping: async function (mapping) {
                if (!confirm('Are you sure you want to delete this mapping?')) return;
                try {
                    await fetch('/api/SitefinityConnectivity/DeleteMapping?mappingId=' + encodeURIComponent(mapping.id));
                    Helpers.showNotification('Mapping deleted successfully', 'success');
                    await this.loadMappings();
                } catch (e) {
                    console.error('DeleteMapping', e);
                    Helpers.showNotification('Error deleting mapping', 'error');
                }
            },
            clearMemory: async function (mapping) {
                if (!confirm('This operation is intended if you have imported items and then deleted them.\nAre you sure you want to proceed?')) return;
                try {
                    var res = await fetch('/api/Import/ClearMemoryMappings?mappingId=' + encodeURIComponent(mapping.id));
                    var jsonRes = await res.json();
                    if (jsonRes && jsonRes.NumberOfItemsRemoved && jsonRes.Succeess) {
                        Helpers.showNotification('Successfully removed ' + jsonRes.NumberOfItemsRemoved + ' items from memory', 'success');
                    }
                } catch (e) {
                    console.error('ClearMemoryMappings', e);
                    Helpers.showNotification('Error clearing memory', 'error');
                }
            },
            openImportLog: function (mapping) {
                this.importLogMapping = mapping;
                this.importLogVisible = true;
                this.loadImportLog(mapping);
            },
            closeImportLog: function () {
                this.importLogVisible = false;
                this.importLogMapping = null;
                this.importLogRows = [];
            },
            loadImportLog: async function (mapping) {
                if (!mapping || !mapping.id) return;
                this.importLogLoading = true;
                try {
                    var res = await fetch('/api/Import/GetImportHistory?mappingId=' + encodeURIComponent(mapping.id) + '&count=20');
                    if (!res.ok) throw new Error(await res.text() || res.statusText);
                    this.importLogRows = await res.json();
                } catch (e) {
                    console.error('GetImportHistory', e);
                    Helpers.showNotification('Could not load import history.', 'error');
                    this.importLogRows = [];
                } finally {
                    this.importLogLoading = false;
                }
            },
            formatDate: function (val) {
                if (val == null || val === '') return '—';
                var d = new Date(val);
                if (isNaN(d.getTime())) return String(val);
                return d.toLocaleString();
            },
            importLogProgress: function (row) {
                var p = row.processedItems != null ? row.processedItems : row.ProcessedItems;
                var t = row.totalItems != null ? row.totalItems : row.TotalItems;
                if (p == null && t == null) return '—';
                return (p != null ? p : '—') + ' / ' + (t != null ? t : '—');
            },
            importLogOutcome: function (row) {
                var st = (row.status != null ? row.status : row.Status || '').toString();
                var err = row.errorCount != null ? row.errorCount : row.ErrorCount;
                var errNum = err != null ? Number(err) : 0;
                if (st === 'Failed') return 'Failed';
                if (st === 'CompletedWithErrors' || errNum > 0) return 'With errors';
                if (st === 'Running') return 'Running';
                if (st === 'Completed' || st === 'Finished') return 'Success';
                return st !== '' ? st : '—';
            }
        }
    });
})();
