/* ============================================================
   MetaLab Common JS — 全站共享脚本
   ============================================================ */
(function () {
    'use strict';

    // ---- Shared utils (exposed to other scripts via window.MetaLab) ----
    window.MetaLab = window.MetaLab || {};
    var toastTimer = null;
    window.MetaLab.toast = function (el, msg, isError) {
        if (!el) return;
        clearTimeout(toastTimer);
        el.textContent = msg;
        el.className = 'toast' + (isError ? ' error' : '');
        void el.offsetWidth;
        el.classList.add('show');
        toastTimer = setTimeout(function () {
            el.classList.remove('show');
        }, 3000);
    };

    // ---- CSRF token helper (从共享 utils.js 提供的 getCSRFToken 别名) ----
    window.MetaLab.csrfToken = typeof getCSRFToken === 'function' ? getCSRFToken : function () { return ''; };

    // ---- Auto-attach X-CSRF-Token to all state-changing requests ----
    // Monkey-patch XMLHttpRequest and fetch to inject CSRF header
    // Also intercept 401 responses to auto-refresh token
    (function () {
        var SAME_ORIGIN = /^\/(?!\/)/;
        var isRefreshing = false;
        var refreshPromise = null;
        var pendingRetries = [];

        // 优先从 cookie 读取 CSRF token（与服务端验证源一致），meta 标签作为后备
        function resolveCSRFToken() {
            var cookieMatch = document.cookie.match(/(?:^|;\s*)mlb_csrf=([^;]*)/);
            if (cookieMatch && cookieMatch[1]) return cookieMatch[1];
            var meta = document.querySelector('meta[name="csrf-token"]');
            return meta ? meta.getAttribute('content') : '';
        }

        function getCSRFTokenHeader() {
            var t = resolveCSRFToken();
            return t || window.MetaLab.csrfToken();
        }

        // ---- Token refresh logic ----
        function doRefresh() {
            if (isRefreshing) return refreshPromise;
            isRefreshing = true;
            refreshPromise = fetch('/api/auth/refresh', { method: 'POST' })
                .then(function (res) {
                    isRefreshing = false;
                    refreshPromise = null;
                    if (!res.ok) {
                        // Refresh failed — clear all pending retries
                        while (pendingRetries.length) {
                            var r = pendingRetries.shift();
                            r.reject(new Error('refresh_failed'));
                        }
                        return Promise.reject(new Error('refresh_failed'));
                    }
                    // Retry all pending requests
                    while (pendingRetries.length) {
                        var retry = pendingRetries.shift();
                        retry.retry();
                    }
                    return true;
                })
                .catch(function (err) {
                    isRefreshing = false;
                    refreshPromise = null;
                    while (pendingRetries.length) {
                        var r2 = pendingRetries.shift();
                        r2.reject(err);
                    }
                    return Promise.reject(err);
                });
            return refreshPromise;
        }

        // ---- Patch XMLHttpRequest ----
        var origXHROpen = XMLHttpRequest.prototype.open;
        var origXHRSend = XMLHttpRequest.prototype.send;
        XMLHttpRequest.prototype.open = function (method, url) {
            this._method = method;
            this._url = url;
            return origXHROpen.apply(this, arguments);
        };
        XMLHttpRequest.prototype.send = function () {
            var xhr = this;
            if (SAME_ORIGIN.test(xhr._url) &&
                xhr._method && !/^(GET|HEAD|OPTIONS)$/i.test(xhr._method)) {
                xhr.setRequestHeader('X-CSRF-Token', getCSRFTokenHeader());
            }

            // 401 interception for XHR
            // 保存原始 onreadystatechange 后立即清除，防止原生属性重复触发
            // 否则浏览器原生 onreadystatechange 和 addEventListener 监听器会各触发一次
            // 导致 Vditor 图片上传等场景下图片被插入两次
            var origOnReady = xhr.onreadystatechange;
            xhr.onreadystatechange = null;
            xhr.addEventListener('readystatechange', function () {
                if (xhr.readyState === 4 && xhr.status === 401 &&
                    xhr._url !== '/api/auth/refresh' &&
                    !xhr._retried) {
                    xhr._retried = true;
                    // Abort the original response handling
                    xhr._blocked = true;

                    doRefresh().then(function () {
                        // Re-create and re-send the request
                        var newXhr = new XMLHttpRequest();
                        newXhr.open(xhr._method, xhr._url, true);
                        // Copy relevant properties
                        newXhr.onreadystatechange = origOnReady;
                        newXhr.setRequestHeader('X-CSRF-Token', getCSRFTokenHeader());
                        newXhr.send(xhr._body);
                    }).catch(function () {
                        // Refresh failed, trigger original error handler
                        xhr._blocked = false;
                        if (origOnReady) origOnReady.call(xhr);
                    });
                }
                if (!xhr._blocked && origOnReady) {
                    origOnReady.call(xhr);
                }
            });

            // Store body for potential retry
            if (xhr._method && !/^(GET|HEAD)$/i.test(xhr._method)) {
                xhr._body = arguments[0];
            }
            return origXHRSend.apply(xhr, arguments);
        };

        // ---- Patch fetch with 401 interceptor ----
        var origFetch = window.fetch;
        window.fetch = function (url, options) {
            options = options || {};
            var headers = options.headers || {};
            var method = (options.method || 'GET').toUpperCase();
            var urlStr = (typeof url === 'string') ? url : '';

            if (SAME_ORIGIN.test(urlStr) && !/^(GET|HEAD|OPTIONS)$/i.test(method)) {
                if (headers instanceof Headers) {
                    headers.set('X-CSRF-Token', getCSRFTokenHeader());
                } else {
                    headers['X-CSRF-Token'] = getCSRFTokenHeader();
                }
                options.headers = headers;
            }

            // Don't intercept the refresh request itself
            if (urlStr === '/api/auth/refresh') {
                return origFetch(url, options);
            }

            return origFetch(url, options).then(function (res) {
                if (res.status === 401) {
                    // Clone the response so we can read it once for logging
                    var cloned = res.clone();

                    // Queue this request for retry after refresh
                    return new Promise(function (resolve, reject) {
                        pendingRetries.push({
                            retry: function () {
                                // Re-fetch with updated CSRF token
                                var retryOpts = Object.assign({}, options);
                                var retryHeaders = retryOpts.headers || {};
                                if (retryHeaders instanceof Headers) {
                                    retryHeaders.set('X-CSRF-Token', getCSRFTokenHeader());
                                } else {
                                    retryHeaders['X-CSRF-Token'] = getCSRFTokenHeader();
                                }
                                retryOpts.headers = retryHeaders;
                                resolve(origFetch(url, retryOpts));
                            },
                            reject: function (err) {
                                reject(err);
                            }
                        });
                        doRefresh();
                    });
                }
                return res;
            });
        };
    })();

    var menuBtn = document.getElementById('mobileMenuBtn');
    var navLinks = document.getElementById('navLinks');
    var scrollBtn = document.getElementById('scrollTopBtn');

    var menuIcon = '<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>';
    var closeIcon = '<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>';

    // ---- Mobile menu toggle ----
    if (menuBtn && navLinks) {
        menuBtn.addEventListener('click', function () {
            navLinks.classList.toggle('active');
            menuBtn.innerHTML = navLinks.classList.contains('active') ? closeIcon : menuIcon;
        });
    }

    // ---- Close mobile menu on nav click ----
    var links = document.querySelectorAll('.nav-links a');
    for (var i = 0; i < links.length; i++) {
        links[i].addEventListener('click', function () {
            if (navLinks) {
                navLinks.classList.remove('active');
            }
            if (menuBtn) {
                menuBtn.innerHTML = menuIcon;
            }
        });
    }

    // ---- Smooth scroll for anchor links ----
    var anchors = document.querySelectorAll('a[href^="#"]');
    for (var j = 0; j < anchors.length; j++) {
        anchors[j].addEventListener('click', function (e) {
            var href = this.getAttribute('href');
            if (href === '#') return;
            var target = document.querySelector(href);
            if (target) {
                e.preventDefault();
                window.scrollTo({ top: target.offsetTop - 55, behavior: 'smooth' });
            }
        });
    }

    // ---- Scroll-to-top button ----
    if (scrollBtn) {
        window.addEventListener('scroll', function () {
            scrollBtn.classList.toggle('visible', window.scrollY > window.innerHeight * 0.5);
        });
        scrollBtn.addEventListener('click', function () {
            window.scrollTo({ top: 0, behavior: 'smooth' });
        });
    }

    // ---- Dev greeting ----
    console.log('%c🔨 嘿，开发者朋友！', 'color:#2ecc71;font-size:18px;font-weight:bold');
    console.log('%c欢迎来到 MetaLab 的蓝图页。', 'color:#34495e');
    console.log('%c我们正在搭建一个纯净、友好的下一代开发者社区。', 'color:#34495e');
    console.log('%c有任何想法或愿意参与早期测试？欢迎联系我们：metazone@foxmail.com', 'color:#e74c3c;font-style:italic');

    // ---- Logout ----
    var logoutBtn = document.getElementById('logoutBtn');
    if (logoutBtn) {
        logoutBtn.addEventListener('click', function () {
            var xhr = new XMLHttpRequest();
            xhr.open('POST', '/api/auth/logout', true);
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    window.location.href = '/';
                }
            };
            xhr.send();
        });
    }

    // ---- Unread message badge polling ----
    var msgBadge = document.getElementById('msgBadge');
    if (msgBadge) {
        var POLL_INTERVAL = 60 * 1000; // 1 minute
        function pollUnread() {
            fetch('/api/messages/unread')
                .then(function (res) {
                    if (!res.ok) return;
                    return res.json();
                })
                .then(function (data) {
                    if (!data || !data.success) return;
                    var count = data.data && data.data.unread ? data.data.unread : 0;
                    msgBadge.textContent = count > 99 ? '99+' : count;
                    msgBadge.style.display = count > 0 ? 'flex' : 'none';
                })
                .catch(function () {});
        }
        pollUnread();
        setInterval(pollUnread, POLL_INTERVAL);
    }

    // ---- Auto-refresh token (silent) ----
    // 场景 A：页面开着时，每 10 分钟静默续期（保持 access token 不过期）
    // 场景 B：关浏览器 15+ min 后回来，access token 过期但 refresh 仍有效
    //         → 页面渲染为未登录 → 刷新成功后 reload 一次获得登录态
    //         → 仅当页面是未登录状态（无 logoutBtn）时才触发 reload
    // 场景 C：编辑器等页面发 API 请求时遇到 401 → 由 fetch/XHR patch 自动刷新后重试
    // 不在认证页面执行刷新（登录/注册页无需续期）
    var onAuthPage = /^\/auth\//.test(window.location.pathname);
    if (!onAuthPage) {

    var REFRESH_INTERVAL = 10 * 60 * 1000; // 10 minutes
    var refreshTimer = null;

    function tryRefresh(callback) {
        fetch('/api/auth/refresh', { method: 'POST' })
            .then(function (res) {
                if (res.ok) {
                    if (callback) callback();
                } else {
                    if (refreshTimer) {
                        clearInterval(refreshTimer);
                        refreshTimer = null;
                    }
                }
            })
            .catch(function () {
                if (refreshTimer) {
                    clearInterval(refreshTimer);
                    refreshTimer = null;
                }
            });
    }

    // 启动定时刷新：只要用户已登录（有 logoutBtn 元素），就定期刷新
    if (document.getElementById('logoutBtn')) {
        // 页面已经是登录态，启动定时刷新即可，无需 reload
        tryRefresh(function () {
            refreshTimer = setInterval(function () { tryRefresh(null); }, REFRESH_INTERVAL);
        });
    } else {
        // 场景 B：页面渲染为未登录（无 logoutBtn），但 refresh token 可能仍有效
        // 尝试刷新一次，成功后 reload 页面获取登录态
        // 使用 sessionStorage 防止死循环（reload 后再次进入此分支不会再 reload）
        if (!sessionStorage.getItem('mlb_refreshed')) {
            sessionStorage.setItem('mlb_refreshed', '1');
            tryRefresh(function () {
                window.location.reload();
            });
        }
    }

    } // end if (!onAuthPage)
})();
