/* App initialization — route registration and global state */
const App = {
    /** Show the "Last Result" nav link pointing to a scan detail or compare view. */
    setLastResult(scanId) {
        if (!scanId) return;
        localStorage.setItem('comply_last_scan', scanId);

        // Check if we now have a compare pair
        if (typeof ScanAdapter !== 'undefined') {
            const pair = this._findComparePair(scanId);
            if (pair) {
                localStorage.setItem('comply_last_compare', JSON.stringify(pair));
                this._showLastResultLink(null, pair);
                return;
            }
        }

        localStorage.removeItem('comply_last_compare');
        this._showLastResultLink(scanId);
    },

    /** Find a structure+semantic pair for the given scan ID. */
    _findComparePair(scanId) {
        if (typeof ScanAdapter === 'undefined') return null;
        return ScanAdapter.findComparePair(scanId);
    },

    _showLastResultLink(scanId, comparePair) {
        const li = document.getElementById('nav-last-result');
        if (!li) return;
        const a = li.querySelector('a');
        if (a) {
            if (comparePair) {
                a.href = `#/diff/${comparePair.structureId}/${comparePair.semanticId}`;
                a.textContent = 'Compare';
            } else {
                a.href = `#/detail/${scanId}`;
                a.textContent = 'Results';
            }
        }
        li.style.display = '';
    },

    /** Initialize the repo sidebar (demo mode only). */
    initSidebar() {
        if (typeof ScanAdapter === 'undefined') return;
        const sidebar = document.getElementById('repo-sidebar');
        const toggle = document.getElementById('sidebar-toggle');
        if (!sidebar) return;

        sidebar.style.display = '';
        if (toggle) toggle.style.display = '';

        // Add grid class to content area
        const contentArea = sidebar.parentElement;
        if (contentArea) contentArea.classList.add('app-layout-with-sidebar');

        this.refreshSidebar();

        // Highlight active fw-tile on route changes
        window.addEventListener('hashchange', () => this.highlightCurrentRoute());
    },

    /** Refresh the sidebar repo list. */
    refreshSidebar() {
        if (typeof ScanAdapter === 'undefined') return;
        const list = document.getElementById('repo-sidebar-list');
        if (!list) return;

        const repos = ScanAdapter.listRepos();
        const userRepos = repos.filter(r => r.source === 'user');
        const demoRepos = repos.filter(r => r.source === 'demo');

        let html = '';

        if (userRepos.length > 0) {
            html += '<div class="repo-sidebar-divider">Your Scans</div>';
            for (const repo of userRepos) {
                html += this._renderSidebarItem(repo);
            }
        }

        if (demoRepos.length > 0) {
            html += '<div class="repo-sidebar-divider">Demo Repos</div>';
            for (const repo of demoRepos) {
                html += this._renderSidebarItem(repo);
            }
        }

        list.innerHTML = html || '<div style="padding:16px;color:var(--text-muted);font-size:13px">No scans yet</div>';

        // Render sidebar footer (clear button + privacy notice)
        let footer = document.getElementById('repo-sidebar-footer');
        if (!footer) {
            footer = document.createElement('div');
            footer.id = 'repo-sidebar-footer';
            footer.className = 'repo-sidebar-footer';
            const sidebar = document.getElementById('repo-sidebar');
            if (sidebar) sidebar.appendChild(footer);
        }
        const hasUserScans = userRepos.length > 0;
        footer.innerHTML = `
            ${hasUserScans ? '<button class="sidebar-clear-btn" onclick="App.clearMyScans()">Clear My Scans</button>' : ''}
            <div class="sidebar-privacy-notice">Scan results encrypted in your browser. No plaintext data on our servers.</div>
        `;

        // Highlight the tile matching current route
        this.highlightCurrentRoute();
    },

    /** Delete a single scan by id. */
    async deleteScan(id, event) {
        if (event) { event.stopPropagation(); event.preventDefault(); }
        if (typeof ScanAdapter === 'undefined') return;
        ScanAdapter.remove(id);
        const hash = window.location.hash || '';
        if (hash.includes(id)) {
            window.location.hash = '/landing';
        } else if (hash.includes('/landing') || hash === '' || hash === '#/') {
            const sr = document.getElementById('scan-results');
            const ir = document.getElementById('import-results');
            if (sr) sr.innerHTML = '';
            if (ir) ir.innerHTML = '';
        }
        this.refreshSidebar();
    },

    /** Delete all scans for a repo (by scan ID list). */
    deleteRepoScans(ids) {
        if (!ids || !ids.length) return;
        if (typeof ScanAdapter === 'undefined') return;
        for (const id of ids) ScanAdapter.remove(id);
        const hash = window.location.hash || '';
        if (ids.some(id => hash.includes(id))) {
            window.location.hash = '/landing';
        } else if (hash.includes('/landing') || hash === '' || hash === '#/') {
            // On landing page: clear displayed results since they may belong to deleted scan
            const sr = document.getElementById('scan-results');
            const ir = document.getElementById('import-results');
            if (sr) sr.innerHTML = '';
            if (ir) ir.innerHTML = '';
        }
        this.refreshSidebar();
    },

    /** Clear all visitor scans (server + local). */
    async clearMyScans() {
        if (!confirm('Delete all your scan history?')) return;
        if (typeof UserScans !== 'undefined') {
            await UserScans.clear();
        }
        localStorage.removeItem('comply_last_scan');
        localStorage.removeItem('comply_last_compare');
        const li = document.getElementById('nav-last-result');
        if (li) li.style.display = 'none';
        this.refreshSidebar();
        window.location.hash = '/landing';
    },

    /** Resolve the best view href for a specific repo + framework. */
    _fwHref(repo, fw) {
        if (typeof ScanAdapter === 'undefined') return '#/landing';
        const allScans = ScanAdapter.list();
        const repoScans = allScans.filter(s =>
            (s.repoSlug === repo.slug || (s.url || '').toLowerCase().replace(/\.git$/, '').replace(/\/+$/, '').endsWith(repo.slug)) &&
            s.framework === fw.fw
        );
        const struct = repoScans.find(s => (s.depth || '').includes('structure'));
        const sem = repoScans.find(s => (s.depth || '').includes('semantic'));
        if (struct && sem) return `#/diff/${struct.id}/${sem.id}`;
        const latest = repoScans[0];
        if (latest) return `#/detail/${latest.id}`;
        return '#/landing';
    },

    _renderSidebarItem(repo) {
        const fwTiles = repo.frameworks.map(fw => {
            const href = this._fwHref(repo, fw);
            const label = typeof fwLabel === 'function' ? fwLabel(fw.fw) : fw.fw;
            const score = fw.latestScan ? Math.round(fw.latestScan.score || 0) : null;
            const scoreColor = score !== null
                ? (score >= 70 ? 'var(--green)' : score >= 40 ? 'var(--yellow)' : 'var(--red)')
                : '';
            const scoreHtml = score !== null
                ? `<span class="repo-sidebar-fw-score" style="color:${scoreColor}">${score}%</span>`
                : '';
            const dots = [
                `<span class="repo-sidebar-dot ${fw.hasStructure ? 'structure' : 'missing'}" title="Structure"></span>`,
                `<span class="repo-sidebar-dot ${fw.hasSemantic ? 'semantic' : 'missing'}" title="Semantic"></span>`,
            ].join('');
            return `<a href="${href}" class="repo-sidebar-fw-tile"
                       onclick="event.stopPropagation(); App.highlightSidebarItem(this.closest('.repo-sidebar-item'));">
                       <span class="repo-sidebar-fw-label">${label}</span>
                       <span class="repo-sidebar-fw-right">${scoreHtml}${dots}</span></a>`;
        }).join('');

        // Default href: navigate to first framework's detail view if available
        let defaultHref;
        if (repo.frameworks.length > 0) {
            const fwHref = this._fwHref(repo, repo.frameworks[0]);
            defaultHref = fwHref !== '#/landing' ? fwHref : (repo.source === 'demo' ? '#/landing' : `#/landing?repo=${encodeURIComponent(repo.slug)}`);
        } else {
            defaultHref = repo.source === 'demo' ? '#/landing' : `#/landing?repo=${encodeURIComponent(repo.slug)}`;
        }

        // Repo-level links
        const slug = encodeURIComponent(repo.slug);
        const repoLinks = [];
        if (repo.frameworks.length >= 2) {
            repoLinks.push(`<a href="#/overlap/${slug}" class="repo-sidebar-overlap-link"
                  onclick="event.stopPropagation(); App.highlightSidebarItem(this.closest('.repo-sidebar-item'));">
                  Compare ${repo.frameworks.length} Frameworks</a>`);
        }
        // Count total scans for this repo
        const totalScans = typeof ScanAdapter !== 'undefined'
            ? ScanAdapter.list().filter(s => {
                const sSlug = s.repoSlug || (s.url || '').toLowerCase().replace(/\.git$/, '').replace(/\/+$/, '').replace(/.*\//, '');
                return sSlug === repo.slug;
              }).length
            : 0;
        if (totalScans >= 2) {
            repoLinks.push(`<a href="#/progress/${slug}" class="repo-sidebar-overlap-link"
                  onclick="event.stopPropagation(); App.highlightSidebarItem(this.closest('.repo-sidebar-item'));">
                  Progress (${totalScans} scans)</a>`);
        }
        const linksHtml = repoLinks.length > 0
            ? `<div class="repo-sidebar-links">${repoLinks.join('')}</div>`
            : '';

        // Delete button for user scans: collect scan IDs for this repo
        let deleteBtn = '';
        if (repo.source === 'user' && typeof ScanAdapter !== 'undefined') {
            const scanIds = ScanAdapter.list()
                .filter(s => {
                    const sSlug = s.repoSlug || (s.url || '').toLowerCase().replace(/\.git$/, '').replace(/\/+$/, '').replace(/.*\//, '');
                    return sSlug === repo.slug;
                })
                .map(s => s.id);
            if (scanIds.length > 0) {
                const idsJson = JSON.stringify(scanIds).replace(/"/g, '&quot;');
                deleteBtn = `<button class="repo-sidebar-delete" title="Delete scan${scanIds.length > 1 ? 's' : ''}"
                    onclick="event.stopPropagation(); App.deleteRepoScans(${idsJson});">&times;</button>`;
            }
        }

        return `
        <div class="repo-sidebar-item"
             onclick="window.location.hash='${defaultHref}'; App.highlightCurrentRoute();">
            <div style="flex:1;min-width:0">
                <div class="repo-sidebar-name">${repo.name}${deleteBtn}</div>
                ${fwTiles ? `<div class="repo-sidebar-fw-stack">${fwTiles}</div>` : ''}
                ${linksHtml}
            </div>
        </div>`;
    },

    highlightSidebarItem(el) {
        document.querySelectorAll('.repo-sidebar-item').forEach(item => item.classList.remove('active'));
        document.querySelectorAll('.repo-sidebar-fw-tile').forEach(t => t.classList.remove('active'));
        if (el) el.classList.add('active');
    },

    /** Highlight the sidebar fw-tile matching the current hash route. */
    highlightCurrentRoute() {
        const hash = window.location.hash || '';
        if (!hash) return;
        document.querySelectorAll('.repo-sidebar-item').forEach(i => i.classList.remove('active'));
        document.querySelectorAll('.repo-sidebar-fw-tile').forEach(t => t.classList.remove('active'));

        // Try exact match first
        let matched = false;
        document.querySelectorAll('.repo-sidebar-fw-tile').forEach(tile => {
            if (tile.getAttribute('href') === hash) {
                tile.classList.add('active');
                const item = tile.closest('.repo-sidebar-item');
                if (item) item.classList.add('active');
                matched = true;
            }
        });

        // Fuzzy match: for /diff/ and /detail/ routes, match by repo slug in the scan ID
        if (!matched && (hash.startsWith('#/diff/') || hash.startsWith('#/detail/'))) {
            const scanId = hash.split('/')[2] || '';
            // Extract repo slug from scan ID (e.g., "catalog-bespoketracker-eu_ai_act-semantic-v1" -> "bespoketracker")
            document.querySelectorAll('.repo-sidebar-fw-tile').forEach(tile => {
                const tileHref = tile.getAttribute('href') || '';
                const tileScanId = tileHref.split('/')[2] || '';
                // Match if both scan IDs share the same repo+framework prefix
                // Compare up to the depth segment (structure/semantic)
                const prefix = scanId.replace(/-(?:structure|semantic).*$/, '');
                const tilePrefix = tileScanId.replace(/-(?:structure|semantic).*$/, '');
                if (prefix && tilePrefix && prefix === tilePrefix) {
                    tile.classList.add('active');
                    const item = tile.closest('.repo-sidebar-item');
                    if (item) item.classList.add('active');
                    matched = true;
                }
            });
        }
    },

    openScanForm() {
        window.location.hash = '/landing';
    },

    toggleSidebar() {
        const sidebar = document.getElementById('repo-sidebar');
        if (sidebar) sidebar.classList.toggle('open');
    },

    /** Keyboard navigation for sidebar: Up/Down to move, Enter to select. */
    _initKeyboardNav() {
        document.addEventListener('keydown', (e) => {
            // Only when sidebar is visible and no input focused
            const sidebar = document.getElementById('repo-sidebar');
            if (!sidebar || sidebar.style.display === 'none') return;
            const activeEl = document.activeElement;
            if (activeEl && (activeEl.tagName === 'INPUT' || activeEl.tagName === 'TEXTAREA' || activeEl.tagName === 'SELECT')) return;

            const items = [...sidebar.querySelectorAll('.repo-sidebar-item')];
            if (items.length === 0) return;

            const current = sidebar.querySelector('.repo-sidebar-item.active');
            const idx = current ? items.indexOf(current) : -1;

            if (e.key === 'ArrowDown' || e.key === 'j') {
                e.preventDefault();
                const next = items[Math.min(idx + 1, items.length - 1)];
                if (next) {
                    items.forEach(i => i.classList.remove('active'));
                    next.classList.add('active');
                    next.scrollIntoView({ block: 'nearest' });
                }
            } else if (e.key === 'ArrowUp' || e.key === 'k') {
                e.preventDefault();
                const prev = items[Math.max(idx - 1, 0)];
                if (prev) {
                    items.forEach(i => i.classList.remove('active'));
                    prev.classList.add('active');
                    prev.scrollIntoView({ block: 'nearest' });
                }
            } else if (e.key === 'Enter') {
                if (current) {
                    e.preventDefault();
                    current.click();
                }
            }
        });
    },

    /** Restore "Last Result" link on page load. */
    async restoreLastResult() {
        // In demo mode, use ScanAdapter (covers both catalog and user scans)
        if (typeof ScanAdapter !== 'undefined') {
            const savedPair = localStorage.getItem('comply_last_compare');
            if (savedPair) {
                try {
                    const pair = JSON.parse(savedPair);
                    if (ScanAdapter.get(pair.structureId) && ScanAdapter.get(pair.semanticId)) {
                        this._showLastResultLink(null, pair);
                        return;
                    }
                } catch (e) {}
            }
            const scans = ScanAdapter.list();
            if (scans.length > 0) {
                const pair = this._findComparePair(scans[0].id);
                if (pair) {
                    localStorage.setItem('comply_last_compare', JSON.stringify(pair));
                    this._showLastResultLink(null, pair);
                    return;
                }
                this._showLastResultLink(scans[0].id);
            }
            // No scans at all: show nothing
            return;
        }
        const saved = localStorage.getItem('comply_last_scan');
        if (saved) {
            this._showLastResultLink(saved);
            return;
        }
        // Non-demo: check server history for the most recent
        try {
            const history = await complyApi.getHistory(null, null, 1);
            if (history.length > 0) {
                const id = history[0].id;
                localStorage.setItem('comply_last_scan', id);
                this._showLastResultLink(id);
            }
        } catch (e) { /* ignore */ }
    },
};

(function() {
    // Register routes
    Router.on('/landing', () => HomeView.render());
    Router.on('/demo', () => DemoView.render());
    Router.on('/audit', () => AuditView.render());
    Router.on('/scan', () => ScanView.render());
    Router.on('/history', () => HistoryView.render());
    Router.on('/detail', (params) => DetailView.render(params));
    Router.on('/trends', () => TrendsView.render());
    Router.on('/mapping', () => MappingView.render());
    Router.on('/forecast', () => ForecastView.render());
    Router.on('/gate', () => GateView.render());
    Router.on('/monitor', () => MonitorView.render());
    Router.on('/adapters', () => AdaptersView.render());
    Router.on('/diff', (params) => {
        if (typeof CompareView !== 'undefined' && typeof ScanAdapter !== 'undefined') {
            CompareView.render(params);
        } else {
            DiffView.render(params);
        }
    });
    Router.on('/settings', () => SettingsView.render());
    Router.on('/overlap', (params) => OverlapView.render(params));
    Router.on('/progress', (params) => ProgressView.render(params));

    // Load global state
    async function initApp() {
        // Initialize ScanAdapter (loads catalog + migrates old store)
        if (typeof ScanAdapter !== 'undefined') {
            await ScanAdapter.init();
        }

        try {
            const health = await complyApi.getHealth();
            const vBadge = document.getElementById('version-badge');
            if (vBadge && health.version) vBadge.textContent = `v${health.version}`;
        } catch (e) { /* ignore */ }

        try {
            const tier = await complyApi.getTier();
            const tBadge = document.getElementById('tier-badge');
            if (tBadge && tier.tier) tBadge.textContent = tier.tier;
            // Self-hosted: show "Self-Hosted" when not managed and on free tier
            if (tBadge && tier.tier === 'Free' && !tier.managed) tBadge.textContent = 'Self-Hosted';
        } catch (e) { /* ignore */ }

        // Check demo mode -- switch default route to landing
        let isDemoMode = false;
        try {
            const demoConfig = await complyApi._fetch('/demo/config');
            if (demoConfig.demo_mode) {
                isDemoMode = true;
                document.body.classList.add('demo-mode');
                Router.setDefaultRoute('/landing');
                // In demo mode, landing uses LandingView (not HomeView)
                Router.on('/landing', () => LandingView.render());
                // Route /scan and /history to landing in demo mode
                Router.on('/scan', () => LandingView.render());
                Router.on('/history', () => LandingView.render());
                // Hide internal nav items (belt-and-suspenders; CSS hides entire sidebar)
                document.querySelectorAll('[data-demo-hide]').forEach(el => el.style.display = 'none');
            }
        } catch (e) { /* ignore */ }

        if (!isDemoMode) {
            App.restoreLastResult();
        }

        // Initialize sidebar and keyboard nav in demo mode
        if (isDemoMode) {
            App.initSidebar();
            App._initKeyboardNav();
        }
    }

    // Start — await init so demo mode can set default route before router fires
    initApp().then(() => Router.start());
})();
