// Initialize the main Vue instance for Sitecore (matches design.html structure)
(function() {
    if (typeof Vue === 'undefined') return;
    var el = document.getElementById('sitecoreApp');
    if (!el) return;

    // Mock data from design.html (will connect to real data later)
    function generateId() {
        return '{' + 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random() * 16 | 0;
            return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
        }).toUpperCase() + '}';
    }
    function makeNode(name, type, template, children, path) {
        return {
            id: generateId(),
            name: name, type: type, template: template,
            path: path || '/sitecore/content/' + name,
            children: children || [],
            expanded: false,
            excluded: false,
            notes: '',
            visible: true,
            language: 'en',
            created: '2023-' + String(Math.floor(Math.random()*12+1)).padStart(2,'0') + '-15',
            updated: '2025-' + String(Math.floor(Math.random()*12+1)).padStart(2,'0') + '-20'
        };
    }
    var TREE_DATA = [
        makeNode('Content', 'folder', 'Folder', [
            makeNode('Corporate Site', 'site', 'Website', [
                makeNode('Home', 'page', 'Page', [
                    makeNode('Hero Banner', 'component', 'Hero Banner', [], '/sitecore/content/Corporate Site/Home/Hero Banner'),
                    makeNode('Featured Products', 'component', 'Product Grid', [], '/sitecore/content/Corporate Site/Home/Featured Products'),
                    makeNode('Testimonials', 'component', 'Testimonial Carousel', [], '/sitecore/content/Corporate Site/Home/Testimonials'),
                ], '/sitecore/content/Corporate Site/Home'),
                makeNode('About Us', 'page', 'Page', [
                    makeNode('Team Section', 'component', 'Team Grid', [], '/sitecore/content/Corporate Site/About Us/Team Section'),
                    makeNode('History Timeline', 'component', 'Timeline', [], '/sitecore/content/Corporate Site/About Us/History Timeline'),
                ], '/sitecore/content/Corporate Site/About Us'),
                makeNode('Products', 'page', 'Product Landing', [
                    makeNode('Product A', 'page', 'Product Detail', [], '/sitecore/content/Corporate Site/Products/Product A'),
                    makeNode('Product B', 'page', 'Product Detail', [], '/sitecore/content/Corporate Site/Products/Product B'),
                    makeNode('Product C', 'page', 'Product Detail', [], '/sitecore/content/Corporate Site/Products/Product C'),
                ], '/sitecore/content/Corporate Site/Products'),
                makeNode('Blog', 'page', 'Blog Landing', [
                    makeNode('Getting Started with XM Cloud', 'page', 'Blog Post', [], '/sitecore/content/Corporate Site/Blog/Getting Started'),
                    makeNode('Migration Best Practices', 'page', 'Blog Post', [], '/sitecore/content/Corporate Site/Blog/Migration Best Practices'),
                ], '/sitecore/content/Corporate Site/Blog'),
                makeNode('Contact', 'page', 'Page', [
                    makeNode('Contact Form', 'component', 'Form', [], '/sitecore/content/Corporate Site/Contact/Form'),
                    makeNode('Office Locations', 'component', 'Map Widget', [], '/sitecore/content/Corporate Site/Contact/Locations'),
                ], '/sitecore/content/Corporate Site/Contact'),
            ], '/sitecore/content/Corporate Site'),
            makeNode('Partner Portal', 'site', 'Website', [
                makeNode('Dashboard', 'page', 'Portal Dashboard', [], '/sitecore/content/Partner Portal/Dashboard'),
                makeNode('Resources', 'page', 'Resource Landing', [
                    makeNode('Documentation', 'page', 'Resource Page', [], '/sitecore/content/Partner Portal/Resources/Docs'),
                    makeNode('Downloads', 'page', 'Resource Page', [], '/sitecore/content/Partner Portal/Resources/Downloads'),
                ], '/sitecore/content/Partner Portal/Resources'),
                makeNode('Support', 'page', 'Page', [], '/sitecore/content/Partner Portal/Support'),
            ], '/sitecore/content/Partner Portal'),
            makeNode('Intranet', 'site', 'Website', [
                makeNode('Home', 'page', 'Page', [], '/sitecore/content/Intranet/Home'),
                makeNode('HR Policies', 'page', 'Document List', [
                    makeNode('Leave Policy', 'data', 'Policy Document', [], '/sitecore/content/Intranet/HR/Leave'),
                    makeNode('Travel Policy', 'data', 'Policy Document', [], '/sitecore/content/Intranet/HR/Travel'),
                ], '/sitecore/content/Intranet/HR Policies'),
                makeNode('News', 'page', 'News Landing', [
                    makeNode('Company Update Q4', 'page', 'News Article', [], '/sitecore/content/Intranet/News/Q4'),
                    makeNode('Holiday Schedule', 'page', 'News Article', [], '/sitecore/content/Intranet/News/Holidays'),
                ], '/sitecore/content/Intranet/News'),
            ], '/sitecore/content/Intranet'),
        ], '/sitecore/content'),
        makeNode('Media Library', 'folder', 'Media Folder', [
            makeNode('Images', 'folder', 'Media Folder', [
                makeNode('Logos', 'media', 'Image', [], '/sitecore/media/Images/Logos'),
                makeNode('Banners', 'media', 'Image', [], '/sitecore/media/Images/Banners'),
                makeNode('Product Photos', 'media', 'Image', [], '/sitecore/media/Images/Products'),
            ], '/sitecore/media/Images'),
            makeNode('Documents', 'folder', 'Media Folder', [
                makeNode('Whitepapers', 'media', 'PDF', [], '/sitecore/media/Documents/Whitepapers'),
                makeNode('Case Studies', 'media', 'PDF', [], '/sitecore/media/Documents/Case Studies'),
            ], '/sitecore/media/Documents'),
            makeNode('Videos', 'folder', 'Media Folder', [
                makeNode('Product Demos', 'media', 'Video', [], '/sitecore/media/Videos/Demos'),
                makeNode('Tutorials', 'media', 'Video', [], '/sitecore/media/Videos/Tutorials'),
            ], '/sitecore/media/Videos'),
        ], '/sitecore/media'),
        makeNode('Templates', 'folder', 'Template Folder', [
            makeNode('Page Templates', 'folder', 'Template Folder', [
                makeNode('Base Page', 'data', 'Template', [], '/sitecore/templates/Page/Base'),
                makeNode('Landing Page', 'data', 'Template', [], '/sitecore/templates/Page/Landing'),
                makeNode('Article Page', 'data', 'Template', [], '/sitecore/templates/Page/Article'),
            ], '/sitecore/templates/Page Templates'),
            makeNode('Component Templates', 'folder', 'Template Folder', [
                makeNode('Hero', 'data', 'Template', [], '/sitecore/templates/Components/Hero'),
                makeNode('Card Grid', 'data', 'Template', [], '/sitecore/templates/Components/CardGrid'),
            ], '/sitecore/templates/Component Templates'),
        ], '/sitecore/templates'),
        makeNode('System', 'folder', 'Folder', [
            makeNode('Languages', 'folder', 'Folder', [
                makeNode('en', 'data', 'Language', [], '/sitecore/system/Languages/en'),
                makeNode('de-DE', 'data', 'Language', [], '/sitecore/system/Languages/de-DE'),
            ], '/sitecore/system/Languages'),
            makeNode('Workflows', 'folder', 'Folder', [
                makeNode('Sample Workflow', 'data', 'Workflow', [], '/sitecore/system/Workflows/Sample'),
            ], '/sitecore/system/Workflows'),
        ], '/sitecore/system'),
    ];

    var MOCK_SITES = [
        { name: 'Corporate Site', host: 'www.corporate.com', startPath: '/sitecore/content/Corporate Site', language: 'en', database: 'master' },
        { name: 'Partner Portal', host: 'partners.corporate.com', startPath: '/sitecore/content/Partner Portal', language: 'en', database: 'master' },
        { name: 'Intranet', host: 'intranet.corporate.local', startPath: '/sitecore/content/Intranet', language: 'en', database: 'master' },
    ];
    var MOCK_CONTENT_TYPES = [
        { name: 'Page', path: '/sitecore/templates/Page', fields: 12, itemCount: 24, custom: false },
        { name: 'Blog Post', path: '/sitecore/templates/Blog Post', fields: 18, itemCount: 4, custom: true },
        { name: 'Product Detail', path: '/sitecore/templates/Product Detail', fields: 22, itemCount: 3, custom: true },
        { name: 'Hero Banner', path: '/sitecore/templates/Hero Banner', fields: 6, itemCount: 1, custom: true },
        { name: 'Folder', path: '/sitecore/templates/System/Folder', fields: 1, itemCount: 12, custom: false },
        { name: 'Website', path: '/sitecore/templates/Website', fields: 15, itemCount: 3, custom: false },
    ];
    var MOCK_RENDERINGS = [
        { name: 'Hero Banner', type: 'View', path: '~/Views/Components/HeroBanner.cshtml', usageCount: 3, datasource: 'Hero Banner' },
        { name: 'Product Grid', type: 'Controller', path: 'ProductGridController', usageCount: 2, datasource: 'Product Grid' },
        { name: 'Navigation', type: 'Controller', path: 'NavigationController', usageCount: 8, datasource: null },
        { name: 'Footer', type: 'View', path: '~/Views/Shared/Footer.cshtml', usageCount: 3, datasource: null },
        { name: 'Breadcrumb', type: 'View', path: '~/Views/Components/Breadcrumb.cshtml', usageCount: 15, datasource: null },
        { name: 'Rich Text Block', type: 'View', path: '~/Views/Components/RichText.cshtml', usageCount: 32, datasource: 'Rich Text' },
    ];

    new Vue({
        el: el,
        data: {
            activeTab: 'dashboard',
            selectedNode: null,
            selectedNodeId: null,
            selectedConnection: null,
            tree: [],
            treeItems: [],
            platformType: 'Sitecore',
            searchFilter: '',
            searchResults: null,
            searchLoading: false,
            deeplinkId: null,
            initialNodeData: {},
            initialExpanded: {},
            excludedIds: [],
            sites: [],
            contentTypes: [],
            renderings: [],
            itemCountsByLanguage: [],
            instanceTotalItems: 0,
            instancePageCount: 0,
            instanceMediaCount: 0,
            instanceDataCount: 0,
            instanceDetachedCount: 0,
            instanceOverviewLoaded: false,
            exportExcelLoading: false,
            toast: null,
            showReportModal: false,
            importMappingNodeIds: [],
            /** Set true when user picks a connection — success toast once tree loads */
            awaitingConnectToast: false,
            /** Sidebar banner for repository probe (error / empty warning) */
            repositoryAlert: null,
            refreshAllDataBusy: false
        },
        mounted: function() {
            var self = this;
            this.registerRefreshShortcut();
            var params = new URLSearchParams(window.location.search);
            var idParam = params.get('id') || params.get('Id');
            if (idParam) {
                self.deeplinkId = idParam.replace(/[{}]/g, '');
            }
            var lastConnection = localStorage.getItem("lastSitecoreConnection");
            if (lastConnection) {
                try {
                    self.selectedConnection = JSON.parse(lastConnection);
                    self.refreshExcluded();
                    if (self.deeplinkId) {
                        self.fetchDeeplinkItem();
                    } else {
                        self.fetchRootItems();
                    }
                    self.fetchInstanceOverview();
                    self.fetchImportMappingNodeIds();
                } catch (e) {
                    console.error("Failed to parse last connection", e);
                }
            }
            self._onExcludedUpdated = function() {
                self.refreshExcluded();
                self.fetchInstanceOverview();
            };
            self.$root.$on('excluded-updated', self._onExcludedUpdated);
            self.$root.$on('show-toast', function(p) { self.showToast(p.icon, p.text); });
        },
        watch: {
            searchFilter: function(val) {
                if (!val || !val.trim()) this.searchResults = null;
            },
            activeTab: function(tab) {
                if (tab === 'imports') this.fetchImportMappingNodeIds();
            }
        },
        beforeDestroy: function() {
            this.unregisterRefreshShortcut();
            if (this._onExcludedUpdated) this.$root.$off('excluded-updated', this._onExcludedUpdated);
            this.$root.$off('show-toast');
        },
        computed: {
            filteredTree: function() {
                if (!this.searchFilter.trim()) return this.tree;
                var q = this.searchFilter.toLowerCase();
                this.filterNodes(this.tree, q);
                return this.tree;
            },
            totalItems: function() {
                if (this.instanceOverviewLoaded) {
                    return this.instanceTotalItems;
                }
                return (this.treeItems && this.treeItems.length) || 0;
            },
            excludedCount: function() {
                return this.excludedIds ? this.excludedIds.length : 0;
            },
            notesCount: function() {
                return this.countNotes(this.treeItems || this.tree);
            },
            pageCount: function() {
                if (this.instanceOverviewLoaded) return this.instancePageCount;
                return this.countByType(this.treeItems || this.tree, 'page');
            },
            mediaCount: function() {
                if (this.instanceOverviewLoaded) return this.instanceMediaCount;
                return this.countByType(this.treeItems || this.tree, 'media');
            },
            dataCount: function() {
                if (this.instanceOverviewLoaded) return this.instanceDataCount;
                return this.countByType(this.treeItems || this.tree, 'data');
            },
            detachedCount: function() {
                return this.instanceOverviewLoaded ? (this.instanceDetachedCount || 0) : 0;
            },
            dashboardLoading: function() {
                return this.selectedConnection && !this.instanceOverviewLoaded;
            }
        },
        methods: {
            fetchRootItems: function() {
                var self = this;
                if (!this.selectedConnection) return;
                this.deeplinkId = null;
                this.initialNodeData = {};
                this.initialExpanded = {};
                var connId = this.selectedConnection.id || this.selectedConnection.Id;
                var url = '/api/ContentTree/GetRootItems?platformType=' + encodeURIComponent(this.platformType) + '&connectionId=' + encodeURIComponent(connId);
                function parseErr(body) {
                    if (!body || typeof body !== 'object') return { brief: 'Unexpected response', details: '' };
                    var m = body.message || body.Message || body.error || '';
                    var d = body.details || body.Details || '';
                    return { brief: m || 'Request failed', details: d };
                }
                fetch(url)
                    .then(function(r) {
                        return r.text().then(function(t) {
                            var body = null;
                            try { body = t ? JSON.parse(t) : null; } catch (e) { body = null; }
                            return { ok: r.ok, status: r.status, body: body, rawText: t || '' };
                        });
                    })
                    .then(function(res) {
                        self.repositoryAlert = null;
                        var emptyWarning = {
                            kind: 'warning',
                            title: 'Empty or unrecognized datasource',
                            brief: 'Connection succeeded, but the target datasource appears empty, uses a different schema, or needs additional setup.',
                            details: ''
                        };
                        if (!res.ok) {
                            var p = parseErr(res.body);
                            if (!res.body && res.rawText) {
                                self.repositoryAlert = {
                                    kind: 'error',
                                    title: 'Connection failed',
                                    brief: 'The connection to the remote server failed: HTTP ' + res.status,
                                    details: res.rawText.length > 8000 ? res.rawText.slice(0, 8000) + '\n…' : res.rawText
                                };
                            } else {
                                self.repositoryAlert = {
                                    kind: 'error',
                                    title: 'Connection failed',
                                    brief: 'The connection to the remote server failed: ' + p.brief,
                                    details: p.details || ''
                                };
                            }
                            self.treeItems = [];
                            self.awaitingConnectToast = false;
                            return;
                        }
                        var data = res.body;
                        if (data && typeof data === 'object' && !Array.isArray(data) && (data.success === false || data.Success === false)) {
                            var p2 = parseErr(data);
                            self.repositoryAlert = {
                                kind: 'error',
                                title: 'Connection failed',
                                brief: 'The connection to the remote server failed: ' + p2.brief,
                                details: p2.details || ''
                            };
                            self.treeItems = [];
                            self.awaitingConnectToast = false;
                            return;
                        }
                        var list = Array.isArray(data) ? data : [];
                        self.treeItems = list;
                        if (list.length === 0)
                            self.repositoryAlert = emptyWarning;
                        else if (self.awaitingConnectToast) {
                            self.showToast('bi bi-check-circle-fill', 'Connected successfully');
                        }
                        self.awaitingConnectToast = false;
                    })
                    .catch(function(err) {
                        console.error('Error fetching root items:', err);
                        self.repositoryAlert = {
                            kind: 'error',
                            title: 'Connection failed',
                            brief: 'The connection to the remote server failed: ' + (err.message || 'Network error'),
                            details: err.stack || String(err)
                        };
                        self.treeItems = [];
                        self.awaitingConnectToast = false;
                    });
            },
            fetchDeeplinkItem: function() {
                var self = this;
                if (!this.selectedConnection || !this.deeplinkId) return;
                var connId = this.selectedConnection.id || this.selectedConnection.Id;
                var url = '/api/ContentTree/GetItemWithPath?id=' + encodeURIComponent(this.deeplinkId) + '&platformType=' + encodeURIComponent(this.platformType) + '&connectionId=' + encodeURIComponent(connId);
                fetch(url)
                    .then(function(r) { return r.json(); })
                    .then(function(data) {
                        if (!data || !data.success || !data.item) {
                            self.treeItems = [];
                            self.initialNodeData = {};
                            self.initialExpanded = {};
                            if (data && data.message) self.showToast('bi bi-exclamation-circle', data.message);
                            return;
                        }
                        var path = data.path || [];
                        var item = data.item;
                        var allNodes = path.concat([item]);
                        if (allNodes.length === 0) return;
                        self.treeItems = [allNodes[0]];
                        var nodeData = {};
                        var expanded = {};
                        for (var i = 0; i < allNodes.length - 1; i++) {
                            nodeData[allNodes[i].id] = [allNodes[i + 1]];
                            expanded[allNodes[i].id] = true;
                        }
                        self.initialNodeData = nodeData;
                        self.initialExpanded = expanded;
                        self.$nextTick(function() {
                            self.selectNode(item);
                        });
                    })
                    .catch(function(err) {
                        console.error('Error fetching deeplink item:', err);
                        self.treeItems = [];
                        self.initialNodeData = {};
                        self.initialExpanded = {};
                    });
            },
            runSearch: function() {
                if (!this.searchFilter || !this.searchFilter.trim()) {
                    this.searchResults = null;
                    return;
                }
                this.fetchSearchResults();
            },
            clearSearch: function() {
                this.searchFilter = '';
                this.searchResults = null;
            },
            fetchSearchResults: function() {
                var self = this;
                if (!this.selectedConnection || !this.searchFilter || !this.searchFilter.trim()) {
                    this.searchResults = null;
                    return;
                }
                this.searchLoading = true;
                var connId = this.selectedConnection.id || this.selectedConnection.Id;
                var url = '/api/ContentTree/SearchTree?q=' + encodeURIComponent(this.searchFilter.trim()) + '&platformType=' + encodeURIComponent(this.platformType) + '&connectionId=' + encodeURIComponent(connId);
                fetch(url)
                    .then(function(r) { return r.json(); })
                    .then(function(data) {
                        self.searchLoading = false;
                        if (data && data.success && data.results) {
                            self.searchResults = data.results;
                        } else {
                            self.searchResults = [];
                        }
                    })
                    .catch(function(err) {
                        console.error('Error searching:', err);
                        self.searchLoading = false;
                        self.searchResults = [];
                    });
            },
            fetchInstanceOverview: function() {
                var self = this;
                if (!this.selectedConnection) return;
                var connId = this.selectedConnection.id || this.selectedConnection.Id;
                var url = '/api/ContentTree/GetInstanceOverview?platformType=' + encodeURIComponent(this.platformType) + '&connectionId=' + encodeURIComponent(connId);
                var excluded = this.excludedIds;
                if (excluded && excluded.length > 0) {
                    var idsParam = (excluded instanceof Set ? [...excluded] : excluded).slice(0, 500).join(',');
                    if (idsParam) url += '&excludedIds=' + encodeURIComponent(idsParam);
                }
                fetch(url)
                    .then(function(r) { return r.json(); })
                    .then(function(data) {
                        if (data && data.success !== false) {
                            self.instanceTotalItems = data.totalItems || 0;
                            self.instancePageCount = data.pageCount || 0;
                            self.instanceMediaCount = data.mediaCount || 0;
                            self.instanceDataCount = data.dataCount || 0;
                            self.instanceDetachedCount = data.detachedCount || 0;
                            self.sites = data.sites || [];
                            self.contentTypes = data.contentTypes || [];
                            self.renderings = data.renderings || [];
                            self.itemCountsByLanguage = data.itemCountsByLanguage || [];
                            self.instanceOverviewLoaded = true;
                        } else {
                            self.instanceTotalItems = 0;
                            self.instancePageCount = 0;
                            self.instanceMediaCount = 0;
                            self.instanceDataCount = 0;
                            self.instanceDetachedCount = 0;
                            self.sites = [];
                            self.contentTypes = [];
                            self.renderings = [];
                            self.itemCountsByLanguage = [];
                            self.instanceOverviewLoaded = false;
                        }
                    })
                    .catch(function(err) {
                        console.error('Error fetching instance overview:', err);
                        self.instanceTotalItems = 0;
                        self.instancePageCount = 0;
                        self.instanceMediaCount = 0;
                        self.instanceDataCount = 0;
                        self.instanceDetachedCount = 0;
                        self.sites = [];
                        self.contentTypes = [];
                        self.renderings = [];
                        self.itemCountsByLanguage = [];
                        self.instanceOverviewLoaded = false;
                    });
            },
            selectNode: function(node) {
                this.selectedNodeId = node.id || node.Id;
                this.selectedNode = node;
                this.activeTab = 'details';
            },
            selectSearchResult: function(r) {
                this.deeplinkId = r.item.id;
                this.searchFilter = '';
                this.searchResults = null;
                this.fetchDeeplinkItem();
            },
            backToFullView: function() {
                this.deeplinkId = null;
                this.initialNodeData = {};
                this.initialExpanded = {};
                this.fetchRootItems();
                this.selectedNode = null;
                this.selectedNodeId = null;
            },
            toggleNode: function(node) {
                node.expanded = !node.expanded;
            },
            filterNodes: function(nodes, query) {
                for (var i = 0; i < (nodes || []).length; i++) {
                    var n = nodes[i];
                    var match = (n.name || '').toLowerCase().indexOf(query) !== -1;
                    var childMatch = false;
                    if (n.children && n.children.length) {
                        this.filterNodes(n.children, query);
                        for (var j = 0; j < n.children.length; j++) {
                            if (n.children[j].visible !== false) { childMatch = true; break; }
                        }
                    }
                    Vue.set(n, 'visible', match || childMatch);
                    if (childMatch && query) n.expanded = true;
                }
            },
            refreshExcluded: function() {
                if (!this.selectedConnection || typeof ExcludedStore === 'undefined') return;
                var connId = this.selectedConnection.id || this.selectedConnection.Id;
                var ids = ExcludedStore.getExcludedIds(connId, this.platformType);
                this.excludedIds = ids instanceof Set ? [...ids] : (Array.isArray(ids) ? ids : []);
            },
            registerRefreshShortcut: function() {
                var self = this;
                this._chameleonRefreshKey = function(e) {
                    if (!self.selectedConnection || self.refreshAllDataBusy) return;
                    var t = e.target;
                    if (t && (t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.isContentEditable)) return;
                    if (e.altKey && e.shiftKey && !e.ctrlKey && !e.metaKey && (e.key === 'r' || e.key === 'R')) {
                        e.preventDefault();
                        self.refreshAllData();
                    }
                };
                window.addEventListener('keydown', this._chameleonRefreshKey);
            },
            unregisterRefreshShortcut: function() {
                if (this._chameleonRefreshKey) {
                    window.removeEventListener('keydown', this._chameleonRefreshKey);
                    this._chameleonRefreshKey = null;
                }
            },
            refreshAllData: async function() {
                if (!this.selectedConnection || this.refreshAllDataBusy) return;
                this.refreshAllDataBusy = true;
                this.instanceOverviewLoaded = false;
                try {
                    var connId = this.selectedConnection.id || this.selectedConnection.Id;
                    if (typeof ChameleonCacheRefresh !== 'undefined')
                        await ChameleonCacheRefresh.invalidateSourceCaches(connId, this.platformType);
                    this.refreshExcluded();
                    this.repositoryAlert = null;
                    this.awaitingConnectToast = false;
                    if (this.deeplinkId) this.fetchDeeplinkItem();
                    else this.fetchRootItems();
                    this.fetchInstanceOverview();
                    this.fetchImportMappingNodeIds();
                    if (typeof Helpers !== 'undefined') Helpers.showNotification('Refreshed from server', 'success');
                } catch (e) {
                    console.error('refreshAllData:', e);
                    if (typeof Helpers !== 'undefined') Helpers.showNotification((e && e.message) ? e.message : 'Could not refresh', 'error');
                } finally {
                    this.refreshAllDataBusy = false;
                }
            },
            ConnectTo: function(connection) {
                Vue.set(this, 'selectedConnection', connection);
                localStorage.setItem("lastSitecoreConnection", JSON.stringify(connection));
                this.refreshExcluded();
                this.repositoryAlert = null;
                this.awaitingConnectToast = true;
                var params = new URLSearchParams(window.location.search);
                var idParam = params.get('id') || params.get('Id');
                if (idParam) this.deeplinkId = idParam.replace(/[{}]/g, '');
                if (this.deeplinkId) {
                    this.awaitingConnectToast = false;
                    this.fetchDeeplinkItem();
                } else {
                    this.fetchRootItems();
                }
                this.fetchInstanceOverview();
                this.fetchImportMappingNodeIds();
            },
            fetchImportMappingNodeIds: function() {
                var self = this;
                if (!this.selectedConnection) {
                    this.importMappingNodeIds = [];
                    return;
                }
                var connId = this.selectedConnection.id || this.selectedConnection.Id;
                fetch('/api/SitefinityConnectivity/GetMappings?connectionId=' + encodeURIComponent(connId))
                    .then(function(r) { return r.json(); })
                    .then(function(data) {
                        var list = (data && data.result) || [];
                        var set = {};
                        for (var i = 0; i < list.length; i++) {
                            var nid = list[i].nodeId;
                            if (nid != null && nid !== '') set[String(nid)] = true;
                        }
                        self.importMappingNodeIds = Object.keys(set);
                    })
                    .catch(function() {
                        self.importMappingNodeIds = [];
                    });
            },
            disconnect: function() {
                this.selectedConnection = null;
                this.tree = [];
                this.treeItems = [];
                this.repositoryAlert = null;
                this.awaitingConnectToast = false;
                this.sites = [];
                this.contentTypes = [];
                this.renderings = [];
                this.instanceTotalItems = 0;
                this.instancePageCount = 0;
                this.instanceMediaCount = 0;
                this.instanceDataCount = 0;
                this.instanceOverviewLoaded = false;
                this.selectedNode = null;
                this.selectedNodeId = null;
                this.searchFilter = '';
                this.searchResults = null;
                this.deeplinkId = null;
                this.initialNodeData = {};
                this.initialExpanded = {};
                this.activeTab = 'dashboard';
                this.importMappingNodeIds = [];
                localStorage.removeItem("lastSitecoreConnection");
            },
            countNodes: function(nodes) {
                if (!nodes || !nodes.length) return 0;
                var c = 0;
                for (var i = 0; i < nodes.length; i++) {
                    c++;
                    if (nodes[i].children && nodes[i].children.length) {
                        c += this.countNodes(nodes[i].children);
                    }
                }
                return c;
            },
            countNotes: function(nodes) {
                if (!nodes || !nodes.length) return 0;
                var c = 0;
                for (var i = 0; i < nodes.length; i++) {
                    if (nodes[i].notes) c++;
                    if (nodes[i].children) c += this.countNotes(nodes[i].children);
                }
                return c;
            },
            countByType: function(nodes, type) {
                if (!nodes || !nodes.length) return 0;
                var c = 0;
                for (var i = 0; i < nodes.length; i++) {
                    if (nodes[i].type === type) c++;
                    if (nodes[i].children) c += this.countByType(nodes[i].children, type);
                }
                return c;
            },
            exportToExcel: function() {
                var self = this;
                if (!this.selectedConnection || this.exportExcelLoading) return;
                this.exportExcelLoading = true;
                var connId = this.selectedConnection.id || this.selectedConnection.Id;
                var excludedIds = this.excludedIds ? (this.excludedIds instanceof Set ? [...this.excludedIds] : this.excludedIds) : [];
                fetch('/api/ContentTree/ExportToExcel', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        connectionId: connId,
                        platformType: this.platformType || 'Sitecore',
                        excludedIds: excludedIds
                    })
                })
                .then(function(r) {
                    if (!r.ok) return r.json().then(function(j) { throw new Error(j.message || 'Export failed'); });
                    var disp = r.headers.get('Content-Disposition');
                    var match = disp && disp.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
                    var filename = (match && match[1]) ? match[1].replace(/['"]/g, '') : 'sitecore-migration-assessment.xlsx';
                    return r.blob().then(function(blob) { return { blob: blob, filename: filename }; });
                })
                .then(function(result) {
                    var url = URL.createObjectURL(result.blob);
                    var a = document.createElement('a');
                    a.href = url;
                    a.download = result.filename;
                    a.click();
                    URL.revokeObjectURL(url);
                    self.showToast('bi bi-file-earmark-check', 'Exported to Excel');
                })
                .catch(function(err) {
                    console.error('Export error:', err);
                    self.showToast('bi bi-exclamation-circle', err.message || 'Export failed');
                })
                .finally(function() {
                    self.exportExcelLoading = false;
                });
            },
            showToast: function(icon, text) {
                this.toast = { icon: icon, text: text };
                var self = this;
                setTimeout(function() { self.toast = null; }, 2500);
            }
        }
    });
})();
